Annotation of researchv10no/cmd/netnews/src/funcs.c, revision 1.1.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.