From ae31e19f92e717919ac8e3db9039eb38d2b89aae Mon Sep 17 00:00:00 2001 From: in2 Date: Thu, 7 Mar 2002 15:13:44 +0000 Subject: Initial revision git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- innbbsd/connectsock.c | 452 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 innbbsd/connectsock.c (limited to 'innbbsd/connectsock.c') diff --git a/innbbsd/connectsock.c b/innbbsd/connectsock.c new file mode 100644 index 00000000..71203cfe --- /dev/null +++ b/innbbsd/connectsock.c @@ -0,0 +1,452 @@ +#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; +} -- cgit v1.2.3