Annotation of 43BSD/etc/inetd.c, revision 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.