Annotation of 43BSD/etc/timed/timed.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1985 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) 1985 Regents of the University of California.\n\
        !            10:  All rights reserved.\n";
        !            11: #endif not lint
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)timed.c    2.10 (Berkeley) 6/2/86";
        !            15: #endif not lint
        !            16: 
        !            17: #include "globals.h"
        !            18: #define TSPTYPES
        !            19: #include <protocols/timed.h>
        !            20: #include <net/if.h>
        !            21: #include <sys/file.h>
        !            22: #include <sys/ioctl.h>
        !            23: #include <setjmp.h>
        !            24: 
        !            25: int id;
        !            26: int trace;
        !            27: int sock, sock_raw;
        !            28: int status = 0;
        !            29: int backoff;
        !            30: int slvcount;                          /* no. of slaves controlled by master */
        !            31: int machup;
        !            32: u_short sequence;                      /* sequence number */
        !            33: long delay1;
        !            34: long delay2;
        !            35: long random();
        !            36: char hostname[MAXHOSTNAMELEN];
        !            37: struct host hp[NHOSTS];
        !            38: char tracefile[] = "/usr/adm/timed.log";
        !            39: FILE *fd;
        !            40: jmp_buf jmpenv;
        !            41: struct netinfo *nettab = NULL;
        !            42: int nslavenets;                /* Number of networks were I could be a slave */
        !            43: int nmasternets;       /* Number of networks were I could be a master */
        !            44: int nignorednets;      /* Number of ignored networks */
        !            45: int nnets;             /* Number of networks I am connected to */
        !            46: struct netinfo *slavenet;
        !            47: struct netinfo *firstslavenet();
        !            48: int Mflag;
        !            49: int justquit = 0;
        !            50: 
        !            51: struct nets {
        !            52:        char *name;
        !            53:        long net;
        !            54:        struct nets *next;
        !            55: } *nets = (struct nets *)0;
        !            56: 
        !            57: /*
        !            58:  * The timedaemons synchronize the clocks of hosts in a local area network.
        !            59:  * One daemon runs as master, all the others as slaves. The master
        !            60:  * performs the task of computing clock differences and sends correction
        !            61:  * values to the slaves. 
        !            62:  * Slaves start an election to choose a new master when the latter disappears 
        !            63:  * because of a machine crash, network partition, or when killed.
        !            64:  * A resolution protocol is used to kill all but one of the masters
        !            65:  * that happen to exist in segments of a partitioned network when the 
        !            66:  * network partition is fixed.
        !            67:  *
        !            68:  * Authors: Riccardo Gusella & Stefano Zatti
        !            69:  */
        !            70: 
        !            71: main(argc, argv)
        !            72: int argc;
        !            73: char **argv;
        !            74: {
        !            75:        int on;
        !            76:        int ret;
        !            77:        long seed;
        !            78:        int nflag, iflag;
        !            79:        struct timeval time;
        !            80:        struct servent *srvp;
        !            81:        long casual();
        !            82:        char *date();
        !            83:        int n;
        !            84:        int flag;
        !            85:        char buf[BUFSIZ];
        !            86:        struct ifconf ifc;
        !            87:        struct ifreq ifreq, *ifr;
        !            88:        register struct netinfo *ntp;
        !            89:        struct netinfo *ntip;
        !            90:        struct netinfo *savefromnet;
        !            91:        struct sockaddr_in server;
        !            92:        u_short port;
        !            93:        uid_t getuid();
        !            94: 
        !            95: #ifdef lint
        !            96:        ntip = NULL;
        !            97: #endif
        !            98: 
        !            99:        Mflag = 0;
        !           100:        on = 1;
        !           101:        backoff = 1;
        !           102:        trace = OFF;
        !           103:        nflag = OFF;
        !           104:        iflag = OFF;
        !           105:        openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON);
        !           106: 
        !           107:        if (getuid() != 0) {
        !           108:                fprintf(stderr, "Timed: not superuser\n");
        !           109:                exit(1);
        !           110:        }
        !           111: 
        !           112:        while (--argc > 0 && **++argv == '-') {
        !           113:                (*argv)++;
        !           114:                do {
        !           115:                        switch (**argv) {
        !           116: 
        !           117:                        case 'M':
        !           118:                                Mflag = 1; 
        !           119:                                break;
        !           120:                        case 't':
        !           121:                                trace = ON; 
        !           122:                                break;
        !           123:                        case 'n':
        !           124:                                argc--, argv++;
        !           125:                                if (iflag) {
        !           126:                                        fprintf(stderr,
        !           127:                                    "timed: -i and -n make no sense together\n");
        !           128:                                } else {
        !           129:                                        nflag = ON;
        !           130:                                        addnetname(*argv);
        !           131:                                }
        !           132:                                while (*(++(*argv)+1)) ;
        !           133:                                break;
        !           134:                        case 'i':
        !           135:                                argc--, argv++;
        !           136:                                if (nflag) {
        !           137:                                        fprintf(stderr,
        !           138:                                    "timed: -i and -n make no sense together\n");
        !           139:                                } else {
        !           140:                                        iflag = ON;
        !           141:                                        addnetname(*argv);
        !           142:                                }
        !           143:                                while (*(++(*argv)+1)) ;
        !           144:                                break;
        !           145:                        default:
        !           146:                                fprintf(stderr, "timed: -%c: unknown option\n", 
        !           147:                                                        **argv);
        !           148:                                break;
        !           149:                        }
        !           150:                } while (*++(*argv));
        !           151:        }
        !           152: 
        !           153: #ifndef DEBUG
        !           154:        if (fork())
        !           155:                exit(0);
        !           156:        { int s;
        !           157:          for (s = getdtablesize(); s >= 0; --s)
        !           158:                (void) close(s);
        !           159:          (void) open("/dev/null", 0);
        !           160:          (void) dup2(0, 1);
        !           161:          (void) dup2(0, 2);
        !           162:          s = open("/dev/tty", 2);
        !           163:          if (s >= 0) {
        !           164:                (void) ioctl(s, TIOCNOTTY, (char *)0);
        !           165:                (void) close(s);
        !           166:          }
        !           167:        }
        !           168: #endif
        !           169: 
        !           170:        if (trace == ON) {
        !           171:                fd = fopen(tracefile, "w");
        !           172:                setlinebuf(fd);
        !           173:                fprintf(fd, "Tracing started on: %s\n\n", 
        !           174:                                        date());
        !           175:        }
        !           176: 
        !           177:        srvp = getservbyname("timed", "udp");
        !           178:        if (srvp == 0) {
        !           179:                syslog(LOG_CRIT, "unknown service 'timed/udp'");
        !           180:                exit(1);
        !           181:        }
        !           182:        port = srvp->s_port;
        !           183:        server.sin_port = srvp->s_port;
        !           184:        server.sin_family = AF_INET;
        !           185:        sock = socket(AF_INET, SOCK_DGRAM, 0);
        !           186:        if (sock < 0) {
        !           187:                syslog(LOG_ERR, "socket: %m");
        !           188:                exit(1);
        !           189:        }
        !           190:        if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, 
        !           191:                                                        sizeof(on)) < 0) {
        !           192:                syslog(LOG_ERR, "setsockopt: %m");
        !           193:                exit(1);
        !           194:        }
        !           195:        if (bind(sock, &server, sizeof(server))) {
        !           196:                if (errno == EADDRINUSE)
        !           197:                        syslog(LOG_ERR, "server already running");
        !           198:                else
        !           199:                        syslog(LOG_ERR, "bind: %m");
        !           200:                exit(1);
        !           201:        }
        !           202: 
        !           203:        /* choose a unique seed for random number generation */
        !           204:        (void)gettimeofday(&time, (struct timezone *)0);
        !           205:        seed = time.tv_sec + time.tv_usec;
        !           206:        srandom(seed);
        !           207: 
        !           208:        sequence = random();     /* initial seq number */
        !           209: 
        !           210:        /* rounds kernel variable time to multiple of 5 ms. */
        !           211:        time.tv_sec = 0;
        !           212:        time.tv_usec = -((time.tv_usec/1000) % 5) * 1000;
        !           213:        (void)adjtime(&time, (struct timeval *)0);
        !           214: 
        !           215:        id = getpid();
        !           216: 
        !           217:        if (gethostname(hostname, sizeof(hostname) - 1) < 0) {
        !           218:                syslog(LOG_ERR, "gethostname: %m");
        !           219:                exit(1);
        !           220:        }
        !           221:        hp[0].name = hostname;
        !           222: 
        !           223:        if (nflag || iflag) {
        !           224:                struct netent *getnetent();
        !           225:                struct netent *n;
        !           226:                struct nets *np;
        !           227:                for ( np = nets ; np ; np = np->next) {
        !           228:                        n = getnetbyname(np->name);
        !           229:                        if (n == NULL) {
        !           230:                                syslog(LOG_ERR, "getnetbyname: unknown net %s",
        !           231:                                        np->name);
        !           232:                                exit(1);
        !           233:                        }
        !           234:                        np->net = n->n_net;
        !           235:                }
        !           236:        }
        !           237:        ifc.ifc_len = sizeof(buf);
        !           238:        ifc.ifc_buf = buf;
        !           239:        if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
        !           240:                syslog(LOG_ERR, "get interface configuration: %m");
        !           241:                exit(1);
        !           242:        }
        !           243:        n = ifc.ifc_len/sizeof(struct ifreq);
        !           244:        ntp = NULL;
        !           245:        for (ifr = ifc.ifc_req; n > 0; n--, ifr++) {
        !           246:                if (ifr->ifr_addr.sa_family != AF_INET)
        !           247:                        continue;
        !           248:                ifreq = *ifr;
        !           249:                if (ntp == NULL)
        !           250:                        ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
        !           251:                ntp->my_addr = 
        !           252:                        ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
        !           253:                if (ioctl(sock, SIOCGIFFLAGS, 
        !           254:                                        (char *)&ifreq) < 0) {
        !           255:                        syslog(LOG_ERR, "get interface flags: %m");
        !           256:                        continue;
        !           257:                }
        !           258:                if ((ifreq.ifr_flags & IFF_UP) == 0 ||
        !           259:                        ((ifreq.ifr_flags & IFF_BROADCAST) == 0 &&
        !           260:                        (ifreq.ifr_flags & IFF_POINTOPOINT) == 0)) {
        !           261:                        continue;
        !           262:                }
        !           263:                if (ifreq.ifr_flags & IFF_BROADCAST)
        !           264:                        flag = 1;
        !           265:                else
        !           266:                        flag = 0;
        !           267:                if (ioctl(sock, SIOCGIFNETMASK, 
        !           268:                                        (char *)&ifreq) < 0) {
        !           269:                        syslog(LOG_ERR, "get netmask: %m");
        !           270:                        continue;
        !           271:                }
        !           272:                ntp->mask = ((struct sockaddr_in *)
        !           273:                        &ifreq.ifr_addr)->sin_addr.s_addr;
        !           274:                if (flag) {
        !           275:                        if (ioctl(sock, SIOCGIFBRDADDR, 
        !           276:                                                (char *)&ifreq) < 0) {
        !           277:                                syslog(LOG_ERR, "get broadaddr: %m");
        !           278:                                continue;
        !           279:                        }
        !           280:                        ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
        !           281:                } else {
        !           282:                        if (ioctl(sock, SIOCGIFDSTADDR, 
        !           283:                                                (char *)&ifreq) < 0) {
        !           284:                                syslog(LOG_ERR, "get destaddr: %m");
        !           285:                                continue;
        !           286:                        }
        !           287:                        ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr;
        !           288:                }
        !           289:                ntp->dest_addr.sin_port = port;
        !           290:                if (nflag || iflag) {
        !           291:                        u_long addr, mask;
        !           292:                        struct nets *n;
        !           293: 
        !           294:                        addr = ntohl(ntp->dest_addr.sin_addr.s_addr);
        !           295:                        mask = ntohl(ntp->mask);
        !           296:                        while ((mask & 1) == 0) {
        !           297:                                addr >>= 1;
        !           298:                                mask >>= 1;
        !           299:                        }
        !           300:                        for (n = nets ; n ; n = n->next)
        !           301:                                if (addr == n->net)
        !           302:                                        break;
        !           303:                        if (nflag && !n || iflag && n)
        !           304:                                continue;
        !           305:                }
        !           306:                ntp->net = ntp->mask & ntp->dest_addr.sin_addr.s_addr;
        !           307:                ntp->next = NULL;
        !           308:                if (nettab == NULL) {
        !           309:                        nettab = ntp;
        !           310:                } else {
        !           311:                        ntip->next = ntp;
        !           312:                }
        !           313:                ntip = ntp;
        !           314:                ntp = NULL;
        !           315:        }
        !           316:        if (ntp)
        !           317:                (void) free((char *)ntp);
        !           318:        if (nettab == NULL) {
        !           319:                syslog(LOG_ERR, "No network usable");
        !           320:                exit(1);
        !           321:        }
        !           322: 
        !           323:        for (ntp = nettab; ntp != NULL; ntp = ntp->next)
        !           324:                lookformaster(ntp);
        !           325:        setstatus();
        !           326:        /*
        !           327:         * Take care of some basic initialization.
        !           328:         */
        !           329:        /* us. delay to be used in response to broadcast */
        !           330:        delay1 = casual((long)10000, 200000);   
        !           331: 
        !           332:        /* election timer delay in secs. */
        !           333:        delay2 = casual((long)MINTOUT, (long)MAXTOUT);
        !           334: 
        !           335:        if (Mflag) {
        !           336:                /* open raw socket used to measure time differences */
        !           337:                sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 
        !           338:                if (sock_raw < 0)  {
        !           339:                        syslog(LOG_ERR, "opening raw socket: %m");
        !           340:                        exit (1);
        !           341:                }
        !           342: 
        !           343:                /*
        !           344:                 * number (increased by 1) of slaves controlled by master: 
        !           345:                 * used in master.c, candidate.c, networkdelta.c, and 
        !           346:                 * correct.c 
        !           347:                 */
        !           348:                slvcount = 1;
        !           349:                ret = setjmp(jmpenv);
        !           350: 
        !           351:                switch (ret) {
        !           352: 
        !           353:                case 0: 
        !           354:                        makeslave(firstslavenet());
        !           355:                        setstatus();
        !           356:                        break;
        !           357:                case 1: 
        !           358:                        /* Just lost our master */
        !           359:                        setstatus();
        !           360:                        slavenet->status = election(slavenet);
        !           361:                        checkignorednets();
        !           362:                        setstatus();
        !           363:                        if (slavenet->status == MASTER)
        !           364:                                makeslave(firstslavenet());
        !           365:                        else
        !           366:                                makeslave(slavenet);
        !           367:                        setstatus();
        !           368:                        break;
        !           369:                case 2:
        !           370:                        /* Just been told to quit */
        !           371:                        fromnet->status = SLAVE;
        !           372:                        setstatus();
        !           373:                        savefromnet = fromnet;
        !           374:                        rmnetmachs(fromnet);
        !           375:                        checkignorednets();
        !           376:                        if (slavenet)
        !           377:                                makeslave(slavenet);
        !           378:                        else
        !           379:                                makeslave(savefromnet);
        !           380:                        setstatus();
        !           381:                        justquit = 1;
        !           382:                        break;
        !           383:                        
        !           384:                default:
        !           385:                        /* this should not happen */
        !           386:                        syslog(LOG_ERR, "Attempt to enter invalid state");
        !           387:                        break;
        !           388:                }
        !           389:                        
        !           390:                if (status == MASTER) 
        !           391:                        master();
        !           392:                else 
        !           393:                        slave();
        !           394:        } else {
        !           395:                /* if Mflag is not set timedaemon is forced to act as a slave */
        !           396:                status = SLAVE;
        !           397:                if (setjmp(jmpenv)) {
        !           398:                        setstatus();
        !           399:                        checkignorednets();
        !           400:                }
        !           401:                makeslave(firstslavenet());
        !           402:                for (ntp = nettab; ntp != NULL; ntp = ntp->next)
        !           403:                        if (ntp->status == MASTER)
        !           404:                                ntp->status = IGNORE;
        !           405:                setstatus();
        !           406:                slave();
        !           407:        }
        !           408: }
        !           409: 
        !           410: /*
        !           411:  * Try to become master over ignored nets..
        !           412:  */
        !           413: checkignorednets()
        !           414: {
        !           415:        register struct netinfo *ntp;
        !           416:        for (ntp = nettab; ntp != NULL; ntp = ntp->next)
        !           417:                if (ntp->status == IGNORE)
        !           418:                        lookformaster(ntp);
        !           419: }
        !           420: 
        !           421: lookformaster(ntp)
        !           422:        register struct netinfo *ntp;
        !           423: {
        !           424:        struct tsp resp, conflict, *answer, *readmsg(), *acksend();
        !           425:        struct timeval time;
        !           426:        char mastername[MAXHOSTNAMELEN];
        !           427:        struct sockaddr_in masteraddr;
        !           428: 
        !           429:        ntp->status = SLAVE;
        !           430:        /* look for master */
        !           431:        resp.tsp_type = TSP_MASTERREQ;
        !           432:        (void)strcpy(resp.tsp_name, hostname);
        !           433:        answer = acksend(&resp, &ntp->dest_addr, (char *)ANYADDR, 
        !           434:            TSP_MASTERACK, ntp);
        !           435:        if (answer == NULL) {
        !           436:                /*
        !           437:                 * Various conditions can cause conflict: race between
        !           438:                 * two just started timedaemons when no master is
        !           439:                 * present, or timedaemon started during an election.
        !           440:                 * Conservative approach is taken: give up and became a
        !           441:                 * slave postponing election of a master until first
        !           442:                 * timer expires.
        !           443:                 */
        !           444:                time.tv_sec = time.tv_usec = 0;
        !           445:                answer = readmsg(TSP_MASTERREQ, (char *)ANYADDR,
        !           446:                    &time, ntp);
        !           447:                if (answer != NULL) {
        !           448:                        ntp->status = SLAVE;
        !           449:                        return;
        !           450:                }
        !           451: 
        !           452:                time.tv_sec = time.tv_usec = 0;
        !           453:                answer = readmsg(TSP_MASTERUP, (char *)ANYADDR,
        !           454:                    &time, ntp);
        !           455:                if (answer != NULL) {
        !           456:                        ntp->status = SLAVE;
        !           457:                        return;
        !           458:                }
        !           459: 
        !           460:                time.tv_sec = time.tv_usec = 0;
        !           461:                answer = readmsg(TSP_ELECTION, (char *)ANYADDR,
        !           462:                    &time, ntp);
        !           463:                if (answer != NULL) {
        !           464:                        ntp->status = SLAVE;
        !           465:                        return;
        !           466:                }
        !           467:                ntp->status = MASTER;
        !           468:        } else {
        !           469:                (void)strcpy(mastername, answer->tsp_name);
        !           470:                masteraddr = from;
        !           471: 
        !           472:                /*
        !           473:                 * If network has been partitioned, there might be other
        !           474:                 * masters; tell the one we have just acknowledged that 
        !           475:                 * it has to gain control over the others. 
        !           476:                 */
        !           477:                time.tv_sec = 0;
        !           478:                time.tv_usec = 300000;
        !           479:                answer = readmsg(TSP_MASTERACK, (char *)ANYADDR, &time,
        !           480:                    ntp);
        !           481:                /*
        !           482:                 * checking also not to send CONFLICT to ack'ed master
        !           483:                 * due to duplicated MASTERACKs
        !           484:                 */
        !           485:                if (answer != NULL && 
        !           486:                    strcmp(answer->tsp_name, mastername) != 0) {
        !           487:                        conflict.tsp_type = TSP_CONFLICT;
        !           488:                        (void)strcpy(conflict.tsp_name, hostname);
        !           489:                        if (acksend(&conflict, &masteraddr, mastername,
        !           490:                            TSP_ACK, (struct netinfo *)NULL) == NULL) {
        !           491:                                syslog(LOG_ERR, 
        !           492:                                    "error on sending TSP_CONFLICT");
        !           493:                                exit(1);
        !           494:                        }
        !           495:                }
        !           496:        }
        !           497: }
        !           498: /*
        !           499:  * based on the current network configuration, set the status, and count
        !           500:  * networks;
        !           501:  */
        !           502: setstatus()
        !           503: {
        !           504:        register struct netinfo *ntp;
        !           505: 
        !           506:        status = 0;
        !           507:        nmasternets = nslavenets = nnets = nignorednets = 0;
        !           508:        if (trace)
        !           509:                fprintf(fd, "Net status:\n");
        !           510:        for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
        !           511:                switch ((int)ntp->status) {
        !           512:                  case MASTER:
        !           513:                        nmasternets++;
        !           514:                        break;
        !           515:                  case SLAVE:
        !           516:                        nslavenets++;
        !           517:                        break;
        !           518:                  case IGNORE:
        !           519:                        nignorednets++;
        !           520:                        break;
        !           521:                }
        !           522:                if (trace) {
        !           523:                        fprintf(fd, "\t%-16s", inet_ntoa(ntp->net));
        !           524:                        switch ((int)ntp->status) {
        !           525:                          case MASTER:
        !           526:                                fprintf(fd, "MASTER\n");
        !           527:                                break;
        !           528:                          case SLAVE:
        !           529:                                fprintf(fd, "SLAVE\n");
        !           530:                                break;
        !           531:                          case IGNORE:
        !           532:                                fprintf(fd, "IGNORE\n");
        !           533:                                break;
        !           534:                          default:
        !           535:                                fprintf(fd, "invalid state %d\n");
        !           536:                                break;
        !           537:                        }
        !           538:                }
        !           539:                nnets++;
        !           540:                status |= ntp->status;
        !           541:        }
        !           542:        status &= ~IGNORE;
        !           543:        if (trace)
        !           544:                fprintf(fd,
        !           545:                      "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n",
        !           546:                      nnets, nmasternets, nslavenets, nignorednets);
        !           547: }
        !           548: 
        !           549: makeslave(net)
        !           550:        struct netinfo *net;
        !           551: {
        !           552:        register struct netinfo *ntp;
        !           553: 
        !           554:        for (ntp = nettab; ntp != NULL; ntp = ntp->next)
        !           555:                if (ntp->status == SLAVE && ntp != net)
        !           556:                        ntp->status = IGNORE;
        !           557:        slavenet = net;
        !           558: }
        !           559:        
        !           560: struct netinfo *
        !           561: firstslavenet()
        !           562: {
        !           563:        register struct netinfo *ntp;
        !           564: 
        !           565:        for (ntp = nettab; ntp != NULL; ntp = ntp->next)
        !           566:                if (ntp->status == SLAVE)
        !           567:                        return (ntp);
        !           568:        return ((struct netinfo *)0);
        !           569: }
        !           570: 
        !           571: /*
        !           572:  * `casual' returns a random number in the range [inf, sup]
        !           573:  */
        !           574: 
        !           575: long
        !           576: casual(inf, sup)
        !           577: long inf;
        !           578: long sup;
        !           579: {
        !           580:        float value;
        !           581: 
        !           582:        value = (float)(random() & 0x7fffffff) / 0x7fffffff;
        !           583:        return(inf + (sup - inf) * value);
        !           584: }
        !           585: 
        !           586: char *
        !           587: date()
        !           588: {
        !           589:        char    *ctime();
        !           590:        struct  timeval tv;
        !           591: 
        !           592:        (void)gettimeofday(&tv, (struct timezone *)0);
        !           593:        return (ctime(&tv.tv_sec));
        !           594: }
        !           595: 
        !           596: addnetname(name)
        !           597:        char *name;
        !           598: {
        !           599:        register struct nets **netlist = &nets;
        !           600: 
        !           601:        while (*netlist)
        !           602:                netlist = &((*netlist)->next);
        !           603:        *netlist = (struct nets *)malloc(sizeof **netlist);
        !           604:        if (*netlist == (struct nets *)0) {
        !           605:                syslog(LOG_ERR, "malloc failed");
        !           606:                exit(1);
        !           607:        }
        !           608:        bzero((char *)*netlist, sizeof(**netlist));
        !           609:        (*netlist)->name = name;
        !           610: }

unix.superglobalmegacorp.com

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