#include "innbbsconf.h" #include "daemon.h" #include #include 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 INETDstart = 0; int startfrominetd(flag) { INETDstart = flag ; } int 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)(); sethaltfunction(haltfunc) int (*haltfunc)(); { 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); } initunixserver(path, protocol) char *path; char *protocol; { struct sockaddr_un s_un; /* unix endpoint address */ struct protoent *pe; /*protocol information entry*/ int s; char *ptr; 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; } initinetserver(service,protocol) char *service; char *protocol; { 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; 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,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 port,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; } int unixclient(path,protocol) char *path; char *protocol; { struct protoent *pe; /*protocol information entry*/ struct sockaddr_un s_un;/*unix endpoint address*/ int s; bzero((char*)&s_un,sizeof(s_un)); s_un.sun_family= AF_UNIX; if (path==NULL) path=DEFAULTPATH; if (protocol==NULL) protocol="tcp"; strcpy(s_un.sun_path , path); /* 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) { perror("socket"); return -1; } /* Connect the socket to the server */ if (connect(s,(struct sockaddr*)&s_un,sizeof(s_un))<0) { /*perror("connect");*/ return -1; } return s; }