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

unix.superglobalmegacorp.com

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