summaryrefslogblamecommitdiffstats
path: root/innbbsd/connectsock.c
blob: 0dd32b032e9fbd58d8e2064d9e67d896a3eda11b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                
                   
                  



                       



                       
                        


            
                        
 
                          

 



                      
 



                                                          

 


                      
 
                     

 

                                   
                        
 
                      


 
     

                       
 






                                                                                   

 
                                 
                              
 
    
                         
                                      



                    


                      
 





                                                      

 


                      
 



                          


 
   
                              

                             
 



                                                                



















                                                                               


                               
                            

                              








                                                                              

 
   


                                 
 
                                                               






















                                                                            
         
















                                                                                         




                               






                                                                             
            




                                                       
      
             

 




                                           
 









                                                                
         


                                                          

 




                                           
 












                                                                
         


                                                          

 





                                                         
 












                                                                
         




                                                          
                  
                             
      
         





                                        


 


                      
 

                       

                                                               

                  
                                       
      




                                            

 




                                             
 
                      












                                              
                  
                             
      

                     
                  
                                     
      









                                            
         


                  

 




                                     
 






















                                                                            
         










                                                                        
         















                                                                                         
                                 









                                                                     
 
             
 
#include "bbs.h"
#include <stdlib.h>
#include "osdep.h"
#include "innbbsconf.h"
#include "daemon.h"
#include <signal.h>
#include <setjmp.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "externs.h"
static jmp_buf  timebuf;

static void
timeout(sig)
    int             sig;
{
    longjmp(timebuf, sig);
}

extern int      errno;
static void 
reapchild(s)
    int             s;
{
    int             state;
    while (waitpid(-1, &state, WNOHANG | WUNTRACED) > 0) {
    /* printf("reaping child\n"); */
    }
}

void 
dokill(s)
    int             s;
{
    kill(0, SIGKILL);
}

static          int INETDstart = 0;
void 
startfrominetd(int flag)
{
    INETDstart = flag;
}


void 
standalonesetup(fd)
    int             fd;
{
    int             on = 1;
    struct linger   foobar;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
    syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
    foobar.l_onoff = 0;
    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&foobar, sizeof(foobar)) < 0)
    syslog(LOG_ERR, "setsockopt (SO_LINGER): %m");
}

static char    *UNIX_SERVER_PATH;
static int      (*halt) (int);

void
sethaltfunction(haltfunc)
    int             (*haltfunc) (int);
{
    halt = haltfunc;
}

void 
docompletehalt(s)
    int             s;
{
    /*
     * printf("try to remove %s\n", UNIX_SERVER_PATH);
     * unlink(UNIX_SERVER_PATH);
     */
    exit(0);
    /* dokill(); */
}

void 
doremove(s)
    int             s;
{
    if (halt != NULL)
    (*halt) (s);
    else
    docompletehalt(s);
}


int
initunixserver(path, protocol)
    char           *path;
    char           *protocol;
{
    struct sockaddr_un s_un;
    /* unix endpoint address */
    struct protoent *pe;    /* protocol information entry */
    int             s;

    bzero((char *)&s_un, sizeof(s_un));
    s_un.sun_family = AF_UNIX;
    strcpy(s_un.sun_path, path);
    if (protocol == NULL)
    protocol = "tcp";
    /* map protocol name to protocol number */
    pe = getprotobyname(protocol);
    if (pe == NULL) {
    fprintf(stderr, "%s: Unknown protocol.\n", protocol);
    return (-1);
    }
    /* Allocate a socket */
    s = socket(PF_UNIX, strcmp(protocol, "tcp") ? SOCK_DGRAM : SOCK_STREAM, 0);
    if (s < 0) {
    printf("protocol %d\n", pe->p_proto);
    perror("socket");
    return -1;
    }
    /* standalonesetup(s); */
    Signal(SIGHUP, SIG_IGN);
    Signal(SIGUSR1, SIG_IGN);
    Signal(SIGCHLD, reapchild);
    UNIX_SERVER_PATH = path;
    Signal(SIGINT, doremove);
    Signal(SIGTERM, doremove);

    chdir("/");
    if (bind(s, (struct sockaddr *) & s_un, sizeof(struct sockaddr_un)) < 0) {
    perror("bind");
    perror(path);
    return -1;
    }
    listen(s, 10);
    return s;
}

int
initinetserver(service, protocol)
    char           *service;
    char           *protocol;
{
    struct servent *se;     /* service information entry */
    struct protoent *pe;    /* protocol information entry */
    struct sockaddr_in sin; /* Internet endpoint address */
    int             port, s;
    int             randomport = 0;

    bzero((char *)&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    if (!strcmp("0", service)) {
    randomport = 1;
    sin.sin_addr.s_addr = INADDR_ANY;
    }
    if (service == NULL)
    service = DEFAULTPORT;
    if (protocol == NULL)
    protocol = "tcp";
    /* map service name to port number */
    /* service ---> port */
    se = getservbyname(service, protocol);
    if (se == NULL) {
    port = htons((u_short) atoi(service));
    if (port == 0 && !randomport) {
        fprintf(stderr, "%s/%s: Unknown service.\n", service, protocol);
        return (-1);
    }
    } else
    port = se->s_port;
    sin.sin_port = port;

    /* map protocol name to protocol number */
    pe = getprotobyname(protocol);
    if (pe == NULL) {
    fprintf(stderr, "%s: Unknown protocol.\n", protocol);
    return (-1);
    }
    /* Allocate a socket */
    s = socket(PF_INET, strcmp(protocol, "tcp") ? SOCK_DGRAM : SOCK_STREAM, pe->p_proto);
    if (s < 0) {
    perror("socket");
    return -1;
    }
    standalonesetup(s);
    Signal(SIGHUP, SIG_IGN);
    Signal(SIGUSR1, SIG_IGN);
    Signal(SIGCHLD, reapchild);
    Signal(SIGINT, dokill);
    Signal(SIGTERM, dokill);

    chdir("/");
    if (bind(s, (struct sockaddr *) & sin, sizeof(struct sockaddr_in)) < 0) {
    perror("bind");
    return -1;
    }
    listen(s, 10);
#ifdef DEBUG
    {
    int             length = sizeof(sin);
    getsockname(s, &sin, &length);
    printf("portnum alocalted %d\n", sin.sin_port);
    }
#endif
    return s;
}

int 
open_unix_listen(path, protocol, initfunc)
    char           *path;
    char           *protocol;
    int             (*initfunc) ARG((int));
{
    int             s;
    s = initunixserver(path, protocol);
    if (s < 0) {
    return -1;
    }
    if (initfunc != NULL) {
    printf("in inetsingleserver before initfunc s %d\n", s);
    if ((*initfunc) (s) < 0) {
        perror("initfunc error");
        return -1;
    }
    printf("end inetsingleserver before initfunc \n");
    }
    return s;
}

int 
open_listen(service, protocol, initfunc)
    char           *service;
    char           *protocol;
    int             (*initfunc) ARG((int));
{
    int             s;
    if (!INETDstart)
    s = initinetserver(service, protocol);
    else
    s = 0;
    if (s < 0) {
    return -1;
    }
    if (initfunc != NULL) {
    printf("in inetsingleserver before initfunc s %d\n", s);
    if ((*initfunc) (s) < 0) {
        perror("initfunc error");
        return -1;
    }
    printf("end inetsingleserver before initfunc \n");
    }
    return s;
}

int 
inetsingleserver(service, protocol, serverfunc, initfunc)
    char           *service;
    char           *protocol;
    int             (*initfunc) ARG((int));
    int             (*serverfunc) ARG((int));
{
    int             s;
    if (!INETDstart)
    s = initinetserver(service, protocol);
    else
    s = 0;
    if (s < 0) {
    return -1;
    }
    if (initfunc != NULL) {
    printf("in inetsingleserver before initfunc s %d\n", s);
    if ((*initfunc) (s) < 0) {
        perror("initfunc error");
        return -1;
    }
    printf("end inetsingleserver before initfunc \n");
    } {
    int             ns = tryaccept(s);
    int             result = 0;
    if (ns < 0 && errno != EINTR) {
#ifdef DEBUGSERVER
        perror("accept");
#endif
    }
    close(s);
    if (serverfunc != NULL)
        result = (*serverfunc) (ns);
    close(ns);
    return (result);
    }
}


int 
tryaccept(s)
    int             s;
{
    int             ns;
    socklen_t fromlen;
    struct sockaddr sockaddr;   /* Internet endpoint address */
    fromlen = sizeof(struct sockaddr_in);

#ifdef DEBUGSERVER
    fputs("Listening again\n", stdout);
#endif
    do {
    ns = accept(s, &sockaddr, &fromlen);
    errno = 0;
    } while (ns < 0 && errno == EINTR);
    return ns;
}

int 
inetserver(service, protocol, serverfunc)
    char           *service;
    char           *protocol;
    int             (*serverfunc) ARG((int));
{
    int             s;

    if (!INETDstart)
    s = initinetserver(service, protocol);
    else
    s = 0;
    if (s < 0) {
    return -1;
    }
    for (;;) {
    int             ns = tryaccept(s);
    int             result = 0;
    int             pid;
    if (ns < 0 && errno != EINTR) {
#ifdef DEBUGSERVER
        perror("accept");
#endif
        continue;
    }
#ifdef DEBUGSERVER
    fputs("Accept OK\n", stdout);
#endif
    pid = fork();
    if (pid == 0) {
        close(s);
        if (serverfunc != NULL)
        result = (*serverfunc) (ns);
        close(ns);
        exit(result);
    } else if (pid < 0) {
        perror("fork");
        return -1;
    }
    close(ns);
    }
    return 0;
}

int 
inetclient(server, service, protocol)
    char           *server;
    char           *protocol;
    char           *service;
{
    struct servent *se;     /* service information entry */
    struct hostent *he;     /* host information entry */
    struct protoent *pe;    /* protocol information entry */
    struct sockaddr_in sin; /* Internet endpoint address */
    int             port, s;

    bzero((char *)&sin, sizeof(sin));
    sin.sin_family = AF_INET;

    if (service == NULL)
    service = DEFAULTPORT;
    if (protocol == NULL)
    protocol = "tcp";
    if (server == NULL)
    server = DEFAULTSERVER;
    /* map service name to port number */
    /* service ---> port */
    se = getservbyname(service, protocol);
    if (se == NULL) {
    port = htons((u_short) atoi(service));
    if (port == 0) {
        fprintf(stderr, "%s/%s: Unknown service.\n", service, protocol);
        return (-1);
    }
    } else
    port = se->s_port;
    sin.sin_port = port;

    /* map server hostname to IP address, allowing for dotted decimal */
    he = gethostbyname(server);
    if (he == NULL) {
    sin.sin_addr.s_addr = inet_addr(server);
    if (sin.sin_addr.s_addr == INADDR_NONE) {
        fprintf(stderr, "%s: Unknown host.\n", server);
        return (-1);
    }
    } else
    bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);

    /* map protocol name to protocol number */
    pe = getprotobyname(protocol);
    if (pe == NULL) {
    fprintf(stderr, "%s: Unknown protocol.\n", protocol);
    return (-1);
    }
    /* Allocate a socket */
    s = socket(PF_INET, strcmp(protocol, "tcp") ? SOCK_DGRAM : SOCK_STREAM, pe->p_proto);
    if (s < 0) {
    perror("socket");
    return -1;
    }
    if (setjmp(timebuf) == 0) {
    Signal(SIGALRM, timeout);
    alarm(5);
    if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
        alarm(0);
        return -1;
    }
    } else {
    alarm(0);
    return -1;
    }
    alarm(0);

    return s;
}