summaryrefslogtreecommitdiffstats
path: root/innbbsd/connectsock.c
diff options
context:
space:
mode:
authorin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-03-07 23:13:44 +0800
committerin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-03-07 23:13:44 +0800
commitae31e19f92e717919ac8e3db9039eb38d2b89aae (patch)
treec70164d6a1852344f44b04a653ae2815043512af /innbbsd/connectsock.c
downloadpttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.gz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.bz2
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.lz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.xz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.zst
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.zip
Initial revision
git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'innbbsd/connectsock.c')
-rw-r--r--innbbsd/connectsock.c452
1 files changed, 452 insertions, 0 deletions
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 <signal.h>
+#include <setjmp.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 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;
+}