Annotation of researchv10no/cmd/netnews/src/funcs.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * funcs - functions used by both inews and readnews.
        !             3:  */
        !             4: 
        !             5: static char *SccsId = "@(#)funcs.c     2.10    6/24/83";
        !             6: 
        !             7: #include "params.h"
        !             8: 
        !             9: /*
        !            10:  * Append NGDELIM to string.
        !            11:  */
        !            12: ngcat(s)
        !            13: register char *s;
        !            14: {
        !            15:        if (*s) {
        !            16:                while (*s++);
        !            17:                s -= 2;
        !            18:                if (*s++ == NGDELIM)
        !            19:                        return;
        !            20:        }
        !            21:        *s++ = NGDELIM;
        !            22:        *s = '\0';
        !            23: }
        !            24: 
        !            25: /*
        !            26:  * News group matching.
        !            27:  *
        !            28:  * nglist is a list of newsgroups.
        !            29:  * sublist is a list of subscriptions.
        !            30:  * sublist may have "meta newsgroups" in it.
        !            31:  * All fields are NGDELIM separated,
        !            32:  * and there is an NGDELIM at the end of each argument.
        !            33:  *
        !            34:  * Currently implemented glitches:
        !            35:  * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
        !            36:  * If subscription X matches Y, it also matches Y.anything.
        !            37:  */
        !            38: ngmatch(nglist, sublist)
        !            39: register char *nglist, *sublist;
        !            40: {
        !            41:        register char *n, *s;
        !            42:        register int rc;
        !            43: 
        !            44:        rc = FALSE;
        !            45:        for (n = nglist; *n != '\0' && rc == FALSE;) {
        !            46:                for (s = sublist; *s != '\0';) {
        !            47:                        if (*s != NEGCHAR)
        !            48:                                rc |= ptrncmp(s, n);
        !            49:                        else
        !            50:                                rc &= ~ptrncmp(s+1, n);
        !            51:                        while (*s++ != NGDELIM);
        !            52:                }
        !            53:                while (*n++ != NGDELIM);
        !            54:        }
        !            55:        return(rc);
        !            56: }
        !            57: 
        !            58: /*
        !            59:  * Compare two newsgroups for equality.
        !            60:  * The first one may be a "meta" newsgroup.
        !            61:  */
        !            62: ptrncmp(ng1, ng2)
        !            63: register char *ng1, *ng2;
        !            64: {
        !            65:        while (*ng1 != NGDELIM) {
        !            66:                if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
        !            67:                        ng1 += 3;
        !            68:                        while (*ng2 != NGDELIM && *ng2 != '.')
        !            69:                                if (ptrncmp(ng1, ng2++))
        !            70:                                        return(TRUE);
        !            71:                        return (ptrncmp(ng1, ng2));
        !            72:                } else if (*ng1++ != *ng2++)
        !            73:                        return(FALSE);
        !            74:        }
        !            75:        return (*ng2 == '.' || *ng2 == NGDELIM);
        !            76: }
        !            77: 
        !            78: /*
        !            79:  * Remove newsgroups in 'a' not subscribed to by 'b'.
        !            80:  */
        !            81: ngsquash(ap, bp)
        !            82: register char *ap, *bp;
        !            83: {
        !            84:        register char *tp;
        !            85:        char tbuf[BUFLEN];
        !            86: 
        !            87:        /* replace NGDELIM by '\0' in a */
        !            88:        for (tp = ap; *tp != '\0'; tp++)
        !            89:                if (*tp == NGDELIM)
        !            90:                        *tp = '\0';
        !            91:        /* ap = building, tp = checking. */
        !            92:        tp = ap;
        !            93:        while (*tp != '\0') {
        !            94:                ngcat(strcpy(tbuf, tp));
        !            95:                if (ngmatch(tbuf, bp)) {
        !            96:                        while ((*ap++ = *tp++) != '\0')
        !            97:                                ;
        !            98:                        ap[-1] = NGDELIM;
        !            99:                } else
        !           100:                        while (*tp++ != '\0');
        !           101:        }
        !           102:        *ap = '\0';
        !           103: }
        !           104: 
        !           105: /*
        !           106:  * Exec the shell.
        !           107:  * This version resets uid, gid, and umask.
        !           108:  * Called with fsubr(ushell, s, NULL)
        !           109:  */
        !           110: /* ARGSUSED */
        !           111: ushell(s, dummy)
        !           112: char *s, *dummy;
        !           113: {
        !           114:        umask(savmask);
        !           115:        setgid(gid);
        !           116:        setuid(uid);
        !           117:        xshell(s);
        !           118: }
        !           119: 
        !           120: /*
        !           121:  * Exec the shell.
        !           122:  * This version restricts PATH to bin and /usr/bin.
        !           123:  * Called with fsubr(pshell, s, NULL)
        !           124:  */
        !           125: extern char    **environ;
        !           126: 
        !           127: /* ARGSUSED */
        !           128: pshell(s, dummy)
        !           129: char *s, *dummy;
        !           130: {
        !           131:        static char *penv[] = { SYSPATH, NULL };
        !           132:        register char **ep, *p;
        !           133:        register int found;
        !           134: 
        !           135:        found = FALSE;
        !           136:        for (ep = environ; p = *ep; ep++) {
        !           137:                if (strncmp(p, "PATH=", 5) == 0) {
        !           138:                        *ep = penv[0];
        !           139:                        found = TRUE;
        !           140:                }
        !           141:        }
        !           142:        if (!found)
        !           143:                environ = &penv[0];
        !           144:        xshell(s);
        !           145: }
        !           146: 
        !           147: /*
        !           148:  * Exec the shell.
        !           149:  */
        !           150: xshell(s)
        !           151: char *s;
        !           152: {
        !           153:        execl(SHELL, SHELL, "-c", s, 0);
        !           154:        xerror("No shell!");
        !           155: }
        !           156: 
        !           157: /*
        !           158:  * Fork and call a subroutine with two args.
        !           159:  * Return pid without waiting.
        !           160:  */
        !           161: fsubr(f, s1, s2)
        !           162: int (*f)();
        !           163: char *s1, *s2;
        !           164: {
        !           165:        register int pid;
        !           166: 
        !           167:        while ((pid = fork()) == -1)
        !           168:                sleep(1);
        !           169:        if (pid == 0) {
        !           170:                (*f)(s1, s2);
        !           171:                exit(0);
        !           172:        }
        !           173:        return(pid);
        !           174: }
        !           175: 
        !           176: /*
        !           177:  * Wait on a child process.
        !           178:  */
        !           179: fwait(pid)
        !           180: register int pid;
        !           181: {
        !           182:        register int w;
        !           183:        int status;
        !           184:        void (*onhup)(), (*onint)();
        !           185: 
        !           186:        onint = (void (*)()) signal(SIGINT, SIG_IGN);
        !           187:        onhup = (void (*)()) signal(SIGHUP, SIG_IGN);
        !           188:        while ((w = wait(&status)) != pid && w != -1)
        !           189:                ;
        !           190:        if (w == -1)
        !           191:                status = -1;
        !           192:        signal(SIGINT, onint);
        !           193:        signal(SIGHUP, onhup);
        !           194:        return(status);
        !           195: }
        !           196: 
        !           197: /*
        !           198:  * Get user name and home directory.
        !           199:  */
        !           200: getuser()
        !           201: {
        !           202:        static int flag = TRUE;
        !           203:        register struct passwd *p;
        !           204: 
        !           205:        if (flag) {
        !           206:                if ((p = getpwuid(uid)) == NULL)
        !           207:                        xerror("Cannot get user's name");
        !           208:                if (username[0] == 0)
        !           209:                        strcpy(username, p->pw_name);
        !           210:                strcpy(userhome, p->pw_dir);
        !           211:                flag = FALSE;
        !           212:        }
        !           213:        strcpy(header.path, username);
        !           214: }
        !           215: 
        !           216: /*
        !           217:  * Strip trailing newlines, blanks, and tabs from 's'.
        !           218:  * Return TRUE if newline was found, else FALSE.
        !           219:  */
        !           220: nstrip(s)
        !           221: register char *s;
        !           222: {
        !           223:        register char *p;
        !           224:        register int rc;
        !           225: 
        !           226:        rc = FALSE;
        !           227:        p = s;
        !           228:        while (*p)
        !           229:                if (*p++ == '\n')
        !           230:                        rc = TRUE;
        !           231:        while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
        !           232:        *++p = '\0';
        !           233:        return(rc);
        !           234: }
        !           235: 
        !           236: /*
        !           237:  * Delete trailing NGDELIM.
        !           238:  */
        !           239: ngdel(s)
        !           240: register char *s;
        !           241: {
        !           242:        if (*s++) {
        !           243:                while (*s++);
        !           244:                s -= 2;
        !           245:                if (*s == NGDELIM)
        !           246:                        *s = '\0';
        !           247:        }
        !           248: }
        !           249: 
        !           250: /*
        !           251:  * Return the ptr in sp at which the character c appears;
        !           252:  * NULL if not found
        !           253:  *
        !           254:  * These are the v7 index and rindex routines, stolen for portability.
        !           255:  * (Some Unix systems call them strchr and strrchr, notably PWB 2.0
        !           256:  * and its derivitives such as Unix/TS 2.0, Unix 3.0, etc.)  Others,
        !           257:  * like v6, don't have them at all.
        !           258:  */
        !           259: 
        !           260: char *
        !           261: index(sp, c)
        !           262: register char *sp, c;
        !           263: {
        !           264:        do {
        !           265:                if (*sp == c)
        !           266:                        return(sp);
        !           267:        } while (*sp++);
        !           268:        return(NULL);
        !           269: }
        !           270: 
        !           271: /*
        !           272:  * Return the ptr in sp at which the character c last
        !           273:  * appears; NULL if not found
        !           274:  */
        !           275: 
        !           276: char *
        !           277: rindex(sp, c)
        !           278: register char *sp, c;
        !           279: {
        !           280:        register char *r;
        !           281: 
        !           282:        r = NULL;
        !           283:        do {
        !           284:                if (*sp == c)
        !           285:                        r = sp;
        !           286:        } while (*sp++);
        !           287:        return(r);
        !           288: }
        !           289: static FILE    *sysfile;
        !           290: 
        !           291: char *fldget();
        !           292: 
        !           293: /*
        !           294:  * Open SUBFILE.
        !           295:  */
        !           296: s_openr()
        !           297: {
        !           298:        sysfile = xfopen(SUBFILE, "r");
        !           299: }
        !           300: 
        !           301: /*
        !           302:  * Read SUBFILE.
        !           303:  */
        !           304: s_read(sp)
        !           305: register struct srec *sp;
        !           306: {
        !           307:        register char *p;
        !           308: again:
        !           309:        p = bfr;
        !           310:        if (fgets(p, LBUFLEN, sysfile) == NULL)
        !           311:                return(FALSE);
        !           312:        if (!nstrip(p))
        !           313:                xerror("SUBFILE line too long.");
        !           314:        if (*p == '#')
        !           315:                goto again;
        !           316:        sp->s_xmit[0] = '\0';
        !           317:        sp->s_flags[0] = '\0';
        !           318: 
        !           319:        p = fldget(sp->s_name, p);
        !           320:        if (*p++ == '\0')
        !           321:                xerror("Bad SUBFILE line.");
        !           322: /*
        !           323:  * A sys file line reading "ME" means the name of the local system.
        !           324:  */
        !           325:        if (strcmp(sp->s_name, "ME") == 0)
        !           326:                strcpy(sp->s_name, FULLSYSNAME);
        !           327:        p = fldget(sp->s_nbuf, p);
        !           328:        lcase(sp->s_nbuf);
        !           329:        ngcat(sp->s_nbuf);
        !           330:        if (*p++ == '\0')
        !           331:                return(TRUE);
        !           332: 
        !           333:        p = fldget(sp->s_flags, p);
        !           334:        if (*p++ == '\0')
        !           335:                return(TRUE);
        !           336: 
        !           337:        fldget(sp->s_xmit, p);
        !           338:        return(TRUE);
        !           339: }
        !           340: 
        !           341: char *
        !           342: fldget(q, p)
        !           343: register char *q, *p;
        !           344: {
        !           345:        while (*p && *p != ':') {
        !           346:                if (*p == '\\' && p[1]==':')
        !           347:                        p++;
        !           348:                *q++ = *p++;
        !           349:        }
        !           350:        *q = '\0';
        !           351:        return(p);
        !           352: }
        !           353: 
        !           354: /*
        !           355:  * Find the SUBFILE record for a system.
        !           356:  */
        !           357: s_find(sp, system)
        !           358: register struct srec *sp;
        !           359: char *system;
        !           360: {
        !           361:        s_openr();
        !           362:        while (s_read(sp))
        !           363:                if (strncmp(system, sp->s_name, SNLN) == 0) {
        !           364:                        s_close();
        !           365:                        return(TRUE);
        !           366:                }
        !           367:        s_close();
        !           368:        return(FALSE);
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * Close sysfile.
        !           373:  */
        !           374: s_close()
        !           375: {
        !           376:        fclose(sysfile);
        !           377: }
        !           378: 
        !           379: /*
        !           380:  * Local open routine.
        !           381:  */
        !           382: FILE *
        !           383: xfopen(name, mode)
        !           384: register char *name, *mode;
        !           385: {
        !           386:        register FILE *fp;
        !           387:        char    *fname;
        !           388: 
        !           389:        if ((fp = fopen(name, mode)) == NULL) {
        !           390:                fname = rindex(name, '/');
        !           391:                /*
        !           392:                 * IHCC users only see the "filename" that was in trouble, not the
        !           393:                 * whole path.  (for security!)
        !           394:                 */
        !           395: #ifdef IHCC
        !           396:                sprintf(bfr, "Cannot open %s (%s)", ++fname, mode);
        !           397: #else
        !           398:                sprintf(bfr, "Cannot open %s (%s)", name, mode);
        !           399: #endif
        !           400:                xerror(bfr);
        !           401:        }
        !           402:        /* kludge for setuid not being honored for root */
        !           403:        if ((uid == 0) && (duid != 0) && ((mode == "a") || (mode == "w")))
        !           404:                chown(name, duid, dgid);
        !           405:        return(fp);
        !           406: }
        !           407: 
        !           408: time_t
        !           409: cgtdate(datestr)
        !           410: char *datestr;
        !           411: {
        !           412:        time_t  i;
        !           413:        char    junk[40],month[40],day[30],time[60],year[50];
        !           414: 
        !           415:        if ((i = getdate(datestr, (struct timeb *) NULL)) >= 0)
        !           416:                return i;
        !           417:        sscanf(datestr, "%s %s %s %s %s", junk, month, day, time, year);
        !           418:        sprintf(bfr, "%s %s, %s %s", month, day, year, time);
        !           419:        return getdate(bfr, (struct timeb *) NULL);
        !           420: }
        !           421: 
        !           422: lcase(s)
        !           423: register char *s;
        !           424: {
        !           425:        register char *ptr;
        !           426: 
        !           427:        for (ptr = s; *ptr; ptr++)
        !           428:                if (isupper(*ptr))
        !           429:                        *ptr = tolower(*ptr);
        !           430: }
        !           431: 
        !           432: ohwrite(hp, fp)
        !           433: register struct hbuf *hp;
        !           434: register FILE *fp;
        !           435: {
        !           436:        ngdel(strcpy(bfr, hp->nbuf));
        !           437:        fprintf(fp, "A%s\n%s\n%s!%s\n%s\n%s\n", hp->oident, bfr, FULLSYSNAME, hp->path, hp->subdate, hp->title);
        !           438: }
        !           439: 
        !           440: static int hascaught = 0;
        !           441: static catchintr()
        !           442: {
        !           443:        hascaught = 1;
        !           444:        printf("\n");
        !           445:        fflush(stdout);
        !           446: }
        !           447: 
        !           448: /*
        !           449:  * Print a recorded message warning the poor luser what he is doing
        !           450:  * and demand that he understands it before proceeding.  Only do
        !           451:  * this for newsgroups listed in LIBDIR/recording.
        !           452:  */
        !           453: recording(ngrps)
        !           454: char *ngrps;
        !           455: {
        !           456:        char recbuf[100];
        !           457:        FILE *fd;
        !           458:        char nglist[100], fname[100];
        !           459:        char lngrps[100];
        !           460:        char *oldsig;
        !           461:        int  c, n, yes;
        !           462: 
        !           463:        sprintf(recbuf, "%s/%s", LIB, "recording");
        !           464:        fd = fopen(recbuf, "r");
        !           465:        if (fd == NULL)
        !           466:                return 0;
        !           467:        strcpy(lngrps, ngrps);
        !           468:        ngcat(lngrps);
        !           469:        while ((fgets(recbuf, sizeof recbuf, fd)) != NULL) {
        !           470:                sscanf(recbuf, "%s %s", nglist, fname);
        !           471:                ngcat(nglist);
        !           472:                if (ngmatch(lngrps, nglist)) {
        !           473:                        fclose(fd);
        !           474:                        if (fname[0] == '/')
        !           475:                                strcpy(recbuf, fname);
        !           476:                        else
        !           477:                                sprintf(recbuf, "%s/%s", LIB, fname);
        !           478:                        fd = fopen(recbuf, "r");
        !           479:                        if (fd == NULL)
        !           480:                                return 0;
        !           481:                        while ((c = getc(fd)) != EOF)
        !           482:                                putc(c, stderr);
        !           483:                        hascaught = 0;
        !           484:                        oldsig = (char *) signal(SIGINT, catchintr);
        !           485:                        fprintf(stderr, "Do you understand this?  Hit <return> to proceed, <BREAK> to abort: ");
        !           486:                        n = read(2, recbuf, 100);
        !           487:                        c = recbuf[0];
        !           488:                        yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
        !           489:                        signal(SIGINT, oldsig);
        !           490:                        if (hascaught || n <= 0 || !yes)
        !           491:                                return -1;
        !           492:                }
        !           493:        }
        !           494:        return 0;
        !           495: }
        !           496: 
        !           497: /*
        !           498:  * Return a compact representation of the person who posted the given
        !           499:  * message.  A sender or internet name will be used, otherwise
        !           500:  * the last part of the path is used preceeded by an optional ".."
        !           501:  */
        !           502: char *
        !           503: tailpath(hp)
        !           504: struct hbuf *hp;
        !           505: {
        !           506:        char *p, *r;
        !           507:        static char resultbuf[BUFLEN];
        !           508:        char pathbuf[PATHLEN];
        !           509:        char *malloc();
        !           510: 
        !           511:        /*
        !           512:         * This only happens for articles posted by old news software
        !           513:         * in non-internet format.
        !           514:         */
        !           515:        resultbuf[0] = '\0';
        !           516:        strcpy(pathbuf, hp->path);
        !           517:        p = index(pathbuf, ' ');
        !           518:        if (p)
        !           519:                *p = '\0';      /* Chop off trailing " (name)" */
        !           520:        r = rindex(pathbuf, '!');
        !           521:        if (r == 0) {
        !           522:                r = pathbuf;
        !           523:        }
        !           524:        else {
        !           525:                while (r > pathbuf && *--r != '!')
        !           526:                        ;
        !           527:                if (r > pathbuf) {
        !           528:                        r++;
        !           529:                        strcpy(resultbuf, "..!");
        !           530:                }
        !           531:        }
        !           532:        strcat(resultbuf, r);
        !           533:        return resultbuf;
        !           534: }
        !           535: 
        !           536: /*
        !           537:  * Generate the name of the person responsible for posting this article,
        !           538:  * in order to check that two articles were posted by the same person.
        !           539:  */
        !           540: char *
        !           541: senderof(hp)
        !           542: struct hbuf *hp;
        !           543: {
        !           544:        char *q, *tp;
        !           545: 
        !           546:        if (hp->sender[0])
        !           547:                tp = hp->sender;
        !           548:        else if (hp->from[0])
        !           549:                tp = hp->from;
        !           550:        else
        !           551:                tp = tailpath(hp);
        !           552:        
        !           553:        /* Remove full name */
        !           554:        q = index(tp, ' ');
        !           555:        if (q)
        !           556:                *q = '\0';
        !           557: 
        !           558:        q = malloc(strlen(tp) + 1);
        !           559:        strcpy(q, tp);
        !           560:        return q;
        !           561: }
        !           562: 
        !           563: /*
        !           564:  * Returns 1 iff addr looks like a valid internet address
        !           565:  * (as opposed to a routing path).
        !           566:  * The current check insists on *@*.* as a format.
        !           567:  */
        !           568: goodinternet(addr)
        !           569: register char *addr;
        !           570: {
        !           571:        register char *at, *dot;
        !           572: 
        !           573:        at = index(addr, '@');
        !           574:        if (at == NULL)
        !           575:                return 0;
        !           576:        dot = index(at, '.');
        !           577:        if (dot == NULL)
        !           578:                return 0;
        !           579:        /*
        !           580:         * A more thorough check would insist on only alphanumerics
        !           581:         * and dots to the right of the @.
        !           582:         */
        !           583:        return 1;
        !           584: }
        !           585: 
        !           586: rwaccess(fname)
        !           587: char *fname;
        !           588: {
        !           589:        int fd;
        !           590: 
        !           591:        fd = open(fname, 2);
        !           592:        if (fd < 0)
        !           593:                return 0;
        !           594:        close(fd);
        !           595:        return 1;
        !           596: }
        !           597: 
        !           598: exists(fname)
        !           599: char *fname;
        !           600: {
        !           601:        int fd;
        !           602: 
        !           603:        fd = open(fname, 0);
        !           604:        if (fd < 0)
        !           605:                return 0;
        !           606:        close(fd);
        !           607:        return 1;
        !           608: }
        !           609: 
        !           610: prefix(full, pref)
        !           611: register char *full, *pref;
        !           612: {
        !           613:        while (*full++ == *pref++)
        !           614:                ;
        !           615:        if (*--pref == 0)
        !           616:                return 1;
        !           617:        else
        !           618:                return 0;
        !           619: }
        !           620: 
        !           621: char *
        !           622: dirname(ngname)
        !           623: char *ngname;
        !           624: {
        !           625:        static char rbuf[100];
        !           626:        register char *p;
        !           627: 
        !           628:        sprintf(rbuf, "%s/%s", SPOOL, ngname);
        !           629: #ifdef UPWARDCOMPAT
        !           630:        /* First check the old style name. */
        !           631:        if (exists(rbuf))
        !           632:                return rbuf;
        !           633: #endif
        !           634: 
        !           635:        /* Use the new style name for all new stuff. */
        !           636:        for (p=rbuf+strlen(SPOOL); *p; p++)
        !           637:                if (*p == '.')
        !           638:                        *p = '/';
        !           639:        return rbuf;
        !           640: }
        !           641: 
        !           642: #ifdef notdef
        !           643: char *
        !           644: dotname(ngname)
        !           645: char *ngname;
        !           646: {
        !           647:        static char rbuf[100];
        !           648:        register char *p;
        !           649: 
        !           650: #ifdef UPWARDCOMPAT
        !           651:        /* First check the old style name. */
        !           652:        sprintf(rbuf, "%s/.%s", SPOOL, ngname);
        !           653:        if (exists(rbuf))
        !           654:                return rbuf;
        !           655: #endif
        !           656: 
        !           657:        /* Use the new style name for all new stuff. */
        !           658:        sprintf(rbuf, "%s/%s", SPOOL, ngname);
        !           659:        for (p=rbuf+strlen(SPOOL); *p; p++)
        !           660:                if (*p == '.')
        !           661:                        *p = '/';
        !           662:        strcat(rbuf, "/bounds");
        !           663:        return rbuf;
        !           664: }
        !           665: #endif
        !           666: 
        !           667: /*
        !           668:  * Return TRUE iff ngname is a valid newsgroup name, active
        !           669:  * or inactive.
        !           670:  */
        !           671: validng(ngname)
        !           672: char *ngname;
        !           673: {
        !           674:        return exists(dirname(ngname));
        !           675: }
        !           676: 
        !           677: /*
        !           678:  * arpadate is like ctime(3) except that the time is returned in
        !           679:  * an acceptable ARPANET time format instead of ctime format.
        !           680:  */
        !           681: char *
        !           682: arpadate(longtime)
        !           683:        time_t *longtime;
        !           684: {
        !           685:        register char *p, *q, *ud;
        !           686:        char *cp;
        !           687:        register int i;
        !           688:        static char b[40];
        !           689:        struct timeb t;
        !           690:        extern struct tm *localtime();
        !           691:        extern char *ctime();
        !           692:        extern struct timeb *ftime();
        !           693: #ifdef USG
        !           694:        struct tm *bp;
        !           695:        extern char *tzname[];
        !           696: #else
        !           697:        extern char *timezone();
        !           698: #endif
        !           699: 
        !           700:        /*  Get current time. This will be used resolve the timezone. */
        !           701:        ud = ctime(longtime);
        !           702:        ftime(&t);
        !           703: 
        !           704:        /*  Crack the UNIX date line in a singularly unoriginal way. */
        !           705:        q = b;
        !           706: 
        !           707:        p = &ud[0];             /* Mon */
        !           708:        *q++ = *p++;
        !           709:        *q++ = *p++;
        !           710:        *q++ = *p++;
        !           711:        *q++ = ','; *q++ = ' ';
        !           712: 
        !           713:        p = &ud[8];             /* 16 */
        !           714:        if (*p == ' ')
        !           715:                p++;
        !           716:        else
        !           717:                *q++ = *p++;
        !           718:        *q++ = *p++; *q++ = '-';
        !           719: 
        !           720:        p = &ud[4];             /* Sep */
        !           721:        *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = '-';
        !           722: 
        !           723:        p = &ud[22];            /* 1979 */
        !           724:        *q++ = *p++; *q++ = *p++; *q++ = ' ';
        !           725: 
        !           726:        p = &ud[11];            /* 01:03:52 */
        !           727:        for (i = 8; i > 0; i--)
        !           728:                *q++ = *p++;
        !           729: 
        !           730:                                /* -PST or -PDT */
        !           731: #ifdef USG
        !           732:        bp = localtime(&t.time);
        !           733:        p = tzname[bp->tm_isdst];
        !           734: #else
        !           735:        p = timezone(t.timezone, localtime(&t.time)->tm_isdst);
        !           736: #endif
        !           737:        if (p[3] != '\0') {
        !           738:                /* hours from GMT */
        !           739:                p += 3;
        !           740:                *q++ = *p++;
        !           741:                if (p[1] == ':')
        !           742:                        *q++ = '0';
        !           743:                else
        !           744:                        *q++ = *p++;
        !           745:                *q++ = *p++; p++; *q++ = *p++; *q++ = *p++;
        !           746:        } else {
        !           747:                *q++ = ' '; *q++ = *p++; *q++ = *p++; *q++ = *p++;
        !           748:        }
        !           749:        *q = '\0';
        !           750: 
        !           751:        return (b);
        !           752: }
        !           753: 
        !           754: char *
        !           755: replyname(hptr)
        !           756: struct hbuf *hptr;
        !           757: {
        !           758:        register char *ptr;
        !           759:        static char tbuf[PATHLEN];
        !           760: 
        !           761:        ptr = hptr->path;
        !           762:        if (prefix(ptr, FULLSYSNAME))
        !           763:                ptr = index(ptr, '!') + 1;
        !           764: #ifdef INTERNET
        !           765:        if (hptr->from[0])
        !           766:                ptr = hptr->from;
        !           767:        if (hptr->replyto[0])
        !           768:                ptr = hptr->replyto;
        !           769: #endif
        !           770:        strcpy(tbuf, ptr);
        !           771:        ptr = index(tbuf, '(');
        !           772:        if (ptr) {
        !           773:                while (ptr[-1] == ' ')
        !           774:                        ptr--;
        !           775:                *ptr = 0;
        !           776:        }
        !           777: #ifndef INTERNET
        !           778:        /*
        !           779:         * Play games stripping off multiple berknet
        !           780:         * addresses (a!b!c:d:e => a!b!d:e) here.
        !           781:         */
        !           782:        for (ptr=tbuf; *ptr; ptr++)
        !           783:                if (index(NETCHRS, *ptr) && *ptr == ':' && index(ptr+1, ':'))
        !           784:                        strcpy(ptr, index(ptr+1, ':'));
        !           785: #endif
        !           786:        return tbuf;
        !           787: }
        !           788: 
        !           789: /*
        !           790:  * Given an article ID, find the line in the history file that mentions it.
        !           791:  * Return the text of the line, or NULL if not found.  A pointer to a
        !           792:  * static area is returned.
        !           793:  */
        !           794: char *
        !           795: findhist(artid)
        !           796: char *artid;
        !           797: {
        !           798:        static char lbuf[256];
        !           799:        char oidbuf[BUFSIZ];
        !           800:        FILE *hfp;
        !           801:        char *p;
        !           802: 
        !           803:        /* Try to understand old artid's as well.  Assume .UUCP domain. */
        !           804:        if (artid[0] != '<') {
        !           805:                p = index(artid, '.');
        !           806:                if (p)
        !           807:                        *p++ = '\0';
        !           808:                sprintf(oidbuf, "<%s@%s.UUCP>", p, artid);
        !           809:                if (p)
        !           810:                        *--p = '.';
        !           811:        } else
        !           812:                strcpy(oidbuf, artid);
        !           813:        hfp = xfopen(ARTFILE, "r");
        !           814:        while (fgets(lbuf, BUFLEN, hfp) != NULL) {
        !           815:                p = index(lbuf, '\t');
        !           816:                if (p == NULL)
        !           817:                        p = index(lbuf, '\n');
        !           818:                *p = 0;
        !           819:                if (strcmp(lbuf, artid) == 0 || strcmp(lbuf, oidbuf) == 0) {
        !           820:                        fclose(hfp);
        !           821:                        *p = '\t';
        !           822:                        *(lbuf + strlen(lbuf) - 1) = 0; /* zap the \n */
        !           823:                        return(lbuf);
        !           824:                }
        !           825:        }
        !           826:        fclose(hfp);
        !           827:        return(NULL);
        !           828: }
        !           829: 
        !           830: /*
        !           831:  * Hunt up the article "artid", and return the newsgroup/artnum
        !           832:  * where it can be found.
        !           833:  */
        !           834: char *
        !           835: findfname(artid)
        !           836: char *artid;
        !           837: {
        !           838:        char *line, *p, *q;
        !           839:        char *findhist();
        !           840:        FILE *rv;
        !           841:        static char fname[256];
        !           842: 
        !           843:        line = findhist(artid);
        !           844:        if (line) {
        !           845:                /* Look for it stored as an article, where it should be */
        !           846:                p = index(line, '\t');
        !           847:                p = index(p+1, '\t');
        !           848:                p++;
        !           849:                if (*p) {
        !           850:                        q = index(p, ' ');
        !           851:                        if (q)
        !           852:                                *q = 0;
        !           853:                        strcpy(fname, p);
        !           854:                        return fname;
        !           855:                }
        !           856:        }
        !           857: 
        !           858:        return NULL;
        !           859: }
        !           860: 
        !           861: /*
        !           862:  * Hunt up the article "artid", fopen it for read, and return a
        !           863:  * file descriptor to it.  We look everywhere we can think of.
        !           864:  */
        !           865: FILE *
        !           866: hfopen(artid)
        !           867: char *artid;
        !           868: {
        !           869:        char *p;
        !           870:        char *findhist();
        !           871:        FILE *rv = NULL;
        !           872:        char fname[256];
        !           873: 
        !           874:        p = findfname(artid);
        !           875:        if (p) {
        !           876:                strcpy(fname, dirname(p));
        !           877:                rv = fopen(fname, "r"); /* NOT xfopen! */
        !           878:                if (rv != NULL)
        !           879:                        return rv;
        !           880:        }
        !           881: 
        !           882:        xerror("Cannot hfopen article %s", artid);
        !           883: }

unix.superglobalmegacorp.com

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