diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-03-20 19:33:49 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-03-20 19:33:49 +0800 |
commit | 6c7b18b32d87c2a835f7e5c48faac4a8ad44668b (patch) | |
tree | e88e1b2b1007f4ddcd348a4a1bf1d13c515c4564 /daemon/innbbsd/connectsock.c | |
parent | f59699c22c130373cda3cc4cb6fab5bae510bd5a (diff) | |
download | pttbbs-piaip.newlayout.tar pttbbs-piaip.newlayout.tar.gz pttbbs-piaip.newlayout.tar.bz2 pttbbs-piaip.newlayout.tar.lz pttbbs-piaip.newlayout.tar.xz pttbbs-piaip.newlayout.tar.zst pttbbs-piaip.newlayout.zip |
- (internal/exp) first draft of new layoutpiaip.newlayout
git-svn-id: http://opensvn.csie.org/pttbbs/branches/piaip.newlayout@4013 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'daemon/innbbsd/connectsock.c')
-rw-r--r-- | daemon/innbbsd/connectsock.c | 464 |
1 files changed, 464 insertions, 0 deletions
diff --git a/daemon/innbbsd/connectsock.c b/daemon/innbbsd/connectsock.c new file mode 100644 index 00000000..5e526715 --- /dev/null +++ b/daemon/innbbsd/connectsock.c @@ -0,0 +1,464 @@ +#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, 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; +} + +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; +} |