#ifndef lint static char *copyright = "\n\ \n\ Copyright (c) 1993, 1996, 1999 by Bennet Yee.\n\ \n\ This material was developed by the author. Permission to copy this\n\ software, to redistribute it, and to use it for any purpose is hereby\n\ granted, subject to the following five restrictions.\n\ \n\ 1. Any copy made of this software must include this copyright notice in\n\ full.\n\ \n\ 2. All materials containing this software or derivatives thereof must\n\ provide this software in source form or provide a means of obtaining\n\ this software in source form; no fees may be charged for this software\n\ except those for covering media costs and handling.\n\ \n\ 3. All materials developed as a consequence of the use of this software\n\ shall duly acknowledge such use, in accordance with the usual standards\n\ of acknowledging credit in academic research.\n\ \n\ 4. The author makes no warranty or representation that the operation\n\ of this software will be error-free, and the author is under no\n\ obligation to provide any services, by way of maintenance, update, or\n\ otherwise.\n\ \n\ 5. In conjunction with products arising from the use of this material,\n\ there shall be no use of the names of the author, of Carnegie-Mellon\n\ University, nor of any adaptation thereof in any advertising,\n\ promotional, or sales literature without prior written consent from the\n\ author and Carnegie-Mellon University in each case.\n\ \n\ If you have questions, you can contact the author at bsy@cs.cmu.edu\n\ \n\ Users of this software is requested to make their best efforts (a) to\n\ return to the author any improvements or extensions that they make, so\n\ that these may be included in future releases; (b) to document clearly\n\ any improvements or extensions made to this software; and (c) to inform\n\ the author of noteworthy uses of this software. Any improvements or\n\ extensions to this software may be placed under different copyright\n\ restrictions by the author of those improvements or extensions. That\n\ those improvements or extensions be placed under the same copyright as\n\ this software is encouraged.\n\ "; #endif /* lint */ /* * pseudo-inetd -- new sources, not based on Berklix/AT&T code. * * First pass: much more limited that inetd -- no configuration table, * we just listen to a particular tcp socket as specified at the command line * and then run a inetd-style server program with the socket at stdin/out. * * Hacked from my how.to/tcp.client.server/server.c * * 12/13/90, -bsy */ #include #include #include #include #include #include #include #include #include #if !defined(posix_tty) # include #endif #include #include #include #include #if !defined(O_APPEND) # include #endif extern int errno; char *me; #define SERVERPORT 5103 unsigned long servers_allowed = ~0ul; int verbose = 0; reaper() { /* linux / SysV style reenablement, bletch */ #if !defined(USE_SIGSET) (void) signal(SIGCHLD,(void (*)(int)) reaper); #endif if (verbose) write(2,"reaper: ",8); #if defined(_POSIX_VERSION) if (wait((int *) 0) > 0) { ++servers_allowed; if (verbose) write(2,".",1); } #else if (wait((union wait *) 0) > 0) { ++servers_allowed; if (verbose) write(2,".",1); } #endif if (verbose) write(2," reaped\n",8); } usage() { fprintf(stderr,"Usage: %s [-dlv] [-p port] [-c count-to-exit] [-s server-count-limit] [-D descriptor-num] -- cmd [args...]\n",me); } struct dlist { struct dlist *nxt; int d; } def1, def2, def3; main(ac,av) int ac; char **av; { int s, ss; struct sockaddr_in name; int set,i,ch,namelen; #if defined(TIOCNOTTY) int detach; #endif u_long client; u_short port = SERVERPORT; int log = 0, count = -1; struct dlist *dlist = 0, *nd; int alias; extern int getopt(), optind; extern char *optarg; me = strrchr(av[0],'/'); if (!me) me = av[0]; else ++me; #if defined(TIOCNOTTY) detach = 0; #endif while ((ch = getopt(ac,av,"c:lLp:s:d:Dv")) != EOF) switch (ch) { case 'c': count = atoi(optarg); break; case 'l': log = 1; break; case 'L': log = 0; break; case 'p': port = atoi(optarg); break; case 's': servers_allowed = atoi(optarg); break; #if defined(TIOCNOTTY) case 'D': detach = 1; break; #else case 'D': fprintf(stderr,"%s: detach option ignored; POSIX has no way to force a disassociation\n from the control terminal except implicitly through process group\n orphanhood.\n",me); break; #endif case 'd': if (!(nd = (struct dlist *) malloc(sizeof *nd))) { perror(me); fprintf(stderr,"%s: no memory for descriptor list\n",me); exit(1); } nd->nxt = dlist; nd->d = atoi(optarg); dlist = nd; break; case 'v': verbose = 1; break; default: usage(); exit(1); } if (optind >= ac) { usage(); exit(1); } if (!dlist) { dlist = &def1; def1.nxt = &def2; def1.d = 0; def2.nxt = &def3; def2.d = 1; def3.nxt = 0; def3.d = 2; } #if defined(TIOCNOTTY) if (detach) { i = open("/dev/tty",O_RDONLY,0); if (i != -1) { (void) ioctl(i,TIOCNOTTY,(char *) 0); (void) close(i); } } #endif if ((s = socket(PF_INET,SOCK_STREAM,0)) == -1) { perror("socket"); exit(1); } set = 1; if (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(const char *) &set, sizeof(set)) == -1) { perror("setsockoopt"); exit(1); } memset((char *)&name,0,sizeof(name)); name.sin_family = AF_INET; name.sin_port = htons(port); if (bind(s,(struct sockaddr *) &name,sizeof(name)) == -1) { perror("bind"); exit(1); } /* backlogs? how many client at a time? */ if (listen(s,4) == -1) { perror("listen"); exit(1); } #if USE_SIGSET (void) sigset(SIGCHLD,(void (*)(int)) reaper); #else /* linux, bsd */ (void) signal(SIGCHLD,(void (*)(int)) reaper); #endif again: while ((namelen = sizeof name), ((ss = accept(s,(struct sockaddr *)&name,&namelen)) != -1)) { client = name.sin_addr.s_addr; client = ntohl(client); if (verbose) { /* we do not use the other sockaddr info */ fprintf(stderr,"[%d.%d.%d.%d]\n",(client>>24)&0xff,(client>>16)&0xff,(client>>8)&0xff,client&0xff); } if (log) { char buf[256]; sprintf(buf,"netd: Connect on port %d from %d.%d.%d.%d",port,(client>>24)&0xff,(client>>16)&0xff,(client>>8)&0xff,client&0xff); syslog(LOG_INFO | LOG_DAEMON,buf); } /* run prog */ switch (fork()) { case 0: (void) close(s); alias = 0; for (nd = dlist; nd; nd = nd->nxt) { if (nd->d != ss) dup2(ss,nd->d); else ++alias; } if (!alias) (void) close(ss); execvp(av[optind],av+optind); perror("exec"); exit(1); case -1: perror("fork"); exit(1); default: (void) close(ss); --servers_allowed; break; } if (count > 0 && --count == 0) exit(0); while (!servers_allowed) { if (verbose) fprintf(stderr,"Pausing\n"); pause(); if (verbose) fprintf(stderr,"paused, servers_allowed %d\n",servers_allowed); } } if (errno == EINTR) goto again; perror("accept"); exit(1); /* NOTREACHED */ }