[BACK]Return to identd.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / identd

Annotation of src/libexec/identd/identd.c, Revision 1.11

1.11    ! wiz         1: /*     $NetBSD: identd.c,v 1.10 1999/05/18 04:49:41 jwise Exp $        */
1.8       mrg         2:
1.1       cgd         3: /*
                      4: ** identd.c                       A TCP/IP link identification protocol server
                      5: **
                      6: ** This program is in the public domain and may be used freely by anyone
                      7: ** who wants to.
                      8: **
1.9       msaitoh     9: ** Last update: 7 Oct 1993
1.1       cgd        10: **
                     11: ** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
                     12: */
                     13:
1.9       msaitoh    14: #if !defined(__STDC__) && !defined(_AIX)
                     15: #define void int
                     16: #endif
                     17:
                     18: #if defined(IRIX) || defined(SVR4) || defined(NeXT) || (defined(sco) && sco >= 42) || defined(_AIX4) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(ultrix)
1.1       cgd        19: #  define SIGRETURN_TYPE void
                     20: #  define SIGRETURN_TYPE_IS_VOID
                     21: #else
                     22: #  define SIGRETURN_TYPE int
                     23: #endif
                     24:
                     25: #ifdef SVR4
                     26: #  define STRNET
                     27: #endif
                     28:
1.9       msaitoh    29: #ifdef NeXT31
                     30: #  include <libc.h>
                     31: #endif
                     32:
                     33: #ifdef sco
                     34: #  define USE_SIGALARM
                     35: #endif
                     36:
                     37: #include <stdio.h>
                     38: #include <ctype.h>
                     39: #include <errno.h>
                     40: #include <netdb.h>
                     41: #include <signal.h>
                     42: #include <fcntl.h>
                     43:
1.1       cgd        44: #include <sys/types.h>
                     45: #include <sys/param.h>
                     46: #include <sys/ioctl.h>
                     47: #include <sys/socket.h>
                     48: #ifndef _AUX_SOURCE
                     49: #  include <sys/file.h>
                     50: #endif
                     51: #include <sys/time.h>
                     52: #include <sys/wait.h>
                     53:
                     54: #include <pwd.h>
                     55: #include <grp.h>
                     56:
                     57: #include <netinet/in.h>
                     58:
                     59: #ifndef HPUX7
                     60: #  include <arpa/inet.h>
                     61: #endif
                     62:
1.9       msaitoh    63: #ifdef _AIX32
                     64: # include <sys/select.h>
                     65: #endif
                     66:
1.1       cgd        67: #if defined(MIPS) || defined(BSD43)
                     68: extern int errno;
                     69: #endif
                     70:
1.9       msaitoh    71: #if defined(SOLARIS) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(_AIX)
                     72: #  include <unistd.h>
                     73: #  include <stdlib.h>
                     74: #  include <string.h>
                     75: #endif
                     76:
1.1       cgd        77: #include "identd.h"
                     78: #include "error.h"
1.9       msaitoh    79: #include "paths.h"
                     80:
1.1       cgd        81:
                     82: /* Antique unixes do not have these things defined... */
                     83: #ifndef FD_SETSIZE
                     84: #  define FD_SETSIZE 256
                     85: #endif
                     86:
                     87: #ifndef FD_SET
                     88: #  ifndef NFDBITS
                     89: #    define NFDBITS    (sizeof(int) * NBBY)  /* bits per mask */
                     90: #  endif
                     91: #  define FD_SET(n, p)  ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
                     92: #endif
                     93:
                     94: #ifndef FD_ZERO
                     95: #  define FD_ZERO(p)        bzero((char *)(p), sizeof(*(p)))
                     96: #endif
                     97:
                     98:
1.9       msaitoh    99: char *path_unix = (char *) NULL;
                    100: char *path_kmem = (char *) NULL;
1.1       cgd       101:
                    102: int verbose_flag = 0;
                    103: int debug_flag   = 0;
                    104: int syslog_flag  = 0;
                    105: int multi_flag   = 0;
                    106: int other_flag   = 0;
                    107: int unknown_flag = 0;
                    108: int noident_flag = 0;
1.9       msaitoh   109: int crypto_flag  = 0;
1.10      jwise     110: int liar_flag    = 0;
1.1       cgd       111:
                    112: int lport = 0;
                    113: int fport = 0;
                    114:
1.9       msaitoh   115: char *charset_name = (char *) NULL;
                    116: char *indirect_host = (char *) NULL;
                    117: char *indirect_password = (char *) NULL;
1.10      jwise     118: char *lie_string = (char *) NULL;
1.9       msaitoh   119:
                    120: #ifdef ALLOW_FORMAT
                    121:     int format_flag = 0;
                    122:     char *format = "%u";
                    123: #endif
1.1       cgd       124:
                    125: static int child_pid;
                    126:
                    127: #ifdef LOG_DAEMON
                    128: static int syslog_facility = LOG_DAEMON;
                    129: #endif
                    130:
1.9       msaitoh   131: static int comparemem __P((void *, void *, int));
                    132: char *clearmem __P((void *, int));
                    133: static SIGRETURN_TYPE child_handler __P((int));
1.8       mrg       134: int main __P((int, char *[]));
                    135:
1.1       cgd       136: /*
                    137: ** The structure passing convention for GCC is incompatible with
                    138: ** Suns own C compiler, so we define our own inet_ntoa() function.
                    139: ** (This should only affect GCC version 1 I think, a well, this works
                    140: ** for version 2 also so why bother.. :-)
                    141: */
1.9       msaitoh   142: #if defined(__GNUC__) && defined(__sparc__) && !defined(NeXT)
1.1       cgd       143:
                    144: #ifdef inet_ntoa
                    145: #undef inet_ntoa
                    146: #endif
                    147:
                    148: char *inet_ntoa(ad)
1.9       msaitoh   149:     struct in_addr ad;
1.1       cgd       150: {
1.9       msaitoh   151:     unsigned long int s_ad;
                    152:     int a, b, c, d;
                    153:     static char addr[20];
                    154:
                    155:     s_ad = ad.s_addr;
                    156:     d = s_ad % 256;
                    157:     s_ad /= 256;
                    158:     c = s_ad % 256;
                    159:     s_ad /= 256;
                    160:     b = s_ad % 256;
                    161:     a = s_ad / 256;
                    162:     sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
                    163:
                    164:     return addr;
1.1       cgd       165: }
                    166: #endif
                    167:
1.9       msaitoh   168: static int comparemem(vp1, vp2, len)
                    169:      void *vp1;
                    170:      void *vp2;
                    171:      int len;
                    172: {
                    173:     unsigned char *p1 = (unsigned char *) vp1;
                    174:     unsigned char *p2 = (unsigned char *) vp2;
                    175:     int c;
                    176:
                    177:     while (len-- > 0)
                    178:        if ((c = (int) *p1++ - (int) *p2++) != 0)
                    179:            return c;
                    180:
                    181:     return 0;
                    182: }
1.1       cgd       183:
                    184: /*
                    185: ** Return the name of the connecting host, or the IP number as a string.
                    186: */
                    187: char *gethost(addr)
1.9       msaitoh   188:     struct in_addr *addr;
1.1       cgd       189: {
1.9       msaitoh   190:     int i;
                    191:     struct hostent *hp;
1.1       cgd       192:
                    193:
1.9       msaitoh   194:     hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET);
                    195:     if (hp)
                    196:     {
                    197:        char *hname = strdup(hp->h_name);
                    198:
                    199:        if (! hname) {
                    200:            syslog(LOG_ERR, "strdup(%s): %m", hp->h_name);
                    201:            exit(1);
                    202:        }
                    203:        /* Found a IP -> Name match, now try the reverse for security reasons */
                    204:        hp = gethostbyname(hname);
                    205:        (void) free(hname);
                    206:        if (hp)
                    207: #ifdef h_addr
                    208:            for (i = 0; hp->h_addr_list[i]; i++)
                    209:                if (comparemem(hp->h_addr_list[i],
                    210:                               (unsigned char *) addr,
                    211:                               (int) sizeof(struct in_addr)) == 0)
                    212:                    return (char *) hp->h_name;
                    213: #else
                    214:        if (comparemem(hp->h_addr, addr, sizeof(struct in_addr)) == 0)
                    215:            return hp->h_name;
                    216: #endif
                    217:   }
                    218:
                    219:   return inet_ntoa(*addr);
1.1       cgd       220: }
                    221:
1.9       msaitoh   222: #ifdef USE_SIGALARM
1.1       cgd       223: /*
                    224: ** Exit cleanly after our time's up.
                    225: */
                    226: static SIGRETURN_TYPE
1.9       msaitoh   227: alarm_handler(int s)
1.1       cgd       228: {
1.9       msaitoh   229:     if (syslog_flag)
                    230:        syslog(LOG_DEBUG, "SIGALRM triggered, exiting");
                    231:
                    232:     exit(0);
1.1       cgd       233: }
1.9       msaitoh   234: #endif
                    235:
1.1       cgd       236:
1.9       msaitoh   237: #if !defined(hpux) && !defined(__hpux) && !defined(SVR4) && \
                    238:     !defined(_CRAY) && !defined(sco) && !defined(LINUX)
1.1       cgd       239: /*
                    240: ** This is used to clean up zombie child processes
                    241: ** if the -w or -b options are used.
                    242: */
                    243: static SIGRETURN_TYPE
1.9       msaitoh   244: child_handler(dummy)
                    245:        int dummy;
1.1       cgd       246: {
1.9       msaitoh   247: #if defined(NeXT) || (defined(__sgi) && defined(__SVR3))
                    248:     union wait status;
1.1       cgd       249: #else
1.9       msaitoh   250:     int status;
1.1       cgd       251: #endif
1.9       msaitoh   252:     int saved_errno = errno;
                    253:
                    254:     while (wait3(&status, WNOHANG, NULL) > 0)
                    255:        ;
1.1       cgd       256:
1.9       msaitoh   257:     errno = saved_errno;
                    258:
1.1       cgd       259: #ifndef SIGRETURN_TYPE_IS_VOID
1.9       msaitoh   260:     return 0;
1.1       cgd       261: #endif
                    262: }
                    263: #endif
                    264:
1.9       msaitoh   265:
                    266: char *clearmem(vbp, len)
                    267:      void *vbp;
                    268:      int len;
1.1       cgd       269: {
1.9       msaitoh   270:     char *bp = (char *) vbp;
                    271:     char *cp;
1.1       cgd       272:
1.9       msaitoh   273:     cp = bp;
                    274:     while (len-- > 0)
                    275:        *cp++ = 0;
                    276:
                    277:     return bp;
1.1       cgd       278: }
                    279:
                    280:
                    281: /*
                    282: ** Main entry point into this daemon
                    283: */
                    284: int main(argc,argv)
1.9       msaitoh   285:     int argc;
                    286:     char *argv[];
1.1       cgd       287: {
1.9       msaitoh   288:     int i, len;
                    289:     struct sockaddr_in sin;
                    290:     struct in_addr laddr, faddr;
                    291: #ifndef USE_SIGALARM
                    292:     struct timeval tv;
                    293: #endif
                    294:     int one = 1;
                    295:
                    296:     int background_flag = 0;
                    297:     int timeout = 0;
                    298:     char *portno = "113";
                    299:     char *bind_address = (char *) NULL;
                    300:     int set_uid = 0;
                    301:     int set_gid = 0;
                    302:     int inhibit_default_config = 0;
                    303:     int opt_count = 0;         /* Count of option flags */
1.1       cgd       304:
                    305: #ifdef __convex__
1.9       msaitoh   306:     argc--;    /* get rid of extra argument passed by inetd */
1.1       cgd       307: #endif
                    308:
1.9       msaitoh   309:
                    310:     if (isatty(0))
                    311:        background_flag = 1;
                    312:
                    313:     /*
                    314:     ** Prescan the arguments for "-f<config-file>" switches
                    315:     */
                    316:     inhibit_default_config = 0;
                    317:     for (i = 1; i < argc && argv[i][0] == '-'; i++)
                    318:        if (argv[i][1] == 'f')
                    319:            inhibit_default_config = 1;
                    320:
                    321:     /*
                    322:     ** Parse the default config file - if it exists
                    323:     */
                    324:     if (!inhibit_default_config)
                    325:        parse_config(NULL, 1);
1.1       cgd       326:
1.9       msaitoh   327:     /*
                    328:     ** Parse the command line arguments
                    329:     */
                    330:     for (i = 1; i < argc && argv[i][0] == '-'; i++) {
                    331:        opt_count++;
                    332:        switch (argv[i][1])
                    333:        {
                    334:          case 'b':    /* Start as standalone daemon */
                    335:            background_flag = 1;
                    336:            break;
                    337:
                    338:          case 'w':    /* Start from Inetd, wait mode */
                    339:            background_flag = 2;
                    340:            break;
                    341:
                    342:          case 'i':    /* Start from Inetd, nowait mode */
                    343:            background_flag = 0;
                    344:            break;
                    345:
                    346:          case 't':
                    347:            timeout = atoi(argv[i]+2);
                    348:            break;
                    349:
                    350:          case 'p':
                    351:            portno = argv[i]+2;
                    352:            break;
                    353:
                    354:          case 'a':
                    355:            bind_address = argv[i]+2;
                    356:            break;
                    357:
                    358:          case 'u':
                    359:            if (isdigit(argv[i][2]))
                    360:                set_uid = atoi(argv[i]+2);
                    361:            else
                    362:            {
                    363:                struct passwd *pwd;
                    364:
                    365:                pwd = getpwnam(argv[i]+2);
                    366:                if (!pwd)
                    367:                    ERROR1("no such user (%s) for -u option", argv[i]+2);
                    368:                else
                    369:                {
                    370:                    set_uid = pwd->pw_uid;
                    371:                    set_gid = pwd->pw_gid;
                    372:                }
                    373:            }
                    374:            break;
                    375:
                    376:          case 'g':
                    377:            if (isdigit(argv[i][2]))
                    378:                set_gid = atoi(argv[i]+2);
                    379:            else
                    380:            {
                    381:                struct group *grp;
                    382:
                    383:                grp = getgrnam(argv[i]+2);
                    384:                if (!grp)
                    385:                    ERROR1("no such group (%s) for -g option", argv[i]+2);
                    386:                else
                    387:                    set_gid = grp->gr_gid;
                    388:            }
                    389:            break;
                    390:
                    391:          case 'c':
                    392:            charset_name = argv[i]+2;
                    393:            break;
                    394:
                    395:          case 'r':
                    396:            indirect_host = argv[i]+2;
                    397:            break;
                    398:
                    399:          case 'l':    /* Use the Syslog daemon for logging */
                    400:            syslog_flag++;
                    401: #ifdef LOG_DAEMON
                    402:            openlog("identd", LOG_PID, syslog_facility);
                    403: #else
                    404:            openlog("identd", LOG_PID);
                    405: #endif
                    406:            break;
                    407:
                    408:          case 'o':
                    409:            other_flag = 1;
                    410:            break;
                    411:
                    412:          case 'e':
                    413:            unknown_flag = 1;
                    414:            break;
                    415:
                    416:          case 'V':    /* Give version of this daemon */
                    417:            printf("[in.identd, version %s]\r\n", version);
                    418:            exit(0);
                    419:            break;
                    420:
                    421:          case 'v':    /* Be verbose */
                    422:            verbose_flag++;
                    423:            break;
                    424:
                    425:          case 'd':    /* Enable debugging */
                    426:            debug_flag++;
                    427:            break;
                    428:
                    429:          case 'm':    /* Enable multiline queries */
                    430:            multi_flag++;
                    431:            break;
                    432:
                    433:          case 'N':    /* Enable users ".noident" files */
                    434:            noident_flag++;
                    435:            break;
                    436:
                    437: #ifdef INCLUDE_CRYPT
                    438:           case 'C':    /* Enable encryption. */
                    439:            {
                    440:                FILE *keyfile;
                    441:
                    442:                if (argv[i][2])
                    443:                    keyfile = fopen(argv[i]+2, "r");
                    444:                else
                    445:                    keyfile = fopen(PATH_DESKEY, "r");
                    446:
                    447:                if (keyfile == NULL)
                    448:                {
                    449:                    ERROR("cannot open key file for option -C");
                    450:                }
                    451:                else
                    452:                {
                    453:                    char buf[1024];
                    454:
                    455:                    if (fgets(buf, 1024, keyfile) == NULL)
                    456:                    {
                    457:                        ERROR("cannot read key file for option -C");
                    458:                    }
                    459:                    else
                    460:                    {
                    461:                        init_encryption(buf);
                    462:                        crypto_flag++;
                    463:                    }
                    464:                    fclose(keyfile);
                    465:                }
                    466:            }
                    467:             break;
                    468: #endif
                    469:
                    470: #ifdef ALLOW_FORMAT
                    471:          case 'n': /* Compatibility flag - just send the user number */
                    472:            format_flag = 1;
                    473:            format = "%U";
                    474:            break;
                    475:
                    476:           case 'F':    /* Output format */
                    477:            format_flag = 1;
                    478:            format = argv[i]+2;
                    479:            break;
                    480: #endif
1.10      jwise     481:
                    482:          case 'L':     /* lie brazenly */
                    483:            liar_flag = 1;
                    484:            if (*(argv[i]+2) != '\0')
                    485:                lie_string = argv[i]+2;
                    486:            else
                    487: #ifdef DEFAULT_LIE_USER
                    488:                lie_string = DEFAULT_LIE_USER;
                    489: #else
                    490:                ERROR("-L specified with no user name");
                    491: #endif
                    492:            break;
1.9       msaitoh   493:
                    494:          default:
                    495:            ERROR1("Bad option %s", argv[i]);
                    496:            break;
                    497:        }
                    498:     }
                    499:
                    500: #if defined(_AUX_SOURCE) || defined (SUNOS35)
                    501:     /* A/UX 2.0* & SunOS 3.5 calls us with an argument XXXXXXXX.YYYY
                    502:     ** where XXXXXXXXX is the hexadecimal version of the callers
                    503:     ** IP number, and YYYY is the port/socket or something.
                    504:     ** It seems to be impossible to pass arguments to a daemon started
                    505:     ** by inetd.
                    506:     **
                    507:     ** Just in case it is started from something else, then we only
                    508:     ** skip the argument if no option flags have been seen.
                    509:     */
                    510:     if (opt_count == 0)
                    511:        argc--;
                    512: #endif
                    513:
                    514:     /*
                    515:     ** Path to kernel namelist file specified on command line
                    516:     */
                    517:     if (i < argc)
                    518:        path_unix = argv[i++];
                    519:
                    520:     /*
                    521:     ** Path to kernel memory device specified on command line
                    522:     */
                    523:     if (i < argc)
                    524:        path_kmem = argv[i++];
                    525:
                    526:
                    527:     if (i < argc)
                    528:        ERROR1("Too many arguments: ignored from %s", argv[i]);
                    529:
                    530:
                    531:     /*
                    532:     ** We used to call k_open here. But then the file descriptor
                    533:     ** kd->fd open on /dev/kmem is shared by all child processes.
                    534:     ** From the fork(2) man page:
                    535:     **      o  The child process has its own copy of the parent's descriptors.  These
                    536:     **         descriptors reference the same underlying objects.  For instance, file
                    537:     **         pointers in file objects are shared between the child and the parent
                    538:     **         so that an lseek(2) on a descriptor in the child process can affect a
                    539:     **         subsequent read(2) or write(2) by the parent.
                    540:     ** Thus with concurrent (simultaneous) identd client processes,
                    541:     ** they step on each other's toes when they use kvm_read.
                    542:     **
                    543:     ** Calling k_open here was a mistake for another reason too: we
                    544:     ** did not yet honor -u and -g options. Presumably we are
                    545:     ** running as root (unless the in.identd file is setuid), and
                    546:     ** then we can open kmem regardless of -u and -g values.
                    547:     **
                    548:     **
                    549:     ** Open the kernel memory device and read the nlist table
                    550:     **
                    551:     **     if (k_open() < 0)
                    552:     **                 ERROR("main: k_open");
                    553:     */
                    554:
                    555:     /*
                    556:     ** Do the special handling needed for the "-b" flag
                    557:     */
                    558:     if (background_flag == 1)
1.1       cgd       559:     {
1.9       msaitoh   560:        struct sockaddr_in addr;
                    561:        struct servent *sp;
                    562:        int fd;
                    563:
                    564:
                    565:        if (!debug_flag)
                    566:        {
                    567:            if (fork())
                    568:                exit(0);
                    569:
                    570:            close(0);
                    571:            close(1);
                    572:            close(2);
                    573:
                    574:            if (fork())
                    575:                exit(0);
                    576:        }
                    577:
                    578:        fd = socket(AF_INET, SOCK_STREAM, 0);
                    579:        if (fd == -1)
                    580:            ERROR("main: socket");
                    581:
                    582:        if (fd != 0)
                    583:            dup2(fd, 0);
                    584:
                    585:        clearmem((void *) &addr, (int) sizeof(addr));
                    586:
                    587:        addr.sin_family = AF_INET;
                    588:        if (bind_address == (char *) NULL)
                    589:            addr.sin_addr.s_addr = htonl(INADDR_ANY);
1.1       cgd       590:        else
1.9       msaitoh   591:        {
                    592:            if (isdigit(bind_address[0]))
                    593:                addr.sin_addr.s_addr = inet_addr(bind_address);
                    594:            else
                    595:            {
                    596:                struct hostent *hp;
                    597:
                    598:                hp = gethostbyname(bind_address);
                    599:                if (!hp)
                    600:                    ERROR1("no such address (%s) for -a switch", bind_address);
                    601:
                    602:                /* This is ugly, should use memcpy() or bcopy() but... */
                    603:                addr.sin_addr.s_addr = * (unsigned long *) (hp->h_addr);
                    604:            }
1.1       cgd       605:        }
                    606:
1.9       msaitoh   607:        if (isdigit(portno[0]))
                    608:            addr.sin_port = htons(atoi(portno));
1.1       cgd       609:        else
1.9       msaitoh   610:        {
                    611:            sp = getservbyname(portno, "tcp");
                    612:            if (sp == (struct servent *) NULL)
                    613:                ERROR1("main: getservbyname: %s", portno);
                    614:            addr.sin_port = sp->s_port;
                    615:        }
1.1       cgd       616:
1.9       msaitoh   617: #ifdef SO_REUSEADDR
                    618:        setsockopt(0, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one));
                    619: #endif
1.1       cgd       620:
1.9       msaitoh   621:        if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
                    622:            ERROR("main: bind");
1.1       cgd       623:     }
1.9       msaitoh   624:
                    625:     if (background_flag)
                    626:     {
                    627:       if (listen(0, 3) < 0)
                    628:        ERROR("main: listen");
                    629:     }
                    630:
                    631:     if (set_gid)
1.1       cgd       632:     {
1.9       msaitoh   633:        if (setgid(set_gid) == -1)
                    634:            ERROR("main: setgid");
                    635:        /* Call me paranoid... PSz */
                    636:        if (getgid() != set_gid)
                    637:            ERROR2("main: setgid failed: wanted %d, got GID %d", set_gid, getgid());
                    638:        if (getegid() != set_gid)
                    639:            ERROR2("main: setgid failed: wanted %d, got EGID %d", set_gid, getegid());
1.1       cgd       640:     }
1.9       msaitoh   641:
                    642:     if (set_uid)
1.1       cgd       643:     {
1.9       msaitoh   644:        if (setuid(set_uid) == -1)
                    645:            ERROR("main: setuid");
                    646:        /* Call me paranoid... PSz */
                    647:        if (getuid() != set_uid)
                    648:            ERROR2("main: setuid failed: wanted %d, got UID %d", set_uid, getuid());
                    649:        if (geteuid() != set_uid)
                    650:            ERROR2("main: setuid failed: wanted %d, got EUID %d", set_uid, geteuid());
1.1       cgd       651:     }
                    652:
                    653:     /*
1.9       msaitoh   654:     ** Do some special handling if the "-b" or "-w" flags are used
                    655:     */
                    656:     if (background_flag)
                    657:     {
                    658:        int nfds, fd;
                    659:        fd_set read_set;
                    660:        struct sockaddr sad;
                    661:        int sadlen;
                    662:
                    663:
                    664:        /*
                    665:        ** Set up the SIGCHLD signal child termination handler so
                    666:        ** that we can avoid zombie processes hanging around and
                    667:        ** handle childs terminating before being able to complete the
                    668:        ** handshake.
                    669:        */
                    670: #if (defined(SVR4) || defined(hpux) || defined(__hpux) || defined(IRIX) || \
                    671:      defined(_CRAY) || defined(_AUX_SOURCE) || defined(sco) || \
                    672:         defined(LINUX))
                    673:        signal(SIGCHLD, SIG_IGN);
1.1       cgd       674: #else
1.9       msaitoh   675:        signal(SIGCHLD, child_handler);
1.1       cgd       676: #endif
                    677:
1.9       msaitoh   678:        /*
                    679:        ** Loop and dispatch client handling processes
                    680:        */
                    681:        do
                    682:        {
                    683: #ifdef USE_SIGALARM
                    684:            /*
                    685:            ** Terminate if we've been idle for 'timeout' seconds
                    686:            */
                    687:            if (background_flag == 2 && timeout)
                    688:            {
                    689:                signal(SIGALRM, alarm_handler);
                    690:                alarm(timeout);
                    691:            }
                    692: #endif
1.1       cgd       693:
1.9       msaitoh   694:            /*
                    695:            ** Wait for a connection request to occur.
                    696:            ** Ignore EINTR (Interrupted System Call).
                    697:            */
                    698:            do
                    699:            {
                    700:                FD_ZERO(&read_set);
                    701:                FD_SET(0, &read_set);
                    702:
                    703: #ifndef USE_SIGALARM
                    704:                if (timeout)
                    705:                {
                    706:                    tv.tv_sec = timeout;
                    707:                    tv.tv_usec = 0;
                    708: #ifdef __hpux
                    709:                    nfds = select(FD_SETSIZE,
                    710:                                  (int *) &read_set, NULL, NULL, &tv);
                    711: #else
                    712:                    nfds = select(FD_SETSIZE, &read_set, NULL, NULL, &tv);
                    713: #endif
                    714:                }
                    715:                else
                    716: #endif
1.1       cgd       717:
1.9       msaitoh   718: #ifdef __hpux
                    719:                nfds = select(FD_SETSIZE, (int *) &read_set, NULL, NULL, NULL);
                    720: #else
                    721:                nfds = select(FD_SETSIZE, &read_set, NULL, NULL, NULL);
                    722: #endif
                    723:            } while (nfds < 0  && errno == EINTR);
                    724:
                    725:            /*
1.11    ! wiz       726:            ** An error occurred in select? Just die
1.9       msaitoh   727:            */
                    728:            if (nfds < 0)
                    729:                ERROR("main: select");
                    730:
                    731:            /*
                    732:            ** Timeout limit reached. Exit nicely
                    733:            */
                    734:            if (nfds == 0)
                    735:                exit(0);
1.1       cgd       736:
1.9       msaitoh   737: #ifdef USE_SIGALARM
                    738:            /*
                    739:            ** Disable the alarm timeout
                    740:            */
                    741:            alarm(0);
                    742: #endif
1.1       cgd       743:
1.9       msaitoh   744:            /*
                    745:            ** Accept the new client
                    746:            */
                    747:            sadlen = sizeof(sad);
                    748:            errno = 0;
                    749:            fd = accept(0, &sad, &sadlen);
                    750:            if (fd == -1)
                    751:                ERROR1("main: accept. errno = %d", errno);
1.1       cgd       752:
1.9       msaitoh   753:            /*
                    754:            ** And fork, then close the fd if we are the parent.
                    755:            */
                    756:            child_pid = fork();
                    757:        } while (child_pid && (close(fd), 1));
                    758:
                    759:        /*
                    760:        ** We are now in child, the parent has returned to "do" above.
                    761:        */
                    762:        if (dup2(fd, 0) == -1)
                    763:            ERROR("main: dup2: failed fd 0");
                    764:
                    765:        if (dup2(fd, 1) == -1)
                    766:            ERROR("main: dup2: failed fd 1");
                    767:
                    768:        if (dup2(fd, 2) == -1)
                    769:            ERROR("main: dup2: failed fd 2");
                    770:     }
                    771:
1.1       cgd       772:     /*
1.9       msaitoh   773:     ** Get foreign internet address
1.1       cgd       774:     */
1.9       msaitoh   775:     len = sizeof(sin);
                    776:     if (getpeername(0, (struct sockaddr *) &sin, &len) == -1)
                    777:     {
                    778:        /*
                    779:        ** A user has tried to start us from the command line or
                    780:        ** the network link died, in which case this message won't
                    781:        ** reach to other end anyway, so lets give the poor user some
                    782:        ** errors.
                    783:        */
                    784:        perror("in.identd: getpeername()");
                    785:        exit(1);
                    786:     }
                    787:
                    788:     faddr = sin.sin_addr;
1.1       cgd       789:
                    790:
1.9       msaitoh   791: #ifdef STRONG_LOG
                    792:     if (syslog_flag)
                    793:        syslog(LOG_INFO, "Connection from %s", gethost(&faddr));
                    794: #endif
1.1       cgd       795:
1.9       msaitoh   796:
                    797:     /*
                    798:     ** Get local internet address
1.1       cgd       799:     */
1.9       msaitoh   800:     len = sizeof(sin);
                    801: #ifdef ATTSVR4
                    802:     if (t_getsockname(0, (struct sockaddr *) &sin, &len) == -1)
1.1       cgd       803: #else
1.9       msaitoh   804:     if (getsockname(0, (struct sockaddr *) &sin, &len) == -1)
1.1       cgd       805: #endif
1.9       msaitoh   806:     {
                    807:        /*
                    808:        ** We can just die here, because if this fails then the
                    809:        ** network has died and we haven't got anyone to return
                    810:        ** errors to.
                    811:        */
                    812:        exit(1);
                    813:     }
                    814:     laddr = sin.sin_addr;
1.1       cgd       815:
                    816:
                    817:     /*
1.9       msaitoh   818:     ** Get the local/foreign port pair from the luser
1.1       cgd       819:     */
1.9       msaitoh   820:     parse(stdin, &laddr, &faddr);
1.1       cgd       821:
1.9       msaitoh   822:     exit(0);
1.1       cgd       823: }

CVSweb <webmaster@jp.NetBSD.org>