Annotation of researchv10no/cmd/netnews/src/ifuncs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * ifuncs - functions used by inews.
                      3:  */
                      4: 
                      5: static char *SccsId = "@(#)ifuncs.c    2.21    3/31/83";
                      6: 
                      7: #include "iparams.h"
                      8: 
                      9: /*
                     10:  * Transmit this article to all interested systems.
                     11:  */
                     12: 
                     13: #ifdef u370
                     14: static struct srec srec;
                     15: static struct hbuf h;
                     16: #endif
                     17: 
                     18: broadcast()
                     19: {
                     20:        register char *nptr, *hptr;
                     21:        register FILE *fp;
                     22: #ifndef u370
                     23:        struct srec srec;
                     24:        struct hbuf h;
                     25: #endif
                     26: 
                     27:        /* h is a local copy of the header we can scribble on */
                     28:        fp = xfopen(ARTICLE, "r");
                     29:        if (hread(&h, fp, TRUE) == NULL)
                     30:                xerror("Cannot reread article");
                     31:        fclose(fp);
                     32:        if (h.distribution[0])
                     33:                strcpy(h.nbuf, h.distribution);
                     34:        ngcat(h.nbuf);
                     35: 
                     36:         /* break path into list of systems. */
                     37:        hptr = nptr = h.path;
                     38:        while (*hptr != '\0') {
                     39:                if (index(NETCHRS, *hptr)) {
                     40:                        *hptr++ = '\0';
                     41:                        nptr = hptr;
                     42:                } else
                     43:                        hptr++;
                     44:        }
                     45:        *nptr = '\0';
                     46: 
                     47:        /* loop once per system. */
                     48:        lock();
                     49:        s_openr();
                     50:        while (s_read(&srec)) {
                     51:                if (strncmp(srec.s_name, FULLSYSNAME, SNLN) == 0)
                     52:                        continue;
                     53:                hptr = h.path;
                     54:                while (*hptr != '\0') {
                     55:                        if (strncmp(srec.s_name, hptr, SNLN) == 0)
                     56:                                goto contin;
                     57:                        while (*hptr++ != '\0')
                     58:                                ;
                     59:                }
                     60:                if (ngmatch(h.nbuf, srec.s_nbuf)) {
                     61:                        transmit(&srec, xfopen(ARTICLE, "r"), 1);
                     62:                }
                     63:        contin:;
                     64:        }
                     65:        s_close();
                     66:        unlock();
                     67: }
                     68: 
                     69: /*
                     70:  * Transmit file to system.
                     71:  */
                     72: #define PROC 0004
                     73: transmit(sp, ifp, maynotify)
                     74: register struct srec *sp;
                     75: register FILE *ifp;
                     76: int maynotify;
                     77: {
                     78:        register FILE *ofp;
                     79:        register int c;
                     80:        register char *ptr;
                     81:        struct hbuf hh;
                     82:        char TRANS[BUFLEN];
                     83:        char *argv[20];
                     84:        register int pid, fd;
                     85:        extern char firstbufname[];
                     86: 
                     87: /* A:  afmt: the other machine runs an A news, so we xmit in A format */
                     88:        int afmt = (index(sp->s_flags, 'A') != NULL);
                     89: /* B:  use B format (this is the default - don't use this letter elsewise). */
                     90: /* F:  append name to file */
                     91:        int appfile = (index(sp->s_flags, 'F') != NULL);
                     92: /* L:  local: don't send the article unless it was generated locally */
                     93:        int local = (index(sp->s_flags, 'L') != NULL);
                     94: /* N:  notify: don't send the article, just tell him we have it */
                     95:        int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
                     96: /* S:  noshell: don't fork a shell to execute the xmit command */
                     97:        int noshell = (index(sp->s_flags, 'S') != NULL);
                     98: /* U:  useexist: use the -c option to uux to use the existing copy */
                     99:        int useexist = (index(sp->s_flags, 'U') != NULL);
                    100: 
                    101:        if (local && mode == PROC)
                    102:                return;
                    103: #ifdef DEBUG
                    104:        printf("Transmitting to '%s'\n", sp->s_name);
                    105: #endif
                    106:        if (!appfile && !useexist) {
                    107:                if (hread(&hh, ifp, TRUE) == NULL) {
                    108:                        fprintf(stderr, "Bad header, not transmitting\n");
                    109:                        log("Bad header, not transmitting %s re %s to %s",
                    110:                                hh.ident, hh.title, sp->s_name);
                    111:                        return;
                    112:                }
                    113:                /* Taken out for obscure reasons - see the standard.
                    114:                ngsquash(hh.nbuf, sp->s_nbuf);
                    115:                */
                    116:                if (hh.nbuf[0] == '\0') {
                    117:                        printf("Article not subscribed to by %s\n", sp->s_name);
                    118:                        return;
                    119:                }
                    120:                sprintf(TRANS, "%s/trXXXXXX", SPOOL);
                    121:        }
                    122: 
                    123:        if (notify) {
                    124:                char oldid[50];
                    125:                sprintf(hh.title, "ihave %s %s", hh.ident, FULLSYSNAME);
                    126:                sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
                    127:                strcpy(oldid, hh.ident);
                    128:                getident(&hh);
                    129:                log("tell %s about %s, notif. id %s",
                    130:                        sp->s_name, oldid, hh.ident);
                    131:        } else
                    132:                log("xmit article %s to %s",
                    133:                        hh.ident, sp->s_name);
                    134: 
                    135:        if (appfile) {
                    136:                if (firstbufname[0] == '\0')
                    137:                        xerror("No file name to xmit from");
                    138:                ofp = fopen(sp->s_xmit, "a");
                    139:                if (ofp == NULL)
                    140:                        xerror("Cannot append to %s", sp->s_xmit);
                    141:                fprintf(ofp, "%s\n", firstbufname);
                    142:                fclose(ofp);
                    143:                return;
                    144:        }
                    145:        else
                    146: #ifdef UXMIT
                    147:        if (useexist) {
                    148:                if (firstbufname[0] == '\0')
                    149:                        xerror("No file name to xmit from");
                    150:                if (*sp->s_xmit == '\0')
                    151:                        sprintf(bfr, UXMIT, sp->s_name, firstbufname);
                    152:                else
                    153:                        sprintf(bfr, sp->s_xmit, firstbufname);
                    154:        } else
                    155: #endif
                    156:        {
                    157:                ofp = xfopen(mktemp(TRANS), "w");
                    158:                if (afmt)
                    159:                        ohwrite(&hh, ofp);
                    160:                else 
                    161:                        hwrite(&hh, ofp);
                    162:                if (!notify)
                    163:                        while ((c = getc(ifp)) != EOF)
                    164:                                putc(c, ofp);
                    165:                fclose(ifp);
                    166:                fclose(ofp);
                    167:                if (*sp->s_xmit == '\0')
                    168:                        sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
                    169:                else
                    170:                        sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
                    171:        }
                    172: 
                    173:        /* At this point, the command to be executed is in bfr. */
                    174:        if (noshell) {
                    175:                if (pid = fork())
                    176:                        fwait(pid);
                    177:                else {
                    178:                        close(0);
                    179:                        open(TRANS, 0);
                    180:                        ptr = sp->s_xmit;
                    181:                        for (pid = 0; pid < 19; pid++) {
                    182:                                while (isspace(*ptr))
                    183:                                        *ptr++ = 0;
                    184:                                argv[pid] = ptr;
                    185:                                while (!isspace(*++ptr) && *ptr)
                    186:                                        ;
                    187:                                if (!*ptr)
                    188:                                        break;
                    189:                        }
                    190:                        argv[++pid] = 0;
                    191:                        execv(sp->s_xmit, argv);
                    192:                        xerror("Can't execv\n");
                    193:                }
                    194:        } else
                    195:                system(bfr);
                    196:        if (!appfile && !useexist)
                    197:                unlink(TRANS);
                    198: }
                    199: 
                    200: typedef struct {
                    201:        char *dptr;
                    202:        int dsize;
                    203: } datum;
                    204: 
                    205: /*
                    206:  * Return TRUE if we have seen this file before, else FALSE.
                    207:  */
                    208: history(hp)
                    209: struct hbuf *hp;
                    210: {
                    211:        register FILE *hfp;
                    212:        register char *p;
                    213:        datum lhs, rhs;
                    214:        datum fetch();
                    215: 
                    216: #ifdef DEBUG
                    217:        fprintf(stderr,"history(%s)\n", hp->ident);
                    218: #endif
                    219:        idlock(hp->ident);
                    220: #ifdef DBM
                    221:        dbminit(ARTFILE);
                    222:        lhs.dptr = hp->ident;
                    223:        lhs.dsize = strlen(lhs.dptr) + 1;
                    224:        rhs = fetch(lhs);
                    225:        if (rhs.dptr)
                    226:                return(TRUE);
                    227: #else
                    228:        hfp = xfopen(ARTFILE, "r");
                    229:        while (fgets(bfr, BUFLEN, hfp) != NULL) {
                    230:                p = index(bfr, '\t');
                    231:                if (p == NULL)
                    232:                        p = index(bfr, '\n');
                    233:                if (p != NULL)  /* can happen if nulls in file */
                    234:                        *p = 0;
                    235:                if (strcmp(bfr, hp->ident)==0 ||
                    236:                                hp->oident[0] && strcmp(bfr, hp->oident)==0) {
                    237:                        fclose(hfp);
                    238:                        idunlock();
                    239: #ifdef DEBUG
                    240:                        fprintf(stderr,"history returns true\n");
                    241: #endif
                    242:                        return(TRUE);
                    243:                }
                    244:        }
                    245:        fclose(hfp);
                    246: #endif
                    247:        addhist(hp->ident);
                    248:        addhist("\t");
                    249: #ifdef DEBUG
                    250:        fprintf(stderr,"history returns false\n");
                    251: #endif
                    252:        return(FALSE);
                    253: }
                    254: 
                    255: static char histline[256];     /* Assumed initially zero */
                    256: 
                    257: addhist(msg)
                    258: char *msg;
                    259: {
                    260:        strcat(histline, msg);
                    261: }
                    262: 
                    263: savehist()
                    264: {
                    265:        register FILE *hfp;
                    266:        datum lhs, rhs;
                    267:        long fpos;
                    268:        register char *p;
                    269: 
                    270:        hfp = xfopen(ARTFILE, "a");
                    271:        fpos = ftell(hfp);
                    272:        fprintf(hfp, "%s\n", histline);
                    273:        fclose(hfp);
                    274: #ifdef DBM
                    275:        /* We assume that history has already been called, calling dbminit. */
                    276:        p = index(histline, '\t');
                    277:        if (p)
                    278:                *p = 0;
                    279:        lhs.dptr = histline;
                    280:        lhs.dsize = strlen(lhs.dptr) + 1;
                    281:        rhs.dptr = (char *) &fpos;
                    282:        rhs.dsize = sizeof fpos;
                    283:        store(lhs, rhs);
                    284: #endif
                    285:        histline[0] = 0;
                    286:        idunlock();
                    287: }
                    288: 
                    289: /*
                    290:  * Save partial news.
                    291:  */
                    292: newssave(fd, dummy)
                    293: FILE *fd, *dummy;
                    294: {
                    295:        register FILE *tofd, *fromfd;
                    296:        char sfname[BUFLEN];
                    297:        register int c;
                    298:        struct hbuf h;
                    299:        time_t tim;
                    300: 
                    301:        if (fd == NULL)
                    302:                fromfd = xfopen(INFILE, "r");
                    303:        else
                    304:                fromfd = fd;
                    305:        umask(savmask);
                    306:        setgid(gid);
                    307:        setuid(uid);
                    308: 
                    309:        sprintf(sfname, "%s/%s", userhome, PARTIAL);
                    310:        if ((tofd = fopen(sfname, "a")) == NULL)
                    311:                xerror("Cannot save partial news");
                    312:        time(&tim);
                    313:        fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
                    314:        while ((c = getc(fromfd)) != EOF)
                    315:                putc(c, tofd);
                    316:        fclose(fromfd);
                    317:        fclose(tofd);
                    318:        printf("News saved in %s\n", sfname);
                    319:        xxit(0);
                    320: }
                    321: 
                    322: /*
                    323:  * Handle dates in header.
                    324:  */
                    325: 
                    326: dates(hp)
                    327: struct hbuf *hp;
                    328: {
                    329:        long edt;
                    330: 
                    331:        time(&hp->rectime);
                    332:        nstrip(strcpy(hp->recdate, arpadate(&hp->rectime)));
                    333:        if (*hp->subdate) {
                    334:                if (cgtdate(hp->subdate) < 0) {
                    335:                        log("Bad sub date '%s'", hp->subdate);
                    336:                        xerror("Cannot parse submittal date");
                    337:                }
                    338:        } else
                    339:                strcpy(hp->subdate, hp->recdate);
                    340:        if (*hp->expdate) {
                    341:                if ((edt = cgtdate(hp->expdate)) < 0)
                    342:                        xerror("Cannot parse expiration date");
                    343:                nstrip(strcpy(hp->expdate, arpadate(&edt)));
                    344:        } else {
                    345:                defexp = TRUE;
                    346:                /*
                    347:                 * Default is now applied in expire.c
                    348:                hp->exptime = hp->rectime + DFLTEXP;
                    349:                nstrip(strcpy(hp->expdate, arpadate(&hp->exptime)));
                    350:                */
                    351:        }
                    352: }
                    353: 
                    354: /*
                    355:  *     Exit and cleanup.
                    356:  */
                    357: xxit(status)
                    358: int status;
                    359: {
                    360:        unlink(INFILE);
                    361:        unlink(ARTICLE);
                    362:        while (lockcount > 0)
                    363:                unlock();
                    364:        idunlock();
                    365:        exit(status);
                    366: }
                    367: 
                    368: xerror(message, arg1, arg2)
                    369: char *message;
                    370: int arg1, arg2;
                    371: {
                    372:        char buffer[128];
                    373: 
                    374:        fflush(stdout);
                    375:        sprintf(buffer, message, arg1, arg2);
                    376:        fprintf(stderr, "inews: %s.\n", buffer);
                    377:        log(buffer);
                    378:        xxit(1);
                    379: }
                    380: 
                    381: #ifdef VMS
                    382: 
                    383: #define        SUBLOCK "/tmp/netnews.lck.1"
                    384: 
                    385: /*
                    386:  * Newsystem locking.
                    387:  * These routines are different for VMS because we can not
                    388:  * effectively simulate links, and VMS supports multiple
                    389:  * version numbers of files
                    390:  */
                    391: lock()
                    392: {
                    393:        register int i;
                    394:        register int fd;
                    395: 
                    396:        if (lockcount++ == 0) {
                    397:                i = DEADTIME;
                    398:                while ((fd = creat(SUBLOCK, 0444)) < 0) {
                    399:                        if (--i < 0) {
                    400:                                unlink(SUBLOCK);
                    401:                                log("News system locked up");
                    402:                        }
                    403:                        if (i < -3)
                    404:                                xerror("Unable to unlock news system");
                    405:                        sleep((unsigned)1);
                    406:                }
                    407:                close(fd);
                    408:        }
                    409: }
                    410: 
                    411: unlock()
                    412: {
                    413:        if (--lockcount == 0)
                    414:                unlink(SUBLOCK);
                    415: }
                    416: 
                    417: #else  VMS
                    418: 
                    419: /*
                    420:  * Newsystem locking.
                    421:  */
                    422: 
                    423: lock()
                    424: {
                    425:        register int i;
                    426: 
                    427:        if (lockcount++ == 0) {
                    428:                i = DEADTIME;
                    429:                while (link(SUBFILE, LOCKFILE)) {
                    430:                        if (--i < 0)
                    431:                                xerror("News system locked up");
                    432:                        sleep((unsigned)1);
                    433:                }
                    434:        }
                    435: }
                    436: 
                    437: unlock()
                    438: {
                    439:        if (--lockcount == 0)
                    440:                unlink(LOCKFILE);
                    441: }
                    442: #endif VMS
                    443: 
                    444: char lockname[80];
                    445: idlock(str)
                    446: char *str;
                    447: {
                    448:        register int i;
                    449:        char tempname[80];
                    450:        long now;
                    451:        struct stat sbuf;
                    452:        int fd;
                    453: 
                    454: #ifdef VMS
                    455:        sprintf(lockname, "/tmp/%s.l.1", str);
                    456:        if ((fd = creat(lockname, 0444)) < 0) {
                    457: #else  VMS
                    458:        sprintf(tempname, "/tmp/LTMP.%d", getpid());
                    459:        sprintf(lockname, "/tmp/L%s", str);
                    460: #ifdef FOURTEENMAX
                    461:        lockname[5 /* /tmp/ */ + 14] = '\0';
                    462: #endif
                    463:        close(creat(tempname, 0666));
                    464:        while (link(tempname, lockname)) {
                    465: #endif VMS
                    466:                time(&now);
                    467:                i = stat(lockname, &sbuf);
                    468:                if (i < 0) {
                    469:                        xerror("Directory permission problem in /tmp");
                    470:                }
                    471:                if (sbuf.st_mtime + 10*60 < now) {
                    472:                        unlink(lockname);
                    473:                        log("Article %s locked up", str);
                    474:                        continue;
                    475:                }
                    476:                log("waiting on lock for %s", lockname);
                    477:                sleep((unsigned)60);
                    478:        }
                    479: #ifdef VMS
                    480:        close(fd);
                    481: #else
                    482:        unlink(tempname);
                    483: #endif
                    484:        unlink(tempname);
                    485: }
                    486: 
                    487: idunlock()
                    488: {
                    489:        unlink(lockname);
                    490: }
                    491: 
                    492: /*
                    493:  * Put a unique name into header.ident.
                    494:  */
                    495: getident(hp)
                    496: struct hbuf *hp;
                    497: {
                    498:        long seqn;
                    499:        register FILE *fp;
                    500: 
                    501:        lock();
                    502:        fp = xfopen(SEQFILE, "r");
                    503:        fgets(bfr, BUFLEN, fp);
                    504:        fclose(fp);
                    505:        seqn = atol(bfr) + 1;
                    506: #ifdef VMS
                    507:        unlink(SEQFILE);
                    508: #endif VMS
                    509:        fp = xfopen(SEQFILE, "w");
                    510:        fprintf(fp, "%ld\n", seqn);
                    511:        fclose(fp);
                    512:        unlock();
                    513:        sprintf(hp->ident, "<%ld@%s%s>", seqn, FULLSYSNAME, MYDOMAIN);
                    514: }
                    515: 
                    516: /*
                    517:  * Log the given message, with printf strings and parameters allowed,
                    518:  * on the log file, if it can be written.  The date and an attempt at
                    519:  * figuring out the remote system name are also logged.
                    520:  */
                    521: log(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
                    522: char *fmt;
                    523: {
                    524:        FILE *logfile;
                    525:        char msg[256];
                    526:        char *logtime, *p, *q;
                    527:        char rmtsys[256];
                    528:        char c;
                    529:        long t;
                    530: 
                    531:        if (header.relayversion[0]) {
                    532:                for (p=header.relayversion; p; p=index(p+1, 's'))
                    533:                        if (strncmp(p, "site ", 5) == 0)
                    534:                                break;
                    535:                if (p == NULL)
                    536:                        goto crackpath;
                    537:                p += 4;
                    538:                while (*p == ' ' || *p == '\t')
                    539:                        p++;
                    540:                for (q=p; *q && *q!=' ' && *q != '\t'; q++)
                    541:                        ;
                    542:                c = *q;
                    543:                strcpy(rmtsys, p);
                    544:                *q = c;
                    545:        } else {
                    546: crackpath:
                    547:                strcpy(rmtsys, header.path);
                    548:                p = index(rmtsys, '!');
                    549:                if (p == NULL)
                    550:                        p = index(rmtsys, ':');
                    551:                if (p)
                    552:                        *p = 0;
                    553:                else {
                    554:                        p = rindex(rmtsys, '@');
                    555:                        if (p)
                    556:                                strcpy(rmtsys, p+1);
                    557:                        else
                    558:                                strcpy(rmtsys, "local");
                    559:                }
                    560:        }
                    561: 
                    562:        time(&t);
                    563:        logtime = ctime(&t);
                    564:        logtime[16] = 0;
                    565:        logtime += 4;
                    566: 
                    567:        sprintf(msg, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
                    568: 
                    569:        lock();
                    570:        if (access(logfname, 0)) {
                    571:                unlock(0);
                    572:                return;
                    573:        }
                    574:        logfile = fopen(logfname, "a");
                    575:        if (logfile == NULL) {
                    576:                unlock(0);
                    577:                return;
                    578:        }
                    579:        fprintf(logfile, "%s %s\t%s\n", logtime, rmtsys, msg);
                    580:        fclose(logfile);
                    581:        unlock();
                    582: }
                    583: 
                    584: /*
                    585:  * Check if header.nbuf contains only valid newsgroup names;
                    586:  * exit with error if not valid.
                    587:  *
                    588:  * a == TRUE means header.nbuf is subscription list
                    589:  * a == FALSE means header.nbuf is newsgroup list
                    590:  */
                    591: 
                    592: ngfcheck(a)
                    593: int a;
                    594: {
                    595:        char ngcheck[NGFSIZ];   /* Hold NGFILE newsgroups */
                    596:        char tbuf[BUFLEN];      /* hold single header.nbuf news group */
                    597:        register char *s1, *s2;
                    598:        register FILE *f;
                    599: 
                    600:        s1 = ngcheck;
                    601:        f = xfopen(NGFILE, "r");
                    602:        while (fgets(bfr, BUFLEN, f) != NULL) {
                    603:                for (s2 = bfr; *s2 != '\0' &&
                    604:                    *s2 != ' ' && *s2 != '\t' &&
                    605:                    *s2 != ':' && *s2 != '\n';) {
                    606:                        if (s1 >= &ngcheck[NGFSIZ-2])
                    607:                                xerror("NGFILE too long");
                    608:                        *s1++ = *s2++;
                    609:                }
                    610:                *s1++ = NGDELIM;
                    611:        }
                    612:        *s1 = '\0';
                    613:        fclose(f);
                    614:        for (s1 = header.nbuf; *s1 != '\0';) {
                    615:                if (*s1 == NEGCHAR)
                    616:                        s1++;
                    617:                s2 = tbuf;
                    618:                while ((*s2++ = *s1++) != NGDELIM)
                    619:                        if (s1[-1] == ':')
                    620:                                xerror("Newsgroup cannot contain ':'");
                    621:                *s2 = '\0';
                    622:                s2 = tbuf;
                    623:                if (!ngmatch(s2, ngcheck) && (!a || !ngmatch(ngcheck, s2))) {
                    624:                        ngdel(s2);
                    625:                        sprintf(bfr, "Bad news group \"%s\"", s2);
                    626:                        newssave(stdin, NULL);
                    627:                        xerror(bfr);
                    628:                }
                    629:        }
                    630: }
                    631: 
                    632: /*
                    633:  * Figure out who posted the article (which is locally entered).
                    634:  * The results are placed in the header structure hp.
                    635:  */
                    636: gensender(hp, logname)
                    637: struct hbuf *hp;
                    638: char *logname;
                    639: {
                    640:        char *fn;
                    641:        static char buf[100];
                    642:        char buf2[100];
                    643:        char *fullname(), *getenv();
                    644:        char *p;
                    645:        int fd;
                    646: 
                    647:        fn = getenv("NAME");
                    648: 
                    649:        if (fn == NULL) {
                    650:                sprintf(buf, "%s/%s", getenv("HOME"), ".name");
                    651:                fd = open(buf, 0);
                    652:                if (fd >= 0) {
                    653:                        read(fd, buf2, sizeof buf2);
                    654:                        close(fd);
                    655:                        if (buf2[0] >= 'A')
                    656:                                fn = buf2;
                    657:                        for (p=fn; *p; p++)
                    658:                                if (*p < ' ')
                    659:                                        *p = 0;
                    660:                }
                    661:        }
                    662: 
                    663:        if (fn == NULL)
                    664:                fn = fullname(logname);
                    665: 
                    666:        sprintf(hp->path, "%s", logname);
                    667:        sprintf(hp->from, "%s@%s%s (%s)", logname, FULLSYSNAME, MYDOMAIN, fn);
                    668: }
                    669: 
                    670: /*
                    671:  * Trap interrupts.
                    672:  */
                    673: onsig(n)
                    674: int n;
                    675: {
                    676:        static int numsigs = 0;
                    677:        /*
                    678:         * Most UNIX systems reset caught signals to SIG_DFL.
                    679:         * This bad design requires that the trap be set again here.
                    680:         * Unfortunately, if the signal recurs before the trap is set,
                    681:         * the program will die, possibly leaving the lock in place.
                    682:         */
                    683:        if (++numsigs > 100) {
                    684:                log("readnews ran away looping on signal %d", n);
                    685:                xxit(1);
                    686:        }
                    687:        signal(n, onsig);
                    688:        sigtrap = n;
                    689: }
                    690: 
                    691: /*
                    692:  * If the stdin begins with "#", we assume we have been fed a batched
                    693:  * shell script which looks like this:
                    694:  *     #! rnews 1234
                    695:  *     article with 1234 chars
                    696:  *     #! rnews 4321
                    697:  *     article with 4321 chars
                    698:  *
                    699:  * In this case we just exec the unbatcher and let it unpack and call us back.
                    700:  *
                    701:  * Note that there is a potential security hole here.  If the batcher is
                    702:  * /bin/sh, someone could ship you arbitrary stuff to run as shell commands.
                    703:  * The main protection you have is that the effective uid will be news, not
                    704:  * uucp and not the super user.  (That, plus the fact that BATCH is set to
                    705:  * "unbatch" as the system is distributed.)  If you want to run a batched link
                    706:  * and you are security concious, do not use /bin/sh as the unbatcher.
                    707:  * the thing to do is to change BATCH in your localize.sh file from /bin/sh
                    708:  * to some restricted shell which can only run rnews.
                    709:  */
                    710: checkbatch()
                    711: {
                    712:        int c;
                    713: 
                    714: #ifdef BATCH
                    715:        c = getc(stdin);
                    716:        ungetc(c, stdin);
                    717:        clearerr(stdin);
                    718:        if (c == '#') {
                    719:                reset_stdin();
                    720:                execl(BATCH, "news-unpack", 0);
                    721:                xerror("Unable to exec shell to unpack news.\n");
                    722:        }
                    723: #endif
                    724: }
                    725: 
                    726: /*
                    727:  * We've already done a read on stdin, and we want to seek back to the
                    728:  * beginning.  We want the real file descriptor (beyond buffers) to
                    729:  * reflect the true beginning.  Do whatever is necessary.
                    730:  */
                    731: reset_stdin()
                    732: {
                    733:        register FILE *ofd;
                    734:        register int c;
                    735:        char *ofdname;
                    736: 
                    737:        /* First try to seek back - if so, it's a cheap way back. */
                    738:        if (lseek(0, 0L, 0) == 0)
                    739:                return;
                    740: 
                    741:        /* Can't seek, so have to copy input to a file and use that. */
                    742:        ofdname = "/tmp/inewsXXXXX";
                    743:        mktemp(ofdname);
                    744:        ofd = fopen(ofdname, "w");
                    745:        while ((c=getc(stdin)) != EOF)
                    746:                putc(c, ofd);
                    747:        fclose(stdin);
                    748:        fclose(ofd);
                    749: 
                    750:        /* Now for a few lower level hacks to reopen stdin and make
                    751:         * absolutely sure that the right fd's are done for the exec.
                    752:         */
                    753:        close(0);               /* to make sure stdin is really closed. */
                    754:        open(ofdname, 0);       /* returns zero */
                    755:        unlink(ofdname);        /* to avoid cleaning it up later. */
                    756: }

unix.superglobalmegacorp.com

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