summaryrefslogtreecommitdiffstats
path: root/daemon/innbbsd/connectsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/innbbsd/connectsock.c')
-rw-r--r--daemon/innbbsd/connectsock.c464
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;
+}