121134Sdist /* 221134Sdist * Copyright (c) 1983 Regents of the University of California. 321134Sdist * All rights reserved. The Berkeley software License Agreement 421134Sdist * specifies the terms and conditions for redistribution. 521134Sdist */ 621134Sdist 716374Skarels #ifndef lint 821134Sdist char copyright[] = 921134Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1021134Sdist All rights reserved.\n"; 1121134Sdist #endif not lint 1216374Skarels 1321134Sdist #ifndef lint 14*26877Skarels static char sccsid[] = "@(#)inetd.c 5.4 (Berkeley) 03/13/86"; 1521134Sdist #endif not lint 1621134Sdist 1716374Skarels /* 1816374Skarels * Inetd - Internet super-server 1916374Skarels * 2016374Skarels * This program invokes all internet services as needed. 2116374Skarels * connection-oriented services are invoked each time a 2216374Skarels * connection is made, by creating a process. This process 2316374Skarels * is passed the connection as file descriptor 0 and is 2416374Skarels * expected to do a getpeername to find out the source host 2516374Skarels * and port. 2616374Skarels * 2716374Skarels * Datagram oriented services are invoked when a datagram 2816374Skarels * arrives; a process is created and passed a pending message 2916374Skarels * on file descriptor 0. Datagram servers may either connect 3016374Skarels * to their peer, freeing up the original socket for inetd 3116374Skarels * to receive further messages on, or ``take over the socket'', 3216374Skarels * processing all arriving datagrams and, eventually, timing 3316374Skarels * out. The first type of server is said to be ``multi-threaded''; 3416374Skarels * the second type of server ``single-threaded''. 3516374Skarels * 3616374Skarels * Inetd uses a configuration file which is read at startup 3716374Skarels * and, possibly, at some later time in response to a hangup signal. 3816374Skarels * The configuration file is ``free format'' with fields given in the 3916374Skarels * order shown below. Continuation lines for an entry must being with 4016374Skarels * a space or tab. All fields must be present in each entry. 4116374Skarels * 4216374Skarels * service name must be in /etc/services 4316374Skarels * socket type stream/dgram/raw/rdm/seqpacket 4416374Skarels * protocol must be in /etc/protocols 4516374Skarels * wait/nowait single-threaded/multi-threaded 4617346Sbloom * user user to run daemon as 4716374Skarels * server program full path name 4816374Skarels * server program arguments maximum of MAXARGS (5) 4916374Skarels * 5016374Skarels * Comment lines are indicated by a `#' in column 1. 5116374Skarels */ 5216374Skarels #include <sys/param.h> 5316374Skarels #include <sys/stat.h> 5416374Skarels #include <sys/ioctl.h> 5516374Skarels #include <sys/socket.h> 5616374Skarels #include <sys/file.h> 5716374Skarels #include <sys/wait.h> 5816374Skarels 5916374Skarels #include <netinet/in.h> 6016374Skarels #include <arpa/inet.h> 6116374Skarels 6216374Skarels #include <errno.h> 6316374Skarels #include <stdio.h> 6416374Skarels #include <signal.h> 6516374Skarels #include <netdb.h> 6616510Sralph #include <syslog.h> 6717346Sbloom #include <pwd.h> 6816374Skarels 6916374Skarels extern int errno; 7016374Skarels 7116374Skarels int reapchild(); 7216374Skarels char *index(); 7316374Skarels char *malloc(); 7416374Skarels 7516374Skarels int debug = 0; 7625046Skarels int nsock, maxsock; 7725046Skarels fd_set allsock; 7816374Skarels int options; 7916374Skarels struct servent *sp; 8016374Skarels 8116374Skarels struct servtab { 8216374Skarels char *se_service; /* name of service */ 8316374Skarels int se_socktype; /* type of socket to use */ 8416374Skarels char *se_proto; /* protocol used */ 8516374Skarels short se_wait; /* single threaded server */ 8616374Skarels short se_checked; /* looked at during merge */ 8717346Sbloom char *se_user; /* user name to run as */ 88*26877Skarels struct biltin *se_bi; /* if built-in, description */ 8916374Skarels char *se_server; /* server program */ 9016374Skarels #define MAXARGV 5 9116374Skarels char *se_argv[MAXARGV+1]; /* program arguments */ 9216374Skarels int se_fd; /* open descriptor */ 9316374Skarels struct sockaddr_in se_ctrladdr;/* bound address */ 9416374Skarels struct servtab *se_next; 9516374Skarels } *servtab; 9616374Skarels 97*26877Skarels int echo_stream(), discard_stream(), machtime_stream(); 98*26877Skarels int daytime_stream(), chargen_stream(); 99*26877Skarels int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg(); 100*26877Skarels 101*26877Skarels struct biltin { 102*26877Skarels char *bi_service; /* internally provided service name */ 103*26877Skarels int bi_socktype; /* type of socket supported */ 104*26877Skarels short bi_fork; /* 1 if should fork before call */ 105*26877Skarels short bi_wait; /* 1 if should wait for child */ 106*26877Skarels int (*bi_fn)(); /* function which performs it */ 107*26877Skarels } biltins[] = { 108*26877Skarels /* Echo received data */ 109*26877Skarels "echo", SOCK_STREAM, 1, 0, echo_stream, 110*26877Skarels "echo", SOCK_DGRAM, 0, 0, echo_dg, 111*26877Skarels 112*26877Skarels /* Internet /dev/null */ 113*26877Skarels "discard", SOCK_STREAM, 1, 0, discard_stream, 114*26877Skarels "discard", SOCK_DGRAM, 0, 0, discard_dg, 115*26877Skarels 116*26877Skarels /* Return 32 bit time since 1970 */ 117*26877Skarels "time", SOCK_STREAM, 0, 0, machtime_stream, 118*26877Skarels "time", SOCK_DGRAM, 0, 0, machtime_dg, 119*26877Skarels 120*26877Skarels /* Return human-readable time */ 121*26877Skarels "daytime", SOCK_STREAM, 0, 0, daytime_stream, 122*26877Skarels "daytime", SOCK_DGRAM, 0, 0, daytime_dg, 123*26877Skarels 124*26877Skarels /* Familiar character generator */ 125*26877Skarels "chargen", SOCK_STREAM, 1, 0, chargen_stream, 126*26877Skarels "chargen", SOCK_DGRAM, 0, 0, chargen_dg, 127*26877Skarels 0 128*26877Skarels }; 129*26877Skarels 130*26877Skarels #define NUMINT (sizeof(intab) / sizeof(struct inent)) 13116374Skarels char *CONFIG = "/etc/inetd.conf"; 132*26877Skarels char **Argv; 133*26877Skarels char *LastArg; 13416374Skarels 135*26877Skarels main(argc, argv, envp) 13616374Skarels int argc; 137*26877Skarels char *argv[], *envp[]; 13816374Skarels { 13916374Skarels register struct servtab *sep; 14017346Sbloom register struct passwd *pwd; 14116374Skarels char *cp, buf[50]; 14216374Skarels int pid, i; 14316374Skarels 144*26877Skarels Argv = argv; 145*26877Skarels if (envp == 0 || *envp == 0) 146*26877Skarels envp = argv; 147*26877Skarels while (*envp) 148*26877Skarels envp++; 149*26877Skarels LastArg = envp[-1] + strlen(envp[-1]); 15016374Skarels argc--, argv++; 15116374Skarels while (argc > 0 && *argv[0] == '-') { 15216374Skarels for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 15316374Skarels 15416374Skarels case 'd': 15516374Skarels debug = 1; 15616374Skarels options |= SO_DEBUG; 15716374Skarels break; 15816374Skarels 15916374Skarels default: 16016374Skarels fprintf(stderr, 16116374Skarels "inetd: Unknown flag -%c ignored.\n", *cp); 16216374Skarels break; 16316374Skarels } 16416374Skarels nextopt: 16516374Skarels argc--, argv++; 16616374Skarels } 16716374Skarels if (argc > 0) 16816374Skarels CONFIG = argv[0]; 16916374Skarels #ifndef DEBUG 17016374Skarels if (fork()) 17116374Skarels exit(0); 17216374Skarels { int s; 17316374Skarels for (s = 0; s < 10; s++) 17416374Skarels (void) close(s); 17516374Skarels } 17616374Skarels (void) open("/", O_RDONLY); 17716374Skarels (void) dup2(0, 1); 17816374Skarels (void) dup2(0, 2); 17916374Skarels { int tt = open("/dev/tty", O_RDWR); 18016374Skarels if (tt > 0) { 18116374Skarels ioctl(tt, TIOCNOTTY, 0); 18216374Skarels close(tt); 18316374Skarels } 18416374Skarels } 18516374Skarels #endif 18624856Seric openlog("inetd", LOG_PID, LOG_DAEMON); 18716374Skarels config(); 18816374Skarels signal(SIGHUP, config); 18916374Skarels signal(SIGCHLD, reapchild); 19016374Skarels for (;;) { 19125046Skarels int s, ctrl, n; 19225046Skarels fd_set readable; 19316374Skarels 19425046Skarels while (nsock == 0) 19516374Skarels sigpause(0); 19616374Skarels readable = allsock; 19725046Skarels if ((n = select(maxsock + 1, &readable, 0, 0, 0)) <= 0) 19816374Skarels continue; 19925046Skarels for (s = 0; s <= maxsock; s++) 20025046Skarels if (FD_ISSET(s, &readable)) 20125046Skarels break; 20216374Skarels for (sep = servtab; sep; sep = sep->se_next) 20316374Skarels if (s == sep->se_fd) 20416374Skarels goto found; 20516374Skarels abort(1); 20616374Skarels found: 20716374Skarels if (debug) 20816374Skarels fprintf(stderr, "someone wants %s\n", sep->se_service); 20925046Skarels if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 21016374Skarels ctrl = accept(s, 0, 0); 21116510Sralph if (debug) 21216510Sralph fprintf(stderr, "accept, ctrl %d\n", ctrl); 21316374Skarels if (ctrl < 0) { 21416374Skarels if (errno == EINTR) 21516374Skarels continue; 21616510Sralph syslog(LOG_WARNING, "accept: %m"); 21716374Skarels continue; 21816374Skarels } 21916374Skarels } else 22016374Skarels ctrl = sep->se_fd; 22125046Skarels sigblock(sigmask(SIGCHLD)|sigmask(SIGHUP)); 222*26877Skarels pid = 0; 223*26877Skarels if (sep->se_bi == 0 || sep->se_bi->bi_fork) 224*26877Skarels pid = fork(); 22516374Skarels if (pid < 0) { 22625046Skarels if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 22716374Skarels close(ctrl); 22816374Skarels sleep(1); 22916374Skarels continue; 23016374Skarels } 23116374Skarels if (sep->se_wait) { 23216374Skarels sep->se_wait = pid; 23325046Skarels FD_CLR(s, &allsock); 23425046Skarels nsock--; 23516374Skarels } 23616374Skarels sigsetmask(0); 23716374Skarels if (pid == 0) { 23816374Skarels #ifdef DEBUG 23916374Skarels int tt = open("/dev/tty", O_RDWR); 24016374Skarels if (tt > 0) { 24116374Skarels ioctl(tt, TIOCNOTTY, 0); 24216374Skarels close(tt); 24316374Skarels } 24416374Skarels #endif 245*26877Skarels if (sep->se_bi == 0 || sep->se_bi->bi_fork) 246*26877Skarels for (i = getdtablesize(); --i > 2; ) 247*26877Skarels if (i != ctrl) 248*26877Skarels close(i); 249*26877Skarels if (sep->se_bi) 250*26877Skarels (*sep->se_bi->bi_fn)(ctrl, sep); 251*26877Skarels else { 252*26877Skarels dup2(ctrl, 0); 253*26877Skarels close(ctrl); 254*26877Skarels dup2(0, 1); 255*26877Skarels dup2(0, 2); 256*26877Skarels if ((pwd = getpwnam(sep->se_user)) == NULL) { 257*26877Skarels syslog(LOG_ERR, 258*26877Skarels "getpwnam: %s: No such user", 259*26877Skarels sep->se_user); 260*26877Skarels _exit(1); 261*26877Skarels } 262*26877Skarels if (pwd->pw_uid) { 263*26877Skarels (void) setgid(pwd->pw_gid); 264*26877Skarels initgroups(pwd->pw_name, pwd->pw_gid); 265*26877Skarels (void) setuid(pwd->pw_uid); 266*26877Skarels } 267*26877Skarels if (debug) 268*26877Skarels fprintf(stderr, "%d execl %s\n", 269*26877Skarels getpid(), sep->se_server); 270*26877Skarels execv(sep->se_server, sep->se_argv); 271*26877Skarels if (sep->se_socktype != SOCK_STREAM) 272*26877Skarels recv(0, buf, sizeof (buf), 0); 273*26877Skarels syslog(LOG_ERR, "execv %s: %m", sep->se_server); 274*26877Skarels _exit(1); 27517346Sbloom } 27616374Skarels } 27725046Skarels if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 27816374Skarels close(ctrl); 27916374Skarels } 28016374Skarels } 28116374Skarels 28216374Skarels reapchild() 28316374Skarels { 28416374Skarels union wait status; 28516374Skarels int pid; 28616374Skarels register struct servtab *sep; 28716374Skarels 28816374Skarels for (;;) { 28916374Skarels pid = wait3(&status, WNOHANG, 0); 29016374Skarels if (pid <= 0) 29116374Skarels break; 29216374Skarels if (debug) 29316374Skarels fprintf(stderr, "%d reaped\n", pid); 29416374Skarels for (sep = servtab; sep; sep = sep->se_next) 29516374Skarels if (sep->se_wait == pid) { 29616374Skarels if (status.w_status) 29716510Sralph syslog(LOG_WARNING, 29816510Sralph "%s: exit status 0x%x", 29916374Skarels sep->se_server, status); 30016374Skarels if (debug) 30116374Skarels fprintf(stderr, "restored %s, fd %d\n", 30216374Skarels sep->se_service, sep->se_fd); 30325046Skarels FD_SET(sep->se_fd, &allsock); 30425046Skarels nsock++; 30516374Skarels sep->se_wait = 1; 30616374Skarels } 30716374Skarels } 30816374Skarels } 30916374Skarels 31016374Skarels config() 31116374Skarels { 31216374Skarels register struct servtab *sep, *cp, **sepp; 31316374Skarels struct servtab *getconfigent(), *enter(); 31417156Ssam int omask, on = 1; 31516374Skarels 31616374Skarels if (!setconfig()) { 31716510Sralph syslog(LOG_ERR, "%s: %m", CONFIG); 31816374Skarels return; 31916374Skarels } 32016374Skarels for (sep = servtab; sep; sep = sep->se_next) 32116374Skarels sep->se_checked = 0; 32216374Skarels while (cp = getconfigent()) { 32316374Skarels for (sep = servtab; sep; sep = sep->se_next) 32416374Skarels if (strcmp(sep->se_service, cp->se_service) == 0 && 32516374Skarels strcmp(sep->se_proto, cp->se_proto) == 0) 32616374Skarels break; 32716374Skarels if (sep != 0) { 32816374Skarels int i; 32916374Skarels 33025046Skarels omask = sigblock(sigmask(SIGCHLD)); 33116374Skarels sep->se_wait = cp->se_wait; 33216374Skarels #define SWAP(a, b) { char *c = a; a = b; b = c; } 33316374Skarels if (cp->se_server) 33416374Skarels SWAP(sep->se_server, cp->se_server); 33516374Skarels for (i = 0; i < MAXARGV; i++) 33616374Skarels SWAP(sep->se_argv[i], cp->se_argv[i]); 33716374Skarels sigsetmask(omask); 33816374Skarels freeconfig(cp); 33916374Skarels } else 34016374Skarels sep = enter(cp); 34116374Skarels sep->se_checked = 1; 34216374Skarels if (sep->se_fd != -1) 34316374Skarels continue; 34416374Skarels sp = getservbyname(sep->se_service, sep->se_proto); 34516374Skarels if (sp == 0) { 34616510Sralph syslog(LOG_ERR, "%s/%s: unknown service", 34716374Skarels sep->se_service, sep->se_proto); 34816374Skarels continue; 34916374Skarels } 35016374Skarels sep->se_ctrladdr.sin_port = sp->s_port; 35116374Skarels if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) { 35216510Sralph syslog(LOG_ERR, "%s/%s: socket: %m", 35316374Skarels sep->se_service, sep->se_proto); 35416374Skarels continue; 35516374Skarels } 35617156Ssam #define turnon(fd, opt) \ 35717156Ssam setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on)) 35816374Skarels if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 35917156Ssam turnon(sep->se_fd, SO_DEBUG) < 0) 36016510Sralph syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 36117156Ssam if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 36216510Sralph syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 36317156Ssam #undef turnon 36416374Skarels if (bind(sep->se_fd, &sep->se_ctrladdr, 36516374Skarels sizeof (sep->se_ctrladdr), 0) < 0) { 36616510Sralph syslog(LOG_ERR, "%s/%s: bind: %m", 36716374Skarels sep->se_service, sep->se_proto); 36816374Skarels continue; 36916374Skarels } 37016374Skarels if (sep->se_socktype == SOCK_STREAM) 37116374Skarels listen(sep->se_fd, 10); 37225046Skarels FD_SET(sep->se_fd, &allsock); 37325046Skarels nsock++; 37425046Skarels if (sep->se_fd > maxsock) 37525046Skarels maxsock = sep->se_fd; 37616374Skarels } 37716374Skarels endconfig(); 37816374Skarels /* 37916374Skarels * Purge anything not looked at above. 38016374Skarels */ 38125046Skarels omask = sigblock(sigmask(SIGCHLD)); 38216374Skarels sepp = &servtab; 38316374Skarels while (sep = *sepp) { 38416374Skarels if (sep->se_checked) { 38516374Skarels sepp = &sep->se_next; 38616374Skarels continue; 38716374Skarels } 38816374Skarels *sepp = sep->se_next; 38916374Skarels if (sep->se_fd != -1) { 39025046Skarels FD_CLR(sep->se_fd, &allsock); 39125046Skarels nsock--; 39216374Skarels (void) close(sep->se_fd); 39316374Skarels } 39416374Skarels freeconfig(sep); 39516374Skarels free((char *)sep); 39616374Skarels } 39716374Skarels (void) sigsetmask(omask); 39816374Skarels } 39916374Skarels 40016374Skarels struct servtab * 40116374Skarels enter(cp) 40216374Skarels struct servtab *cp; 40316374Skarels { 40416374Skarels register struct servtab *sep; 40525046Skarels int omask; 40616374Skarels char *strdup(); 40716374Skarels 40816374Skarels sep = (struct servtab *)malloc(sizeof (*sep)); 40916374Skarels if (sep == (struct servtab *)0) { 41016510Sralph syslog(LOG_ERR, "Out of memory."); 41116374Skarels exit(-1); 41216374Skarels } 41316374Skarels *sep = *cp; 41416374Skarels sep->se_fd = -1; 41525046Skarels omask = sigblock(sigmask(SIGCHLD)); 41616374Skarels sep->se_next = servtab; 41716374Skarels servtab = sep; 41816374Skarels sigsetmask(omask); 41916374Skarels return (sep); 42016374Skarels } 42116374Skarels 42216374Skarels FILE *fconfig = NULL; 42316374Skarels struct servtab serv; 42416374Skarels char line[256]; 42516374Skarels char *skip(), *nextline(); 42616374Skarels 42716374Skarels setconfig() 42816374Skarels { 42916374Skarels 43016374Skarels if (fconfig != NULL) { 43116374Skarels fseek(fconfig, 0, L_SET); 43216374Skarels return (1); 43316374Skarels } 43416374Skarels fconfig = fopen(CONFIG, "r"); 43516374Skarels return (fconfig != NULL); 43616374Skarels } 43716374Skarels 43816374Skarels endconfig() 43916374Skarels { 44016374Skarels 44116374Skarels if (fconfig == NULL) 44216374Skarels return; 44316374Skarels fclose(fconfig); 44416374Skarels fconfig = NULL; 44516374Skarels } 44616374Skarels 44716374Skarels struct servtab * 44816374Skarels getconfigent() 44916374Skarels { 45016374Skarels register struct servtab *sep = &serv; 45116374Skarels char *cp, *arg; 45216374Skarels int argc; 45316374Skarels 454*26877Skarels more: 45516374Skarels while ((cp = nextline(fconfig)) && *cp == '#') 45616374Skarels ; 45716374Skarels if (cp == NULL) 45816374Skarels return ((struct servtab *)0); 45916374Skarels sep->se_service = strdup(skip(&cp)); 46016374Skarels arg = skip(&cp); 46116374Skarels if (strcmp(arg, "stream") == 0) 46216374Skarels sep->se_socktype = SOCK_STREAM; 46316374Skarels else if (strcmp(arg, "dgram") == 0) 46416374Skarels sep->se_socktype = SOCK_DGRAM; 46516374Skarels else if (strcmp(arg, "rdm") == 0) 46616374Skarels sep->se_socktype = SOCK_RDM; 46716374Skarels else if (strcmp(arg, "seqpacket") == 0) 46816374Skarels sep->se_socktype = SOCK_SEQPACKET; 46916374Skarels else if (strcmp(arg, "raw") == 0) 47016374Skarels sep->se_socktype = SOCK_RAW; 47116374Skarels else 47216374Skarels sep->se_socktype = -1; 47316374Skarels sep->se_proto = strdup(skip(&cp)); 47416374Skarels arg = skip(&cp); 47516374Skarels sep->se_wait = strcmp(arg, "wait") == 0; 47617346Sbloom sep->se_user = strdup(skip(&cp)); 47716374Skarels sep->se_server = strdup(skip(&cp)); 478*26877Skarels if (strcmp(sep->se_server, "internal") == 0) { 479*26877Skarels register struct biltin *bi; 480*26877Skarels 481*26877Skarels for (bi = biltins; bi->bi_service; bi++) 482*26877Skarels if (bi->bi_socktype == sep->se_socktype && 483*26877Skarels strcmp(bi->bi_service, sep->se_service) == 0) 484*26877Skarels break; 485*26877Skarels if (bi->bi_service == 0) { 486*26877Skarels syslog(LOG_ERR, "internal service %s unknown\n", 487*26877Skarels sep->se_service); 488*26877Skarels goto more; 489*26877Skarels } 490*26877Skarels sep->se_bi = bi; 491*26877Skarels sep->se_wait = bi->bi_wait; 492*26877Skarels } 49316374Skarels argc = 0; 49416374Skarels for (arg = skip(&cp); cp; arg = skip(&cp)) 49516374Skarels if (argc < MAXARGV) 49616374Skarels sep->se_argv[argc++] = strdup(arg); 49716374Skarels while (argc <= MAXARGV) 49816374Skarels sep->se_argv[argc++] = NULL; 49916374Skarels return (sep); 50016374Skarels } 50116374Skarels 50216374Skarels freeconfig(cp) 50316374Skarels register struct servtab *cp; 50416374Skarels { 50516374Skarels int i; 50616374Skarels 50716374Skarels if (cp->se_service) 50816374Skarels free(cp->se_service); 50916374Skarels if (cp->se_proto) 51016374Skarels free(cp->se_proto); 51116374Skarels if (cp->se_server) 51216374Skarels free(cp->se_server); 51316374Skarels for (i = 0; i < MAXARGV; i++) 51416374Skarels if (cp->se_argv[i]) 51516374Skarels free(cp->se_argv[i]); 51616374Skarels } 51716374Skarels 51816374Skarels char * 51916374Skarels skip(cpp) 52016374Skarels char **cpp; 52116374Skarels { 52216374Skarels register char *cp = *cpp; 52316374Skarels char *start; 52416374Skarels 52516374Skarels again: 52616374Skarels while (*cp == ' ' || *cp == '\t') 52716374Skarels cp++; 52816374Skarels if (*cp == '\0') { 52916374Skarels char c; 53016374Skarels 53116374Skarels c = getc(fconfig); 53216374Skarels ungetc(c, fconfig); 53316374Skarels if (c == ' ' || c == '\t') 53416374Skarels if (cp = nextline(fconfig)) 53516374Skarels goto again; 53616374Skarels *cpp = (char *)0; 53716374Skarels return ((char *)0); 53816374Skarels } 53916374Skarels start = cp; 54016374Skarels while (*cp && *cp != ' ' && *cp != '\t') 54116374Skarels cp++; 54216374Skarels if (*cp != '\0') 54316374Skarels *cp++ = '\0'; 54416374Skarels *cpp = cp; 54516374Skarels return (start); 54616374Skarels } 54716374Skarels 54816374Skarels char * 54916374Skarels nextline(fd) 55016374Skarels FILE *fd; 55116374Skarels { 55216374Skarels char *cp; 55316374Skarels 55416374Skarels if (fgets(line, sizeof (line), fconfig) == NULL) 55516374Skarels return ((char *)0); 55616374Skarels cp = index(line, '\n'); 55716374Skarels if (cp) 55816374Skarels *cp = '\0'; 55916374Skarels return (line); 56016374Skarels } 56116374Skarels 56216374Skarels char * 56316374Skarels strdup(cp) 56416374Skarels char *cp; 56516374Skarels { 56616374Skarels char *new; 56716374Skarels 56816374Skarels if (cp == NULL) 56916374Skarels cp = ""; 57016374Skarels new = malloc(strlen(cp) + 1); 57116374Skarels if (new == (char *)0) { 57216510Sralph syslog(LOG_ERR, "Out of memory."); 57316374Skarels exit(-1); 57416374Skarels } 57516374Skarels strcpy(new, cp); 57616374Skarels return (new); 57716374Skarels } 578*26877Skarels 579*26877Skarels setproctitle(a, s) 580*26877Skarels char *a; 581*26877Skarels int s; 582*26877Skarels { 583*26877Skarels int size; 584*26877Skarels register char *cp; 585*26877Skarels struct sockaddr_in sin; 586*26877Skarels char buf[80]; 587*26877Skarels 588*26877Skarels cp = Argv[0]; 589*26877Skarels size = sizeof(sin); 590*26877Skarels if (getpeername(s, &sin, &size) == 0) 591*26877Skarels sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 592*26877Skarels else 593*26877Skarels sprintf(buf, "-%s", a); 594*26877Skarels strncpy(cp, buf, LastArg - cp); 595*26877Skarels cp += strlen(cp); 596*26877Skarels while (cp < LastArg) 597*26877Skarels *cp++ = ' '; 598*26877Skarels } 599*26877Skarels 600*26877Skarels /* 601*26877Skarels * Internet services provided internally by inetd: 602*26877Skarels */ 603*26877Skarels 604*26877Skarels /* ARGSUSED */ 605*26877Skarels echo_stream(s, sep) /* Echo service -- echo data back */ 606*26877Skarels int s; 607*26877Skarels struct servtab *sep; 608*26877Skarels { 609*26877Skarels char buffer[BUFSIZ]; 610*26877Skarels int i; 611*26877Skarels 612*26877Skarels setproctitle("echo", s); 613*26877Skarels while ((i = read(s, buffer, sizeof(buffer))) > 0 && 614*26877Skarels write(s, buffer, i) > 0) 615*26877Skarels ; 616*26877Skarels exit(0); 617*26877Skarels } 618*26877Skarels 619*26877Skarels /* ARGSUSED */ 620*26877Skarels echo_dg(s, sep) /* Echo service -- echo data back */ 621*26877Skarels int s; 622*26877Skarels struct servtab *sep; 623*26877Skarels { 624*26877Skarels char buffer[BUFSIZ]; 625*26877Skarels int i, size; 626*26877Skarels struct sockaddr sa; 627*26877Skarels 628*26877Skarels size = sizeof(sa); 629*26877Skarels if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) 630*26877Skarels return; 631*26877Skarels (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); 632*26877Skarels } 633*26877Skarels 634*26877Skarels /* ARGSUSED */ 635*26877Skarels discard_stream(s, sep) /* Discard service -- ignore data */ 636*26877Skarels int s; 637*26877Skarels struct servtab *sep; 638*26877Skarels { 639*26877Skarels char buffer[BUFSIZ]; 640*26877Skarels 641*26877Skarels setproctitle("discard", s); 642*26877Skarels while (1) { 643*26877Skarels while (read(s, buffer, sizeof(buffer)) > 0) 644*26877Skarels ; 645*26877Skarels if (errno != EINTR) 646*26877Skarels break; 647*26877Skarels } 648*26877Skarels exit(0); 649*26877Skarels } 650*26877Skarels 651*26877Skarels /* ARGSUSED */ 652*26877Skarels discard_dg(s, sep) /* Discard service -- ignore data */ 653*26877Skarels int s; 654*26877Skarels struct servtab *sep; 655*26877Skarels { 656*26877Skarels char buffer[BUFSIZ]; 657*26877Skarels 658*26877Skarels (void) read(s, buffer, sizeof(buffer)); 659*26877Skarels } 660*26877Skarels 661*26877Skarels #include <ctype.h> 662*26877Skarels #define LINESIZ 72 663*26877Skarels char ring[128]; 664*26877Skarels char *endring; 665*26877Skarels 666*26877Skarels initring() 667*26877Skarels { 668*26877Skarels register int i; 669*26877Skarels 670*26877Skarels endring = ring; 671*26877Skarels 672*26877Skarels for (i = 0; i <= 128; ++i) 673*26877Skarels if (isprint(i)) 674*26877Skarels *endring++ = i; 675*26877Skarels } 676*26877Skarels 677*26877Skarels /* ARGSUSED */ 678*26877Skarels chargen_stream(s, sep) /* Character generator */ 679*26877Skarels int s; 680*26877Skarels struct servtab *sep; 681*26877Skarels { 682*26877Skarels char text[LINESIZ+2]; 683*26877Skarels register int i; 684*26877Skarels register char *rp, *rs, *dp; 685*26877Skarels 686*26877Skarels setproctitle("discard", s); 687*26877Skarels if (endring == 0) 688*26877Skarels initring(); 689*26877Skarels 690*26877Skarels for (rs = ring; ; ++rs) { 691*26877Skarels if (rs >= endring) 692*26877Skarels rs = ring; 693*26877Skarels rp = rs; 694*26877Skarels dp = text; 695*26877Skarels i = MIN(LINESIZ, endring - rp); 696*26877Skarels bcopy(rp, dp, i); 697*26877Skarels dp += i; 698*26877Skarels if ((rp += i) >= endring) 699*26877Skarels rp = ring; 700*26877Skarels if (i < LINESIZ) { 701*26877Skarels i = LINESIZ - i; 702*26877Skarels bcopy(rp, dp, i); 703*26877Skarels dp += i; 704*26877Skarels if ((rp += i) >= endring) 705*26877Skarels rp = ring; 706*26877Skarels } 707*26877Skarels *dp++ = '\r'; 708*26877Skarels *dp++ = '\n'; 709*26877Skarels 710*26877Skarels if (write(s, text, dp - text) != dp - text) 711*26877Skarels break; 712*26877Skarels } 713*26877Skarels exit(0); 714*26877Skarels } 715*26877Skarels 716*26877Skarels /* ARGSUSED */ 717*26877Skarels chargen_dg(s, sep) /* Character generator */ 718*26877Skarels int s; 719*26877Skarels struct servtab *sep; 720*26877Skarels { 721*26877Skarels char text[LINESIZ+2]; 722*26877Skarels register int i; 723*26877Skarels register char *rp; 724*26877Skarels static char *rs = ring; 725*26877Skarels struct sockaddr sa; 726*26877Skarels int size; 727*26877Skarels 728*26877Skarels if (endring == 0) 729*26877Skarels initring(); 730*26877Skarels 731*26877Skarels size = sizeof(sa); 732*26877Skarels if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) 733*26877Skarels return; 734*26877Skarels rp = rs; 735*26877Skarels if (rs++ >= endring) 736*26877Skarels rs = ring; 737*26877Skarels i = MIN(LINESIZ - 2, endring - rp); 738*26877Skarels bcopy(rp, text, i); 739*26877Skarels if ((rp += i) >= endring) 740*26877Skarels rp = ring; 741*26877Skarels if (i < LINESIZ - 2) { 742*26877Skarels bcopy(rp, text, i); 743*26877Skarels if ((rp += i) >= endring) 744*26877Skarels rp = ring; 745*26877Skarels } 746*26877Skarels text[LINESIZ - 2] = '\r'; 747*26877Skarels text[LINESIZ - 1] = '\n'; 748*26877Skarels 749*26877Skarels (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); 750*26877Skarels } 751*26877Skarels 752*26877Skarels /* 753*26877Skarels * Return a machine readable date and time, in the form of the 754*26877Skarels * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 755*26877Skarels * returns the number of seconds since midnight, Jan 1, 1970, 756*26877Skarels * we must add 2208988800 seconds to this figure to make up for 757*26877Skarels * some seventy years Bell Labs was asleep. 758*26877Skarels */ 759*26877Skarels #include <sys/time.h> 760*26877Skarels 761*26877Skarels long 762*26877Skarels machtime() 763*26877Skarels { 764*26877Skarels struct timeval tv; 765*26877Skarels 766*26877Skarels if (gettimeofday(&tv, 0) < 0) { 767*26877Skarels fprintf(stderr, "Unable to get time of day\n"); 768*26877Skarels return; 769*26877Skarels } 770*26877Skarels return (htonl((long)tv.tv_sec + 2208988800)); 771*26877Skarels } 772*26877Skarels 773*26877Skarels /* ARGSUSED */ 774*26877Skarels machtime_stream(s, sep) 775*26877Skarels int s; 776*26877Skarels struct servtab *sep; 777*26877Skarels { 778*26877Skarels long result; 779*26877Skarels 780*26877Skarels result = machtime(); 781*26877Skarels (void) write(s, (char *) &result, sizeof(result)); 782*26877Skarels } 783*26877Skarels 784*26877Skarels /* ARGSUSED */ 785*26877Skarels machtime_dg(s, sep) 786*26877Skarels int s; 787*26877Skarels struct servtab *sep; 788*26877Skarels { 789*26877Skarels long result; 790*26877Skarels struct sockaddr sa; 791*26877Skarels int size; 792*26877Skarels 793*26877Skarels size = sizeof(sa); 794*26877Skarels if (recvfrom(s, &result, sizeof(result), 0, &sa, &size) < 0) 795*26877Skarels return; 796*26877Skarels result = machtime(); 797*26877Skarels (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); 798*26877Skarels } 799*26877Skarels 800*26877Skarels /* ARGSUSED */ 801*26877Skarels daytime_stream(s, sep) /* Return human-readable time of day */ 802*26877Skarels int s; 803*26877Skarels struct servtab *sep; 804*26877Skarels { 805*26877Skarels char buffer[256]; 806*26877Skarels time_t time(), clock; 807*26877Skarels char *ctime(); 808*26877Skarels 809*26877Skarels clock = time((time_t *) 0); 810*26877Skarels 811*26877Skarels sprintf(buffer, "%s\r", ctime(&clock)); 812*26877Skarels write(s, buffer, strlen(buffer)); 813*26877Skarels } 814*26877Skarels 815*26877Skarels /* ARGSUSED */ 816*26877Skarels daytime_dg(s, sep) /* Return human-readable time of day */ 817*26877Skarels int s; 818*26877Skarels struct servtab *sep; 819*26877Skarels { 820*26877Skarels char buffer[256]; 821*26877Skarels time_t time(), clock; 822*26877Skarels struct sockaddr sa; 823*26877Skarels int size; 824*26877Skarels char *ctime(); 825*26877Skarels 826*26877Skarels clock = time((time_t *) 0); 827*26877Skarels 828*26877Skarels size = sizeof(sa); 829*26877Skarels if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) 830*26877Skarels return; 831*26877Skarels sprintf(buffer, "%s\r", ctime(&clock)); 832*26877Skarels (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); 833*26877Skarels } 834