Annotation of 43BSD/etc/inetd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)inetd.c    5.6 (Berkeley) 4/29/86";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * Inetd - Internet super-server
                     19:  *
                     20:  * This program invokes all internet services as needed.
                     21:  * connection-oriented services are invoked each time a
                     22:  * connection is made, by creating a process.  This process
                     23:  * is passed the connection as file descriptor 0 and is
                     24:  * expected to do a getpeername to find out the source host
                     25:  * and port.
                     26:  *
                     27:  * Datagram oriented services are invoked when a datagram
                     28:  * arrives; a process is created and passed a pending message
                     29:  * on file descriptor 0.  Datagram servers may either connect
                     30:  * to their peer, freeing up the original socket for inetd
                     31:  * to receive further messages on, or ``take over the socket'',
                     32:  * processing all arriving datagrams and, eventually, timing
                     33:  * out.         The first type of server is said to be ``multi-threaded'';
                     34:  * the second type of server ``single-threaded''. 
                     35:  *
                     36:  * Inetd uses a configuration file which is read at startup
                     37:  * and, possibly, at some later time in response to a hangup signal.
                     38:  * The configuration file is ``free format'' with fields given in the
                     39:  * order shown below.  Continuation lines for an entry must being with
                     40:  * a space or tab.  All fields must be present in each entry.
                     41:  *
                     42:  *     service name                    must be in /etc/services
                     43:  *     socket type                     stream/dgram/raw/rdm/seqpacket
                     44:  *     protocol                        must be in /etc/protocols
                     45:  *     wait/nowait                     single-threaded/multi-threaded
                     46:  *     user                            user to run daemon as
                     47:  *     server program                  full path name
                     48:  *     server program arguments        maximum of MAXARGS (5)
                     49:  *
                     50:  * Comment lines are indicated by a `#' in column 1.
                     51:  */
                     52: #include <sys/param.h>
                     53: #include <sys/stat.h>
                     54: #include <sys/ioctl.h>
                     55: #include <sys/socket.h>
                     56: #include <sys/file.h>
                     57: #include <sys/wait.h>
                     58: #include <sys/time.h>
                     59: #include <sys/resource.h>
                     60: 
                     61: #include <netinet/in.h>
                     62: #include <arpa/inet.h>
                     63: 
                     64: #include <errno.h>
                     65: #include <stdio.h>
                     66: #include <signal.h>
                     67: #include <netdb.h>
                     68: #include <syslog.h>
                     69: #include <pwd.h>
                     70: 
                     71: #define        TOOMANY         40              /* don't start more than TOOMANY */
                     72: #define        CNT_INTVL       60              /* servers in CNT_INTVL sec. */
                     73: #define        RETRYTIME       (60*10)         /* retry after bind or server fail */
                     74: 
                     75: #define        SIGBLOCK        (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
                     76: 
                     77: extern int errno;
                     78: 
                     79: int    reapchild(), retry();
                     80: char   *index();
                     81: char   *malloc();
                     82: 
                     83: int    debug = 0;
                     84: int    nsock, maxsock;
                     85: fd_set allsock;
                     86: int    options;
                     87: int    timingout;
                     88: struct servent *sp;
                     89: 
                     90: struct servtab {
                     91:        char    *se_service;            /* name of service */
                     92:        int     se_socktype;            /* type of socket to use */
                     93:        char    *se_proto;              /* protocol used */
                     94:        short   se_wait;                /* single threaded server */
                     95:        short   se_checked;             /* looked at during merge */
                     96:        char    *se_user;               /* user name to run as */
                     97:        struct  biltin *se_bi;          /* if built-in, description */
                     98:        char    *se_server;             /* server program */
                     99: #define MAXARGV 5
                    100:        char    *se_argv[MAXARGV+1];    /* program arguments */
                    101:        int     se_fd;                  /* open descriptor */
                    102:        struct  sockaddr_in se_ctrladdr;/* bound address */
                    103:        int     se_count;               /* number started since se_time */
                    104:        struct  timeval se_time;        /* start of se_count */
                    105:        struct  servtab *se_next;
                    106: } *servtab;
                    107: 
                    108: int echo_stream(), discard_stream(), machtime_stream();
                    109: int daytime_stream(), chargen_stream();
                    110: int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg();
                    111: 
                    112: struct biltin {
                    113:        char    *bi_service;            /* internally provided service name */
                    114:        int     bi_socktype;            /* type of socket supported */
                    115:        short   bi_fork;                /* 1 if should fork before call */
                    116:        short   bi_wait;                /* 1 if should wait for child */
                    117:        int     (*bi_fn)();             /* function which performs it */
                    118: } biltins[] = {
                    119:        /* Echo received data */
                    120:        "echo",         SOCK_STREAM,    1, 0,   echo_stream,
                    121:        "echo",         SOCK_DGRAM,     0, 0,   echo_dg,
                    122: 
                    123:        /* Internet /dev/null */
                    124:        "discard",      SOCK_STREAM,    1, 0,   discard_stream,
                    125:        "discard",      SOCK_DGRAM,     0, 0,   discard_dg,
                    126: 
                    127:        /* Return 32 bit time since 1970 */
                    128:        "time",         SOCK_STREAM,    0, 0,   machtime_stream,
                    129:        "time",         SOCK_DGRAM,     0, 0,   machtime_dg,
                    130: 
                    131:        /* Return human-readable time */
                    132:        "daytime",      SOCK_STREAM,    0, 0,   daytime_stream,
                    133:        "daytime",      SOCK_DGRAM,     0, 0,   daytime_dg,
                    134: 
                    135:        /* Familiar character generator */
                    136:        "chargen",      SOCK_STREAM,    1, 0,   chargen_stream,
                    137:        "chargen",      SOCK_DGRAM,     0, 0,   chargen_dg,
                    138:        0
                    139: };
                    140: 
                    141: #define NUMINT (sizeof(intab) / sizeof(struct inent))
                    142: char   *CONFIG = "/etc/inetd.conf";
                    143: char   **Argv;
                    144: char   *LastArg;
                    145: 
                    146: main(argc, argv, envp)
                    147:        int argc;
                    148:        char *argv[], *envp[];
                    149: {
                    150:        register struct servtab *sep;
                    151:        register struct passwd *pwd;
                    152:        char *cp, buf[50];
                    153:        int pid, i, dofork;
                    154:        struct sigvec sv;
                    155: 
                    156:        Argv = argv;
                    157:        if (envp == 0 || *envp == 0)
                    158:                envp = argv;
                    159:        while (*envp)
                    160:                envp++;
                    161:        LastArg = envp[-1] + strlen(envp[-1]);
                    162:        argc--, argv++;
                    163:        while (argc > 0 && *argv[0] == '-') {
                    164:                for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
                    165: 
                    166:                case 'd':
                    167:                        debug = 1;
                    168:                        options |= SO_DEBUG;
                    169:                        break;
                    170: 
                    171:                default:
                    172:                        fprintf(stderr,
                    173:                            "inetd: Unknown flag -%c ignored.\n", *cp);
                    174:                        break;
                    175:                }
                    176: nextopt:
                    177:                argc--, argv++;
                    178:        }
                    179:        if (argc > 0)
                    180:                CONFIG = argv[0];
                    181: #ifndef DEBUG
                    182:        if (fork())
                    183:                exit(0);
                    184:        { int s;
                    185:        for (s = 0; s < 10; s++)
                    186:                (void) close(s);
                    187:        }
                    188:        (void) open("/", O_RDONLY);
                    189:        (void) dup2(0, 1);
                    190:        (void) dup2(0, 2);
                    191:        { int tt = open("/dev/tty", O_RDWR);
                    192:          if (tt > 0) {
                    193:                ioctl(tt, TIOCNOTTY, (char *)0);
                    194:                close(tt);
                    195:          }
                    196:        }
                    197: #endif
                    198:        openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
                    199:        bzero((char *)&sv, sizeof(sv));
                    200:        sv.sv_mask = SIGBLOCK;
                    201:        sv.sv_handler = retry;
                    202:        sigvec(SIGALRM, &sv, (struct sigvec *)0);
                    203:        config();
                    204:        sv.sv_handler = config;
                    205:        sigvec(SIGHUP, &sv, (struct sigvec *)0);
                    206:        sv.sv_handler = reapchild;
                    207:        sigvec(SIGCHLD, &sv, (struct sigvec *)0);
                    208: 
                    209:        for (;;) {
                    210:            int s, ctrl, n;
                    211:            fd_set readable;
                    212: 
                    213:            while (nsock == 0)
                    214:                    sigpause(0);
                    215:            readable = allsock;
                    216:            if ((n = select(maxsock + 1, &readable, (fd_set *)0,
                    217:                (fd_set *)0, (struct timeval *)0)) <= 0) {
                    218:                    if (n < 0 && errno != EINTR)
                    219:                                syslog(LOG_WARNING, "select: %m\n");
                    220:                    sleep(1);
                    221:                    continue;
                    222:            }
                    223:            for (sep = servtab; n && sep; sep = sep->se_next)
                    224:            if (FD_ISSET(sep->se_fd, &readable)) {
                    225:                n--;
                    226:                if (debug)
                    227:                        fprintf(stderr, "someone wants %s\n", sep->se_service);
                    228:                if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
                    229:                        ctrl = accept(sep->se_fd, (struct sockaddr *)0,
                    230:                            (int *)0);
                    231:                        if (debug)
                    232:                                fprintf(stderr, "accept, ctrl %d\n", ctrl);
                    233:                        if (ctrl < 0) {
                    234:                                if (errno == EINTR)
                    235:                                        continue;
                    236:                                syslog(LOG_WARNING, "accept: %m");
                    237:                                continue;
                    238:                        }
                    239:                } else
                    240:                        ctrl = sep->se_fd;
                    241:                (void) sigblock(SIGBLOCK);
                    242:                pid = 0;
                    243:                dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
                    244:                if (dofork) {
                    245:                        if (sep->se_count++ == 0)
                    246:                            (void)gettimeofday(&sep->se_time,
                    247:                                (struct timezone *)0);
                    248:                        else if (sep->se_count >= TOOMANY) {
                    249:                                struct timeval now;
                    250: 
                    251:                                (void)gettimeofday(&now, (struct timezone *)0);
                    252:                                if (now.tv_sec - sep->se_time.tv_sec >
                    253:                                    CNT_INTVL) {
                    254:                                        sep->se_time = now;
                    255:                                        sep->se_count = 1;
                    256:                                } else {
                    257:                                        syslog(LOG_ERR,
                    258:                        "%s/%s server failing (looping), service terminated\n",
                    259:                                            sep->se_service, sep->se_proto);
                    260:                                        FD_CLR(sep->se_fd, &allsock);
                    261:                                        (void) close(sep->se_fd);
                    262:                                        sep->se_fd = -1;
                    263:                                        sep->se_count = 0;
                    264:                                        nsock--;
                    265:                                        sigsetmask(0);
                    266:                                        if (!timingout) {
                    267:                                                timingout = 1;
                    268:                                                alarm(RETRYTIME);
                    269:                                        }
                    270:                                        continue;
                    271:                                }
                    272:                        }
                    273:                        pid = fork();
                    274:                }
                    275:                if (pid < 0) {
                    276:                        if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
                    277:                                close(ctrl);
                    278:                        sigsetmask(0);
                    279:                        sleep(1);
                    280:                        continue;
                    281:                }
                    282:                if (pid && sep->se_wait) {
                    283:                        sep->se_wait = pid;
                    284:                        FD_CLR(sep->se_fd, &allsock);
                    285:                        nsock--;
                    286:                }
                    287:                sigsetmask(0);
                    288:                if (pid == 0) {
                    289: #ifdef DEBUG
                    290:                        int tt;
                    291: 
                    292:                        if (dofork && (tt = open("/dev/tty", O_RDWR)) > 0) {
                    293:                                ioctl(tt, TIOCNOTTY, 0);
                    294:                                close(tt);
                    295:                        }
                    296: #endif
                    297:                        if (dofork)
                    298:                                for (i = getdtablesize(); --i > 2; )
                    299:                                        if (i != ctrl)
                    300:                                                close(i);
                    301:                        if (sep->se_bi)
                    302:                                (*sep->se_bi->bi_fn)(ctrl, sep);
                    303:                        else {
                    304:                                dup2(ctrl, 0);
                    305:                                close(ctrl);
                    306:                                dup2(0, 1);
                    307:                                dup2(0, 2);
                    308:                                if ((pwd = getpwnam(sep->se_user)) == NULL) {
                    309:                                        syslog(LOG_ERR,
                    310:                                                "getpwnam: %s: No such user",
                    311:                                                sep->se_user);
                    312:                                        if (sep->se_socktype != SOCK_STREAM)
                    313:                                                recv(0, buf, sizeof (buf), 0);
                    314:                                        _exit(1);
                    315:                                }
                    316:                                if (pwd->pw_uid) {
                    317:                                        (void) setgid((gid_t)pwd->pw_gid);
                    318:                                        initgroups(pwd->pw_name, pwd->pw_gid);
                    319:                                        (void) setuid((uid_t)pwd->pw_uid);
                    320:                                }
                    321:                                if (debug)
                    322:                                        fprintf(stderr, "%d execl %s\n",
                    323:                                            getpid(), sep->se_server);
                    324:                                execv(sep->se_server, sep->se_argv);
                    325:                                if (sep->se_socktype != SOCK_STREAM)
                    326:                                        recv(0, buf, sizeof (buf), 0);
                    327:                                syslog(LOG_ERR, "execv %s: %m", sep->se_server);
                    328:                                _exit(1);
                    329:                        }
                    330:                }
                    331:                if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
                    332:                        close(ctrl);
                    333:            }
                    334:        }
                    335: }
                    336: 
                    337: reapchild()
                    338: {
                    339:        union wait status;
                    340:        int pid;
                    341:        register struct servtab *sep;
                    342: 
                    343:        for (;;) {
                    344:                pid = wait3(&status, WNOHANG, (struct rusage *)0);
                    345:                if (pid <= 0)
                    346:                        break;
                    347:                if (debug)
                    348:                        fprintf(stderr, "%d reaped\n", pid);
                    349:                for (sep = servtab; sep; sep = sep->se_next)
                    350:                        if (sep->se_wait == pid) {
                    351:                                if (status.w_status)
                    352:                                        syslog(LOG_WARNING,
                    353:                                            "%s: exit status 0x%x",
                    354:                                            sep->se_server, status);
                    355:                                if (debug)
                    356:                                        fprintf(stderr, "restored %s, fd %d\n",
                    357:                                            sep->se_service, sep->se_fd);
                    358:                                FD_SET(sep->se_fd, &allsock);
                    359:                                nsock++;
                    360:                                sep->se_wait = 1;
                    361:                        }
                    362:        }
                    363: }
                    364: 
                    365: config()
                    366: {
                    367:        register struct servtab *sep, *cp, **sepp;
                    368:        struct servtab *getconfigent(), *enter();
                    369:        int omask;
                    370: 
                    371:        if (!setconfig()) {
                    372:                syslog(LOG_ERR, "%s: %m", CONFIG);
                    373:                return;
                    374:        }
                    375:        for (sep = servtab; sep; sep = sep->se_next)
                    376:                sep->se_checked = 0;
                    377:        while (cp = getconfigent()) {
                    378:                for (sep = servtab; sep; sep = sep->se_next)
                    379:                        if (strcmp(sep->se_service, cp->se_service) == 0 &&
                    380:                            strcmp(sep->se_proto, cp->se_proto) == 0)
                    381:                                break;
                    382:                if (sep != 0) {
                    383:                        int i;
                    384: 
                    385:                        omask = sigblock(SIGBLOCK);
                    386:                        if (cp->se_bi == 0)
                    387:                                sep->se_wait = cp->se_wait;
                    388: #define SWAP(a, b) { char *c = a; a = b; b = c; }
                    389:                        if (cp->se_user)
                    390:                                SWAP(sep->se_user, cp->se_user);
                    391:                        if (cp->se_server)
                    392:                                SWAP(sep->se_server, cp->se_server);
                    393:                        for (i = 0; i < MAXARGV; i++)
                    394:                                SWAP(sep->se_argv[i], cp->se_argv[i]);
                    395:                        sigsetmask(omask);
                    396:                        freeconfig(cp);
                    397:                } else
                    398:                        sep = enter(cp);
                    399:                sep->se_checked = 1;
                    400:                sp = getservbyname(sep->se_service, sep->se_proto);
                    401:                if (sp == 0) {
                    402:                        syslog(LOG_ERR, "%s/%s: unknown service",
                    403:                            sep->se_service, sep->se_proto);
                    404:                        continue;
                    405:                }
                    406:                if (sp->s_port != sep->se_ctrladdr.sin_port) {
                    407:                        sep->se_ctrladdr.sin_port = sp->s_port;
                    408:                        if (sep->se_fd != -1)
                    409:                                (void) close(sep->se_fd);
                    410:                        sep->se_fd = -1;
                    411:                }
                    412:                if (sep->se_fd == -1)
                    413:                        setup(sep);
                    414:        }
                    415:        endconfig();
                    416:        /*
                    417:         * Purge anything not looked at above.
                    418:         */
                    419:        omask = sigblock(SIGBLOCK);
                    420:        sepp = &servtab;
                    421:        while (sep = *sepp) {
                    422:                if (sep->se_checked) {
                    423:                        sepp = &sep->se_next;
                    424:                        continue;
                    425:                }
                    426:                *sepp = sep->se_next;
                    427:                if (sep->se_fd != -1) {
                    428:                        FD_CLR(sep->se_fd, &allsock);
                    429:                        nsock--;
                    430:                        (void) close(sep->se_fd);
                    431:                }
                    432:                freeconfig(sep);
                    433:                free((char *)sep);
                    434:        }
                    435:        (void) sigsetmask(omask);
                    436: }
                    437: 
                    438: retry()
                    439: {
                    440:        register struct servtab *sep;
                    441: 
                    442:        timingout = 0;
                    443:        for (sep = servtab; sep; sep = sep->se_next)
                    444:                if (sep->se_fd == -1)
                    445:                        setup(sep);
                    446: }
                    447: 
                    448: setup(sep)
                    449:        register struct servtab *sep;
                    450: {
                    451:        int on = 1;
                    452: 
                    453:        if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
                    454:                syslog(LOG_ERR, "%s/%s: socket: %m",
                    455:                    sep->se_service, sep->se_proto);
                    456:                return;
                    457:        }
                    458: #define        turnon(fd, opt) \
                    459: setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
                    460:        if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
                    461:            turnon(sep->se_fd, SO_DEBUG) < 0)
                    462:                syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
                    463:        if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
                    464:                syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
                    465: #undef turnon
                    466:        if (bind(sep->se_fd, &sep->se_ctrladdr,
                    467:            sizeof (sep->se_ctrladdr)) < 0) {
                    468:                syslog(LOG_ERR, "%s/%s: bind: %m",
                    469:                    sep->se_service, sep->se_proto);
                    470:                (void) close(sep->se_fd);
                    471:                sep->se_fd = -1;
                    472:                if (!timingout) {
                    473:                        timingout = 1;
                    474:                        alarm(RETRYTIME);
                    475:                }
                    476:                return;
                    477:        }
                    478:        if (sep->se_socktype == SOCK_STREAM)
                    479:                listen(sep->se_fd, 10);
                    480:        FD_SET(sep->se_fd, &allsock);
                    481:        nsock++;
                    482:        if (sep->se_fd > maxsock)
                    483:                maxsock = sep->se_fd;
                    484: }
                    485: 
                    486: struct servtab *
                    487: enter(cp)
                    488:        struct servtab *cp;
                    489: {
                    490:        register struct servtab *sep;
                    491:        int omask;
                    492:        char *strdup();
                    493: 
                    494:        sep = (struct servtab *)malloc(sizeof (*sep));
                    495:        if (sep == (struct servtab *)0) {
                    496:                syslog(LOG_ERR, "Out of memory.");
                    497:                exit(-1);
                    498:        }
                    499:        *sep = *cp;
                    500:        sep->se_fd = -1;
                    501:        omask = sigblock(SIGBLOCK);
                    502:        sep->se_next = servtab;
                    503:        servtab = sep;
                    504:        sigsetmask(omask);
                    505:        return (sep);
                    506: }
                    507: 
                    508: FILE   *fconfig = NULL;
                    509: struct servtab serv;
                    510: char   line[256];
                    511: char   *skip(), *nextline();
                    512: 
                    513: setconfig()
                    514: {
                    515: 
                    516:        if (fconfig != NULL) {
                    517:                fseek(fconfig, 0L, L_SET);
                    518:                return (1);
                    519:        }
                    520:        fconfig = fopen(CONFIG, "r");
                    521:        return (fconfig != NULL);
                    522: }
                    523: 
                    524: endconfig()
                    525: {
                    526: 
                    527:        if (fconfig == NULL)
                    528:                return;
                    529:        fclose(fconfig);
                    530:        fconfig = NULL;
                    531: }
                    532: 
                    533: struct servtab *
                    534: getconfigent()
                    535: {
                    536:        register struct servtab *sep = &serv;
                    537:        char *cp, *arg;
                    538:        int argc;
                    539: 
                    540: more:
                    541:        while ((cp = nextline(fconfig)) && *cp == '#')
                    542:                ;
                    543:        if (cp == NULL)
                    544:                return ((struct servtab *)0);
                    545:        sep->se_service = strdup(skip(&cp));
                    546:        arg = skip(&cp);
                    547:        if (strcmp(arg, "stream") == 0)
                    548:                sep->se_socktype = SOCK_STREAM;
                    549:        else if (strcmp(arg, "dgram") == 0)
                    550:                sep->se_socktype = SOCK_DGRAM;
                    551:        else if (strcmp(arg, "rdm") == 0)
                    552:                sep->se_socktype = SOCK_RDM;
                    553:        else if (strcmp(arg, "seqpacket") == 0)
                    554:                sep->se_socktype = SOCK_SEQPACKET;
                    555:        else if (strcmp(arg, "raw") == 0)
                    556:                sep->se_socktype = SOCK_RAW;
                    557:        else
                    558:                sep->se_socktype = -1;
                    559:        sep->se_proto = strdup(skip(&cp));
                    560:        arg = skip(&cp);
                    561:        sep->se_wait = strcmp(arg, "wait") == 0;
                    562:        sep->se_user = strdup(skip(&cp));
                    563:        sep->se_server = strdup(skip(&cp));
                    564:        if (strcmp(sep->se_server, "internal") == 0) {
                    565:                register struct biltin *bi;
                    566: 
                    567:                for (bi = biltins; bi->bi_service; bi++)
                    568:                        if (bi->bi_socktype == sep->se_socktype &&
                    569:                            strcmp(bi->bi_service, sep->se_service) == 0)
                    570:                                break;
                    571:                if (bi->bi_service == 0) {
                    572:                        syslog(LOG_ERR, "internal service %s unknown\n",
                    573:                                sep->se_service);
                    574:                        goto more;
                    575:                }
                    576:                sep->se_bi = bi;
                    577:                sep->se_wait = bi->bi_wait;
                    578:        }
                    579:        argc = 0;
                    580:        for (arg = skip(&cp); cp; arg = skip(&cp))
                    581:                if (argc < MAXARGV)
                    582:                        sep->se_argv[argc++] = strdup(arg);
                    583:        while (argc <= MAXARGV)
                    584:                sep->se_argv[argc++] = NULL;
                    585:        return (sep);
                    586: }
                    587: 
                    588: freeconfig(cp)
                    589:        register struct servtab *cp;
                    590: {
                    591:        int i;
                    592: 
                    593:        if (cp->se_service)
                    594:                free(cp->se_service);
                    595:        if (cp->se_proto)
                    596:                free(cp->se_proto);
                    597:        if (cp->se_user)
                    598:                free(cp->se_user);
                    599:        if (cp->se_server)
                    600:                free(cp->se_server);
                    601:        for (i = 0; i < MAXARGV; i++)
                    602:                if (cp->se_argv[i])
                    603:                        free(cp->se_argv[i]);
                    604: }
                    605: 
                    606: char *
                    607: skip(cpp)
                    608:        char **cpp;
                    609: {
                    610:        register char *cp = *cpp;
                    611:        char *start;
                    612: 
                    613: again:
                    614:        while (*cp == ' ' || *cp == '\t')
                    615:                cp++;
                    616:        if (*cp == '\0') {
                    617:                char c;
                    618: 
                    619:                c = getc(fconfig);
                    620:                ungetc(c, fconfig);
                    621:                if (c == ' ' || c == '\t')
                    622:                        if (cp = nextline(fconfig))
                    623:                                goto again;
                    624:                *cpp = (char *)0;
                    625:                return ((char *)0);
                    626:        }
                    627:        start = cp;
                    628:        while (*cp && *cp != ' ' && *cp != '\t')
                    629:                cp++;
                    630:        if (*cp != '\0')
                    631:                *cp++ = '\0';
                    632:        *cpp = cp;
                    633:        return (start);
                    634: }
                    635: 
                    636: char *
                    637: nextline(fd)
                    638:        FILE *fd;
                    639: {
                    640:        char *cp;
                    641: 
                    642:        if (fgets(line, sizeof (line), fd) == NULL)
                    643:                return ((char *)0);
                    644:        cp = index(line, '\n');
                    645:        if (cp)
                    646:                *cp = '\0';
                    647:        return (line);
                    648: }
                    649: 
                    650: char *
                    651: strdup(cp)
                    652:        char *cp;
                    653: {
                    654:        char *new;
                    655: 
                    656:        if (cp == NULL)
                    657:                cp = "";
                    658:        new = malloc((unsigned)(strlen(cp) + 1));
                    659:        if (new == (char *)0) {
                    660:                syslog(LOG_ERR, "Out of memory.");
                    661:                exit(-1);
                    662:        }
                    663:        strcpy(new, cp);
                    664:        return (new);
                    665: }
                    666: 
                    667: setproctitle(a, s)
                    668:        char *a;
                    669:        int s;
                    670: {
                    671:        int size;
                    672:        register char *cp;
                    673:        struct sockaddr_in sin;
                    674:        char buf[80];
                    675: 
                    676:        cp = Argv[0];
                    677:        size = sizeof(sin);
                    678:        if (getpeername(s, &sin, &size) == 0)
                    679:                sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
                    680:        else
                    681:                sprintf(buf, "-%s", a); 
                    682:        strncpy(cp, buf, LastArg - cp);
                    683:        cp += strlen(cp);
                    684:        while (cp < LastArg)
                    685:                *cp++ = ' ';
                    686: }
                    687: 
                    688: /*
                    689:  * Internet services provided internally by inetd:
                    690:  */
                    691: 
                    692: /* ARGSUSED */
                    693: echo_stream(s, sep)            /* Echo service -- echo data back */
                    694:        int s;
                    695:        struct servtab *sep;
                    696: {
                    697:        char buffer[BUFSIZ];
                    698:        int i;
                    699: 
                    700:        setproctitle("echo", s);
                    701:        while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
                    702:            write(s, buffer, i) > 0)
                    703:                ;
                    704:        exit(0);
                    705: }
                    706: 
                    707: /* ARGSUSED */
                    708: echo_dg(s, sep)                        /* Echo service -- echo data back */
                    709:        int s;
                    710:        struct servtab *sep;
                    711: {
                    712:        char buffer[BUFSIZ];
                    713:        int i, size;
                    714:        struct sockaddr sa;
                    715: 
                    716:        size = sizeof(sa);
                    717:        if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
                    718:                return;
                    719:        (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
                    720: }
                    721: 
                    722: /* ARGSUSED */
                    723: discard_stream(s, sep)         /* Discard service -- ignore data */
                    724:        int s;
                    725:        struct servtab *sep;
                    726: {
                    727:        char buffer[BUFSIZ];
                    728: 
                    729:        setproctitle("discard", s);
                    730:        while (1) {
                    731:                while (read(s, buffer, sizeof(buffer)) > 0)
                    732:                        ;
                    733:                if (errno != EINTR)
                    734:                        break;
                    735:        }
                    736:        exit(0);
                    737: }
                    738: 
                    739: /* ARGSUSED */
                    740: discard_dg(s, sep)             /* Discard service -- ignore data */
                    741:        int s;
                    742:        struct servtab *sep;
                    743: {
                    744:        char buffer[BUFSIZ];
                    745: 
                    746:        (void) read(s, buffer, sizeof(buffer));
                    747: }
                    748: 
                    749: #include <ctype.h>
                    750: #define LINESIZ 72
                    751: char ring[128];
                    752: char *endring;
                    753: 
                    754: initring()
                    755: {
                    756:        register int i;
                    757: 
                    758:        endring = ring;
                    759: 
                    760:        for (i = 0; i <= 128; ++i)
                    761:                if (isprint(i))
                    762:                        *endring++ = i;
                    763: }
                    764: 
                    765: /* ARGSUSED */
                    766: chargen_stream(s, sep)         /* Character generator */
                    767:        int s;
                    768:        struct servtab *sep;
                    769: {
                    770:        char text[LINESIZ+2];
                    771:        register int i;
                    772:        register char *rp, *rs, *dp;
                    773: 
                    774:        setproctitle("discard", s);
                    775:        if (endring == 0)
                    776:                initring();
                    777: 
                    778:        for (rs = ring; ; ++rs) {
                    779:                if (rs >= endring)
                    780:                        rs = ring;
                    781:                rp = rs;
                    782:                dp = text;
                    783:                i = MIN(LINESIZ, endring - rp);
                    784:                bcopy(rp, dp, i);
                    785:                dp += i;
                    786:                if ((rp += i) >= endring)
                    787:                        rp = ring;
                    788:                if (i < LINESIZ) {
                    789:                        i = LINESIZ - i;
                    790:                        bcopy(rp, dp, i);
                    791:                        dp += i;
                    792:                        if ((rp += i) >= endring)
                    793:                                rp = ring;
                    794:                }
                    795:                *dp++ = '\r';
                    796:                *dp++ = '\n';
                    797: 
                    798:                if (write(s, text, dp - text) != dp - text)
                    799:                        break;
                    800:        }
                    801:        exit(0);
                    802: }
                    803: 
                    804: /* ARGSUSED */
                    805: chargen_dg(s, sep)             /* Character generator */
                    806:        int s;
                    807:        struct servtab *sep;
                    808: {
                    809:        char text[LINESIZ+2];
                    810:        register int i;
                    811:        register char *rp;
                    812:        static char *rs = ring;
                    813:        struct sockaddr sa;
                    814:        int size;
                    815: 
                    816:        if (endring == 0)
                    817:                initring();
                    818: 
                    819:        size = sizeof(sa);
                    820:        if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
                    821:                return;
                    822:        rp = rs;
                    823:        if (rs++ >= endring)
                    824:                rs = ring;
                    825:        i = MIN(LINESIZ - 2, endring - rp);
                    826:        bcopy(rp, text, i);
                    827:        if ((rp += i) >= endring)
                    828:                rp = ring;
                    829:        if (i < LINESIZ - 2) {
                    830:                bcopy(rp, text, i);
                    831:                if ((rp += i) >= endring)
                    832:                        rp = ring;
                    833:        }
                    834:        text[LINESIZ - 2] = '\r';
                    835:        text[LINESIZ - 1] = '\n';
                    836: 
                    837:        (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
                    838: }
                    839: 
                    840: /*
                    841:  * Return a machine readable date and time, in the form of the
                    842:  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
                    843:  * returns the number of seconds since midnight, Jan 1, 1970,
                    844:  * we must add 2208988800 seconds to this figure to make up for
                    845:  * some seventy years Bell Labs was asleep.
                    846:  */
                    847: 
                    848: long
                    849: machtime()
                    850: {
                    851:        struct timeval tv;
                    852: 
                    853:        if (gettimeofday(&tv, (struct timezone *)0) < 0) {
                    854:                fprintf(stderr, "Unable to get time of day\n");
                    855:                return (0L);
                    856:        }
                    857:        return (htonl((long)tv.tv_sec + 2208988800));
                    858: }
                    859: 
                    860: /* ARGSUSED */
                    861: machtime_stream(s, sep)
                    862:        int s;
                    863:        struct servtab *sep;
                    864: {
                    865:        long result;
                    866: 
                    867:        result = machtime();
                    868:        (void) write(s, (char *) &result, sizeof(result));
                    869: }
                    870: 
                    871: /* ARGSUSED */
                    872: machtime_dg(s, sep)
                    873:        int s;
                    874:        struct servtab *sep;
                    875: {
                    876:        long result;
                    877:        struct sockaddr sa;
                    878:        int size;
                    879: 
                    880:        size = sizeof(sa);
                    881:        if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
                    882:                return;
                    883:        result = machtime();
                    884:        (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
                    885: }
                    886: 
                    887: /* ARGSUSED */
                    888: daytime_stream(s, sep)         /* Return human-readable time of day */
                    889:        int s;
                    890:        struct servtab *sep;
                    891: {
                    892:        char buffer[256];
                    893:        time_t time(), clock;
                    894:        char *ctime();
                    895: 
                    896:        clock = time((time_t *) 0);
                    897: 
                    898:        sprintf(buffer, "%s\r", ctime(&clock));
                    899:        (void) write(s, buffer, strlen(buffer));
                    900: }
                    901: 
                    902: /* ARGSUSED */
                    903: daytime_dg(s, sep)             /* Return human-readable time of day */
                    904:        int s;
                    905:        struct servtab *sep;
                    906: {
                    907:        char buffer[256];
                    908:        time_t time(), clock;
                    909:        struct sockaddr sa;
                    910:        int size;
                    911:        char *ctime();
                    912: 
                    913:        clock = time((time_t *) 0);
                    914: 
                    915:        size = sizeof(sa);
                    916:        if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
                    917:                return;
                    918:        sprintf(buffer, "%s\r", ctime(&clock));
                    919:        (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
                    920: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.