Annotation of 43BSDTahoe/new/news/src/ifuncs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * This software is Copyright (c) 1986 by Rick Adams.
                      3:  *
                      4:  * Permission is hereby granted to copy, reproduce, redistribute or
                      5:  * otherwise use this software as long as: there is no monetary
                      6:  * profit gained specifically from the use or reproduction or this
                      7:  * software, it is not sold, rented, traded or otherwise marketed, and
                      8:  * this copyright notice is included prominently in any copy
                      9:  * made.
                     10:  *
                     11:  * The author make no claims as to the fitness or correctness of
                     12:  * this software for any use whatsoever, and it is provided as is. 
                     13:  * Any use of this software is at the user's own risk.
                     14:  *
                     15:  * ifuncs - functions used by inews.
                     16:  */
                     17: 
                     18: #ifdef SCCSID
                     19: static char    *SccsId = "@(#)ifuncs.c 2.66    10/7/87";
                     20: #endif /* SCCSID */
                     21: 
                     22: #include "iparams.h"
                     23: 
                     24: extern long    localize();
                     25: 
                     26: /*LINTLIBRARY*/
                     27: 
                     28: /*
                     29:  * Transmit this article to all interested systems.
                     30:  */
                     31: 
                     32: #ifdef u370
                     33: static struct srec srec;
                     34: #endif /* u370 */
                     35: 
                     36: static struct hbuf h, hh;
                     37: 
                     38: #ifdef MULTICAST
                     39: #define        MAXMCAST        20
                     40: #define        MAXMCS          10
                     41: 
                     42: struct multicast {
                     43:        char mc_name[SBUFLEN];          /* "multi-cast" name */
                     44:        short mc_syscnt;
                     45:        char mc_tosys[MAXMCAST][SBUFLEN];
                     46: } mcast[MAXMCS];
                     47: 
                     48: static int mccount;
                     49: #endif /* MULTICAST */
                     50: 
                     51: long lseek();
                     52: 
                     53: #ifndef DBM
                     54: char *histfile();
                     55: #endif /* !DBM */
                     56: 
                     57: #ifdef VMS
                     58: /*
                     59:  * For VMS/Eunice there are no links: article was moved to firstbufname
                     60:  * before broadcast is reached.  So we read it from there.
                     61:  */
                     62: extern char firstbufname[];
                     63: #endif
                     64: 
                     65: #ifndef GENERICPATH
                     66: /*ARGSUSED*/
                     67: #endif /* !GENERICPATH */
                     68: broadcast(is_rnews)
                     69: int is_rnews;
                     70: {
                     71:        register char *hptr;
                     72:        register char *sptr;
                     73:        register FILE *fp;
                     74: #ifndef u370
                     75:        struct srec srec;
                     76: #endif
                     77:        char sentbuf[LBUFLEN];
                     78:        int nsent = 0;
                     79:        char *sentsys;
                     80: #ifdef GENERICPATH
                     81:        int len;
                     82: #endif /* GENERICPATH */
                     83: 
                     84:        /* h is a local copy of the header we can scribble on */
                     85: #ifdef VMS
                     86:        fp = xfopen (firstbufname, "r");
                     87: #else
                     88:        fp = xfopen(ARTICLE, "r");
                     89: #endif
                     90:        if (hread(&h, fp, TRUE) == NULL)
                     91:                xerror("Cannot reread article");
                     92:        (void) fclose(fp);
                     93: 
                     94:        (void) strcpy(sentbuf, h.ident);
                     95:        (void) strcat(sentbuf, " sent to ");
                     96:        sentsys = index(sentbuf, '\0');
                     97:        nsent = 0;
                     98:        /* break path into list of systems. */
                     99:        hptr = h.path;
                    100: #ifdef GENERICPATH
                    101:        if (!is_rnews && 
                    102:                STRNCMP(PATHSYSNAME, h.path, (len = strlen(PATHSYSNAME))) == 0
                    103:                && index(NETCHRS, h.path[len]))
                    104:                (void) strcpy(h.path, &(h.path[len+1]));
                    105: #endif /* GENERICPATH */
                    106:        sptr = hptr = h.path;
                    107:        while ((hptr=strpbrk(hptr, NETCHRS)) != NULL) {
                    108:                *hptr++ = '\0';
                    109:                sptr = hptr;
                    110:        }
                    111:        *sptr = '\0';
                    112: 
                    113: #ifdef MULTICAST
                    114:        mccount = 0;
                    115: #endif /* MULTICAST */
                    116: 
                    117:        /* loop once per system. */
                    118:        s_openr();
                    119:        while (s_read(&srec)) {
                    120:                char *dist = h.distribution;
                    121:                if (STRNCMP(srec.s_name, LOCALPATHSYSNAME, SNLN) == 0)
                    122:                        continue;
                    123:                if (sptr = srec.s_nosend) {
                    124:                        while (*sptr) {
                    125:                                while (*sptr && *sptr != ',')
                    126:                                        sptr++;
                    127:                                if (*sptr == ',')
                    128:                                        *sptr++ = '\0';
                    129:                        }
                    130:                        *++sptr = '\0';
                    131:                }
                    132:                hptr = h.path;
                    133:                while (*hptr != '\0') {
                    134:                        if (STRNCMP(srec.s_name, hptr, SNLN) == 0)
                    135:                                goto contin;
                    136:                        if (sptr = srec.s_nosend) {
                    137:                                while (*sptr != '\0') {
                    138:                                        if (STRNCMP(sptr, hptr, SNLN) == 0)
                    139:                                                goto contin;
                    140:                                        while (*sptr++)
                    141:                                                ;
                    142:                                }
                    143:                        }
                    144:                        while (*hptr++ != '\0')
                    145:                                ;
                    146:                }
                    147:                if (!ngmatch(h.nbuf, srec.s_nbuf))
                    148:                        continue;
                    149:                if (*dist == '\0')
                    150:                        dist = "world";
                    151:                if (!ngmatch(dist, srec.s_nbuf) && !ngmatch(srec.s_nbuf, dist))
                    152:                            continue;
                    153: 
                    154:                if (nsent) {
                    155:                        hptr = sentsys;
                    156:                        while ((sptr = index(hptr, ',')) != NULL) {
                    157:                                *sptr = '\0';
                    158:                                if (STRCMP(hptr, srec.s_name) == 0) {
                    159:                                        *sptr = ',';
                    160:                                        goto contin;
                    161:                                }
                    162:                                *sptr++ = ',';
                    163:                                for (hptr = sptr; isspace(*hptr); hptr++)
                    164:                                        ;
                    165:                        }
                    166:                        if (STRCMP(hptr, srec.s_name) == 0)
                    167:                                continue;
                    168:                }
                    169:                /* now we've found a system to send this article to */
                    170: #ifdef MULTICAST
                    171:                if (index(srec.s_flags, 'M')) {
                    172:                        /* do a "multi-cast" transmit */
                    173:                        register struct multicast *m;
                    174: 
                    175:                        if (strlen(srec.s_name) >= SBUFLEN ||
                    176:                            strlen(srec.s_xmit) >= SBUFLEN)
                    177:                                xerror("system name too long for multicast");
                    178:                        for (m = mcast; m < &mcast[mccount]; m++)
                    179:                                if (STRCMP(srec.s_xmit, m->mc_name) == 0)
                    180:                                        break;
                    181:                        if (m >= &mcast[MAXMCS])
                    182:                                xerror("Too many multicasts");
                    183:                        if (m == &mcast[mccount]) {
                    184:                                mccount++;
                    185:                                m->mc_syscnt = 0;
                    186:                                strcpy(m->mc_name, srec.s_xmit);
                    187:                        }
                    188:                        if (m->mc_syscnt >= MAXMCAST)
                    189:                                xerror("Too many systems for multicast");
                    190:                        strcpy(m->mc_tosys[m->mc_syscnt++], srec.s_name);
                    191:                } else {
                    192:                        register struct multicast *m;
                    193:                        register char **yptr;
                    194:                        char *sysptrs[MAXMCAST];
                    195:                        int mc;
                    196: 
                    197:                        mc = 0;
                    198:                        for (m = mcast; m < &mcast[mccount]; m++)
                    199:                                if (STRCMP(m->mc_name, srec.s_name) == 0) {
                    200:                                        yptr = sysptrs;
                    201:                                        while (mc < m->mc_syscnt)
                    202:                                                *yptr++ = m->mc_tosys[mc++];
                    203:                                        break;
                    204:                                }
                    205: #ifdef VMS
                    206:                        if (!transmit(&srec, xfopen(firstbufname,"r"),
                    207: #else /* !VMS */
                    208:                        if (!transmit(&srec, xfopen(ARTICLE,"r"),
                    209: #endif /* !VMS */
                    210:                                (STRNCMP(h.nbuf, "to.", 3) != 0),
                    211:                                sysptrs, mc))
                    212:                                continue;
                    213:                }
                    214: #else /* !MULTICAST */
                    215: #ifdef VMS
                    216:                if (!transmit(&srec, xfopen(firstbufname, "r"),
                    217: #else /* !VMS */
                    218:                if (!transmit(&srec, xfopen(ARTICLE, "r"),
                    219: #endif /* !VMS */
                    220:                        (STRNCMP(h.nbuf, "to.", 3) != 0),
                    221:                        (char **) NULL, FALSE))
                    222:                                continue;
                    223: #endif /* !MULTICAST */
                    224:                if (nsent)
                    225:                        (void) strcat(sentbuf, ", ");
                    226:                (void) strcat(sentbuf, srec.s_name);
                    227:                nsent++;
                    228:        contin:;
                    229:        }
                    230:        if (nsent)
                    231:                log(sentbuf);
                    232:        s_close();
                    233: }
                    234: 
                    235: /*
                    236:  * Transmit file to system.
                    237:  */
                    238: #define PROC 0004
                    239: #ifndef MULTICAST
                    240: /* ARGSUSED */
                    241: #endif /* !MULTICAST */
                    242: transmit(sp, ifp, maynotify, sysnames, mc)
                    243: register struct srec *sp;
                    244: register FILE *ifp;
                    245: int maynotify;
                    246: char **sysnames;
                    247: int mc;
                    248: {
                    249:        register FILE *ofp;
                    250:        register int c;
                    251:        register char *ptr;
                    252:        char TRANS[BUFLEN];
                    253:        char *argv[20];
                    254:        register int pid;
                    255:        extern char firstbufname[];
                    256: 
                    257: /* A:  afmt: the other machine runs an A news, so we xmit in A format */
                    258:        int afmt = (index(sp->s_flags, 'A') != NULL);
                    259: /* B:  use B format (this is the default - don't use this letter elsewise). */
                    260: /* F:  append name to file */
                    261:        int appfile = (index(sp->s_flags, 'F') != NULL);
                    262: /* L:  local: don't send the article unless it was generated locally */
                    263:        int local = ((ptr = index(sp->s_flags, 'L')) != NULL);
                    264: /* H:  interpolate history line into command, use existing file */
                    265:        int history = (index(sp->s_flags, 'H') != NULL);
                    266: /* m:  moderated: only send if group is moderated */
                    267:        int sendifmoderated = (index(sp->s_flags, 'm') != NULL);
                    268: /* u:  unmoderated: only send if group is unmoderated */
                    269:        int sendifunmoderated = (index(sp->s_flags, 'u') != NULL);
                    270: /* M:  multi-cast: this is taken care of above, but don't reuse flag */
                    271: #ifdef MULTICAST
                    272: /* O:  multi-cast only, don't send article if not multicast hosts */
                    273:        int multisend = (index(sp->s_flags, 'O') != NULL);
                    274: #endif /* MULTICAST */
                    275: /* N:  notify: don't send the article, just tell him we have it */
                    276:        int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
                    277: /* S:  noshell: don't fork a shell to execute the xmit command */
                    278:        int noshell = (index(sp->s_flags, 'S') != NULL);
                    279: /* U:  useexist: use the -c option to uux to use the existing copy */
                    280:        int useexist = (index(sp->s_flags, 'U') != NULL);
                    281: /* I:  append messageid to file. implies F flag */
                    282:        int appmsgid = maynotify && (index(sp->s_flags, 'I') != NULL);
                    283: 
                    284:        if (notify)
                    285:                appfile = appmsgid = FALSE;
                    286: 
                    287:        if (local && mode == PROC) {
                    288:                local = 0;
                    289:                while (isdigit(*++ptr))
                    290:                        local = local * 10 + *ptr - '0';
                    291:                for (ptr = h.path; *ptr != '\0' && local >= 0; local--)
                    292:                        while (*ptr++ != '\0')
                    293:                                ;
                    294:                if (local < 0) {
                    295:                        (void) fclose(ifp);
                    296:                        return FALSE;
                    297:                }
                    298:        }
                    299: 
                    300:        /*
                    301:        ** Do not transmit to system specified in -x flag.
                    302:        */
                    303:        if (not_here[0] && STRCMP(not_here, sp->s_name) == 0) {
                    304:                (void) fclose(ifp);
                    305:                return FALSE;
                    306:        }
                    307: 
                    308: #ifdef DEBUG
                    309:        printf("Transmitting to '%s'\n", sp->s_name);
                    310: #endif /* DEBUG */
                    311: 
                    312: #ifdef MULTICAST
                    313:        if (multisend && mc == 0) {
                    314:                (void) fclose(ifp);
                    315:                return FALSE;
                    316:        }
                    317: #endif /* MULTICAST */
                    318: 
                    319:        if ((sendifmoderated && is_mod[0] == '\0') ||
                    320:            (sendifunmoderated && is_mod[0] != '\0')) {
                    321:                fclose(ifp);
                    322:                return FALSE;
                    323:        }
                    324: 
                    325:        if (appmsgid || (!appfile && !useexist && !history)) {
                    326:                if (!hread(&hh, ifp, TRUE)) {
                    327:                        logerr("Bad header, not transmitting %s re %s to %s",
                    328:                                hh.ident, hh.title, sp->s_name);
                    329:                        (void) fclose(ifp);
                    330:                        return FALSE;
                    331:                }
                    332:                if (hh.nbuf[0] == '\0') {
                    333:                        fprintf(stderr, "Article not subscribed to by %s\n", sp->s_name);
                    334:                        (void) fclose(ifp);
                    335:                        return FALSE;
                    336:                }
                    337:                (void) sprintf(TRANS, "%s/trXXXXXX", SPOOL);
                    338:        }
                    339: 
                    340:        if (notify) {
                    341:                char oldid[50];
                    342:                (void) sprintf(hh.title, "ihave %s %s", hh.ident, PATHSYSNAME);
                    343:                (void) strcpy(hh.ctlmsg, hh.title);
                    344:                (void) strcpy(hh.numlines, "0");
                    345:                (void) sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
                    346:                (void) strcpy(oldid, hh.ident);
                    347:                getident(&hh);
                    348:                log("tell %s about %s, notif. id %s",
                    349:                        sp->s_name, oldid, hh.ident);
                    350:        }
                    351: 
                    352:        if (appfile || appmsgid) {
                    353:                if (firstbufname[0] == '\0') {
                    354:                        extern char histline[];
                    355:                        localize("junk");
                    356:                        savehist(histline);
                    357:                        xerror("No file name to xmit from");
                    358:                }
                    359:                if (sp->s_xmit[0] == '\0')
                    360:                        sprintf(sp->s_xmit, "%s/%s%s", BATCHDIR, sp->s_name,
                    361:                                appmsgid ? ".ihave" : "");
                    362: #ifdef LOGDIR
                    363:                (void) sprintf(TRANS, "%s/%s/%s", logdir(HOME), BATCHDIR, sp->s_xmit);
                    364:                ofp = fopen(TRANS, "a");
                    365: #else /* !LOGDIR */
                    366:                ofp = fopen(sp->s_xmit, "a");
                    367: #endif /* !LOGDIR */
                    368:                if (ofp == NULL)
                    369:                        xerror("Cannot append to %s", sp->s_xmit);
                    370:                fprintf(ofp, "%s", appmsgid ? hh.ident : firstbufname);
                    371: #ifdef MULTICAST
                    372:                while (--mc >= 0)
                    373:                        fprintf(ofp, " %s", *sysnames++);
                    374: #endif /* !MULTICAST */
                    375:                putc('\n', ofp);
                    376:                (void) fclose(ofp);
                    377:                (void) fclose(ifp);
                    378:                return TRUE;
                    379:        }
                    380:        else if (useexist) {
                    381:                if (firstbufname[0] == '\0')
                    382:                        xerror("No file name to xmit from");
                    383:                if (*sp->s_xmit == '\0')
                    384: #ifdef UXMIT
                    385:                        (void) sprintf(bfr, UXMIT, sp->s_name, firstbufname);
                    386: #else
                    387:                        xerror("UXMIT not defined for U flag");
                    388: #endif
                    389:                else
                    390: #ifdef MULTICAST
                    391:                        makeargs(bfr, sp->s_xmit, firstbufname, sysnames, mc);
                    392: #else
                    393:                        (void) sprintf(bfr, sp->s_xmit, firstbufname);
                    394: #endif
                    395:                (void) fclose(ifp);
                    396:        } else if (history) {
                    397:                extern char histline[];
                    398: 
                    399:                if (*sp->s_xmit == '\0')
                    400:                        xerror("no xmit command with H flag");
                    401: #ifdef MULTICAST
                    402:                makeargs(bfr, sp->s_xmit, histline, sysnames, mc);
                    403: #else
                    404:                (void) sprintf(bfr, sp->s_xmit, histline);
                    405: #endif
                    406:        } else {
                    407:                ofp = xfopen(mktemp(TRANS), "w");
                    408:                if (afmt) {
                    409: #ifdef OLD
                    410:                        fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, PATHSYSNAME,
                    411:                                hh.path, hh.subdate, hh.title);
                    412: #else /* !OLD */
                    413:                        logerr("Must have OLD defined to use A flag for xmit");
                    414:                        return FALSE;
                    415: #endif /* !OLD */
                    416:                } else
                    417:                        hwrite(&hh, ofp);
                    418:                if (!notify)
                    419:                        while ((c = getc(ifp)) != EOF)
                    420:                                putc(c, ofp);
                    421:                if (ferror(ofp))
                    422:                        xerror("write failed on transmit");
                    423:                (void) fclose(ifp);
                    424:                (void) fclose(ofp);
                    425:                if (*sp->s_xmit == '\0')
                    426:                        (void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
                    427:                else
                    428: #ifdef MULTICAST
                    429:                        makeargs(bfr, sp->s_xmit, TRANS, sysnames, mc);
                    430: #else /* !MULTICAST */
                    431:                        (void) sprintf(bfr, sp->s_xmit, TRANS);
                    432: #endif /* !MULTICAST */
                    433:        }
                    434: 
                    435:        /* At this point, the command to be executed is in bfr. */
                    436:        if (noshell) {
                    437:                if (pid = vfork())
                    438:                        fwait(pid);
                    439:                else {
                    440:                        (void) close(0);
                    441:                        (void) open(TRANS, 0);
                    442:                        ptr = bfr;
                    443:                        for (pid = 0; pid < 19; pid++) {
                    444:                                while (isspace(*ptr))
                    445:                                        *ptr++ = 0;
                    446:                                argv[pid] = ptr;
                    447:                                while (!isspace(*++ptr) && *ptr)
                    448:                                        ;
                    449:                                if (!*ptr)
                    450:                                        break;
                    451:                        }
                    452:                        argv[++pid] = 0;
                    453:                        (void) setgid(gid);
                    454:                        (void) setuid(uid);
                    455:                        execvp(argv[0], argv);
                    456:                        xerror("Can't execv %s", argv[0]);
                    457:                }
                    458:        } else {
                    459:                if (!history && sp->s_xmit[0] && !index(bfr, '<')) {
                    460:                        char newcmd[LBUFLEN];
                    461: 
                    462:                        (void) sprintf(newcmd, "(%s) <%s", bfr,
                    463:                            useexist ? firstbufname : TRANS);
                    464:                        system(newcmd);
                    465:                } else
                    466:                        system(bfr);
                    467:        }
                    468:        if (!appfile && !useexist && !history)
                    469:                (void) unlink(TRANS);
                    470:        (void) fclose(ifp);
                    471:        return TRUE;
                    472: }
                    473: 
                    474: #ifdef MULTICAST
                    475: makeargs(buf, cmd, arg2, sysargs, sac)
                    476: char *buf;
                    477: char *cmd;
                    478: char *arg2;
                    479: register char **sysargs;
                    480: int sac;
                    481: {
                    482:        register char *p = cmd;
                    483:        register char *q;
                    484:        register ac = 0;
                    485:        register char *b = buf;
                    486: 
                    487:        q = p;
                    488:        do {
                    489:                if (q = index(q, ' '))
                    490:                        *q = '\0';
                    491:                if (index(p, '%')) {
                    492:                        switch (++ac) {
                    493:                        case 1:
                    494:                                while (--sac >= 0) {
                    495:                                        sprintf(b, p, *sysargs++);
                    496:                                        b = index(b, '\0');
                    497:                                }
                    498:                                break;
                    499:                        case 2:
                    500:                                sprintf(b, p, arg2);
                    501:                                b = index(b, '\0');
                    502:                                break;
                    503:                        default:
                    504:                                if (q)
                    505:                                        *q = ' ';
                    506:                                xerror("badly formed command: %s", cmd);
                    507:                        }
                    508:                } else {
                    509:                        strcpy(b, p);
                    510:                        b = index(b, '\0');
                    511:                }
                    512:                if (q) {
                    513:                        *q = ' ';
                    514:                        p = q;
                    515:                        while (isspace(*q))
                    516:                                q++;
                    517:                }
                    518:        } while (q != NULL);
                    519: }
                    520: #endif /* MULTICAST */
                    521: 
                    522: /*
                    523:  * Return TRUE if we have seen this file before, else FALSE.
                    524:  */
                    525: history(hp)
                    526: struct hbuf *hp;
                    527: {
                    528: #ifdef DBM
                    529:        datum lhs, rhs;
                    530:        datum fetch();
                    531: #else /* !DBM */
                    532:        register FILE *hfp;
                    533:        register char *p;
                    534: #endif /* !DBM */
                    535:        char lcident[BUFLEN];
                    536:        extern char histline[];
                    537: 
                    538: #ifdef DEBUG
                    539:        fprintf(stderr,"history(%s)\n", hp->ident);
                    540: #endif /* DEBUG */
                    541:        /*
                    542:         * Make the article ID case insensitive.
                    543:         */
                    544:        (void) strcpy(lcident, hp->ident);
                    545:        lcase(lcident);
                    546: 
                    547:        idlock(lcident);
                    548: #ifdef DBM
                    549:        initdbm(ARTFILE);
                    550:        lhs.dptr = lcident;
                    551:        lhs.dsize = strlen(lhs.dptr) + 1;
                    552:        rhs = fetch(lhs);
                    553:        if (rhs.dptr) {
                    554:                idunlock();
                    555:                return(TRUE);
                    556:        }
                    557: #else /* !DBM */
                    558:        hfp = xfopen(histfile(lcident), "r");
                    559:        while (fgets(bfr, BUFLEN, hfp) != NULL) {
                    560:                p = index(bfr, '\t');
                    561:                if (p == NULL)
                    562:                        p = index(bfr, '\n');
                    563:                if (p != NULL)  /* can happen if nulls in file */
                    564:                        *p = 0;
                    565:                lcase(bfr);
                    566: 
                    567:                if (STRCMP(bfr, lcident) == 0) {
                    568:                        (void) fclose(hfp);
                    569:                        idunlock();
                    570: #ifdef DEBUG
                    571:                        fprintf(stderr,"history returns true\n");
                    572: #endif /* DEBUG */
                    573:                        return TRUE;
                    574:                }
                    575:        }
                    576:        (void) fclose(hfp);
                    577: #endif /* !DBM */
                    578:        histline[0] = '\0';
                    579:        addhist(hp->ident);
                    580:        addhist("\t");
                    581: #ifdef DEBUG
                    582:        fprintf(stderr,"history returns false\n");
                    583: #endif
                    584:        return FALSE;
                    585: }
                    586: 
                    587: char histline[PATHLEN];
                    588: 
                    589: addhist(msg)
                    590: char *msg;
                    591: {
                    592:        (void) strcat(histline, msg);
                    593: }
                    594: 
                    595: savehist(hline)
                    596: char *hline;
                    597: {
                    598:        register FILE *hfp;
                    599:        register char *p;
                    600: #ifdef DBM
                    601:        long fpos;
                    602: #endif /* !DBM */
                    603: 
                    604: #ifndef DBM
                    605:        if (STRCMP((p = histfile(hline)), ARTFILE) != 0) {
                    606:        /* If the history subfile is accessible */
                    607:                if ((hfp = xfopen(p, "a")) != NULL ) { /* If we can append */
                    608:                        fprintf(hfp, "%s\n", hline);   /* Append */
                    609:                        (void) fclose(hfp);
                    610:                } else
                    611:                        logerr("Unable to append to %s: %s", p, errmsg(errno));
                    612:        } else
                    613: #endif /* !DBM */
                    614:        {
                    615:        hfp = xfopen(ARTFILE, "a");
                    616:        (void) fseek(hfp, 0L, 2); /* Unisoft 5.1 doesn't seek to EOF on 'a' */
                    617: #ifdef DBM
                    618:        fpos = ftell(hfp);
                    619: #endif /* !DBM */
                    620:        fprintf(hfp, "%s\n", hline);
                    621:        (void) fclose(hfp);
                    622:        }
                    623: #ifdef DBM
                    624:        {
                    625:        datum lhs, rhs;
                    626:        /* We assume that history has already been called, calling dbminit. */
                    627:        p = index(hline, '\t');
                    628:        if (p)
                    629:                *p = 0;
                    630:        lcase(hline);
                    631:        lhs.dptr = hline;
                    632:        lhs.dsize = strlen(lhs.dptr) + 1;
                    633:        rhs.dptr = (char *)&fpos;
                    634:        rhs.dsize = sizeof fpos;
                    635:        store(lhs, rhs);
                    636:        }
                    637: #endif /* DBM */
                    638:        idunlock();
                    639: }
                    640: 
                    641: /*
                    642:  * Save partial news.
                    643:  */
                    644: /* ARGSUSED */
                    645: newssave(fd, dummy)
                    646: FILE *fd;
                    647: char *dummy;
                    648: {
                    649:        register FILE *tofd, *fromfd;
                    650:        char sfname[BUFLEN];
                    651:        register int c;
                    652:        time_t tim;
                    653: 
                    654:        if (fd == NULL)
                    655:                fromfd = xfopen(INFILE, "r");
                    656:        else
                    657:                fromfd = fd;
                    658:        (void) umask(savmask);
                    659:        (void) setgid(gid);
                    660:        (void) setuid(uid);
                    661: 
                    662:        (void) sprintf(sfname, "%s/%s", userhome, PARTIAL);
                    663:        if ((tofd = fopen(sfname, "a")) == NULL)
                    664:                xerror("Cannot save partial news in %s", sfname);
                    665:        (void) time(&tim);
                    666:        fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
                    667:        while ((c = getc(fromfd)) != EOF)
                    668:                putc(c, tofd);
                    669:        (void) fclose(fromfd);
                    670:        (void) fclose(tofd);
                    671:        printf("News saved in %s\n", sfname);
                    672:        xxit(1);
                    673: }
                    674: 
                    675: /*
                    676:  * Handle dates in header.
                    677:  */
                    678: 
                    679: dates(hp)
                    680: struct hbuf *hp;
                    681: {
                    682:        time_t edt;
                    683: 
                    684:        if (*hp->subdate) {
                    685:                if (cgtdate(hp->subdate) < 0) {
                    686:                        error("Cannot parse submittal date '%s'", hp->subdate);
                    687:                }
                    688:        } else {
                    689:                (void) time(&edt);
                    690:                (void) strcpy(hp->subdate, arpadate(&edt));
                    691:        }
                    692: }
                    693: 
                    694: #define LOCKSIZE       128
                    695: char lockname[LOCKSIZE];
                    696: 
                    697: idlock(str)
                    698: char *str;
                    699: {
                    700:        register int i;
                    701:        register char *cp, *scp;
                    702:        char tempname[LOCKSIZE];
                    703:        time_t now;
                    704:        struct stat sbuf;
                    705:        extern int errno;
                    706: #ifdef VMS
                    707:        int fd;
                    708: /* The name here is because of the peculiar properties of version numbers
                    709:  * in Eunice.  We eliminate any troublesome characters also.
                    710:  */
                    711:        (void) sprintf(lockname, "/tmp/%.10s.l.1", str);
                    712:        for (cp = lockname; *cp; cp++)
                    713:                if (*cp == '/' || *cp == '[' || *cp == ']') *cp = '.';
                    714:        while ((fd = creat(lockname, 0444)) < 0) {
                    715: #else /* !VMS */
                    716:        (void) strcpy(tempname, "/tmp/LTMP.XXXXXX");
                    717:        (void) mktemp(tempname);
                    718:        (void) strcpy(lockname, "/tmp/L");
                    719:        i = strlen(lockname);
                    720:        cp = &lockname[i];
                    721:        scp = str - 1;
                    722:        while (i++ < LOCKSIZE && *++scp != '\0')
                    723:                if (*scp == '/')        /* slash screws up the open */
                    724:                        *cp++ = '.';
                    725:                else
                    726:                        *cp++ = *scp;
                    727:        *cp = '\0';
                    728: #ifdef FOURTEENMAX
                    729:        lockname[5 /* /tmp/ */ + 14] = '\0';
                    730: #endif
                    731:        i = creat(tempname, 0666);
                    732:        if (i < 0)
                    733:                xerror("Cannot creat %s: errno %d", tempname, errno);
                    734:        (void) close(i);
                    735:        while (link(tempname, lockname)) {
                    736: #endif /* !VMS */
                    737:                (void) time(&now);
                    738:                if (stat(lockname, &sbuf) < 0)
                    739:                        xerror("Directory permission problem in /tmp");
                    740: 
                    741:                if (sbuf.st_mtime + 10*60 < now) {
                    742:                        (void) unlink(lockname);
                    743:                        logerr("Article %s locked up", str);
                    744:                        break;
                    745:                }
                    746:                log("waiting on lock for %s", lockname);
                    747:                sleep((unsigned)60);
                    748:        }
                    749: #ifdef VMS
                    750:        (void) close(fd);
                    751: #endif
                    752:        (void) unlink(tempname);
                    753: }
                    754: 
                    755: idunlock()
                    756: {
                    757:        (void) unlink(lockname);
                    758: }
                    759: 
                    760: /*
                    761:  * Put a unique name into header.ident.
                    762:  */
                    763: getident(hp)
                    764: struct hbuf *hp;
                    765: {
                    766:        long seqn;
                    767:        register FILE *fp;
                    768:        extern char *mydomain();
                    769: 
                    770:        lock();
                    771:        fp = xfopen(SEQFILE, "r");
                    772:        (void) fgets(bfr, BUFLEN, fp);
                    773:        (void) fclose(fp);
                    774:        seqn = atol(bfr) + 1;
                    775: /*
                    776:  * For Eunice, this breaks if SEQFILE is not in Unix format.
                    777:  */
                    778:        fp = xfopen(SEQFILE, "r+w");
                    779:        fprintf(fp, "%ld\n", seqn);
                    780:        (void) fclose(fp);
                    781:        unlock();
                    782:        (void) sprintf(hp->ident, "<%ld@%s>", seqn, LOCALSYSNAME);
                    783: }
                    784: 
                    785: /*
                    786:  * Check that header.nbuf contains only valid newsgroup names;
                    787:  * exit with error if not valid.
                    788:  */
                    789: ngfcheck(isproc)
                    790: {
                    791:        register FILE * f;
                    792:        register char * cp;
                    793:        register int    i, j;
                    794:        register int    ngcount, okcount, havealiased;
                    795:        register int    pass;
                    796:        char *          ngs[sizeof header.nbuf / 2];
                    797:        char            uses[sizeof header.nbuf / 2];
                    798:        char            tbuf[sizeof header.nbuf];
                    799:        char            abuf[BUFLEN];
                    800: 
                    801:        havealiased = ngcount = 0;
                    802:        is_mod[0] = '\0';
                    803:        /*
                    804:        ** Split header.nbuf into constituent newsgroups.
                    805:        ** Zap "local" newsgroups of articles from remote sites.
                    806:        */
                    807:        cp = tbuf;
                    808:        (void) strcpy(cp, header.nbuf);
                    809:        for ( ; ; ) {
                    810:                while (*cp == NGDELIM || *cp == ' ')
                    811:                        ++cp;
                    812:                if (*cp == '\0')
                    813:                        break;
                    814:                ngs[ngcount] = cp;
                    815:                do {
                    816:                        ++cp;
                    817:                } while (*cp != '\0' && *cp != NGDELIM && *cp != ' ');
                    818:                if (*cp != '\0')
                    819:                        *cp++ = '\0';
                    820:                /*
                    821:                ** Check for local only distribution on incoming
                    822:                ** newsgroups.  This might occur if someone posted to
                    823:                ** general,net.unix
                    824:                */
                    825:                if (isproc && index(ngs[ngcount], '.') == NULL &&
                    826:                        index(header.nbuf, '.') != NULL) {
                    827:                                logerr("Local group %s removed",
                    828:                                        ngs[ngcount]);
                    829:                                continue;
                    830:                }
                    831:                uses[ngcount] = 1;      /* it should go in "Newsgroups" line */
                    832:                ++ngcount;
                    833:        }
                    834:        /*
                    835:        ** Check groups against active file.
                    836:        */
                    837: recheck:
                    838:        okcount = 0;
                    839:        rewind(actfp); clearerr(actfp);
                    840:        while (okcount < ngcount && fgets(bfr, BUFLEN, actfp) == bfr) {
                    841:                if ((cp = index(bfr, ' ')) == NULL)
                    842:                        continue;       /* strange line in input! */
                    843:                /* newsgroup 12345 12345 X */
                    844:                /*  cp +    01234567890123 */
                    845:                if (!isproc && cp[13]  == 'n')
                    846:                        continue;       /* can't post to this group! */
                    847:                *cp = '\0';
                    848:                for (i = 0; i < ngcount; ++i)
                    849:                        if (uses[i] >= 1 && STRCMP(bfr, ngs[i]) == 0) {
                    850:                                uses[i] = 2;    /* it should be localized too */
                    851:                                if (cp[13] == 'm')
                    852:                                        strcpy(is_mod, bfr);
                    853:                                ++okcount;
                    854:                        }
                    855:        }
                    856: #ifdef ALWAYSALIAS
                    857:        okcount = 0;
                    858: #endif /* ALWAYSALIAS */
                    859:        /*
                    860:        ** Handle groups absent from active file.
                    861:        */
                    862:        if (havealiased == 0 && okcount < ngcount) {
                    863:                /*
                    864:                ** See if remaining groups are in our alias list.
                    865:                */
                    866:                f = xfopen(ALIASES, "r");
                    867:                while (okcount < ngcount && fscanf(f, "%s %s%*[^\n]", abuf, bfr) == 2)
                    868:                        for (i = 0; i < ngcount; ++i) {
                    869: #ifndef ALWAYSALIAS
                    870:                                if (uses[i] == 2)
                    871:                                        continue;
                    872: #endif /* ALWAYSALIAS */
                    873:                                if (STRCMP(ngs[i], abuf) != 0)
                    874:                                        continue;
                    875:                                if (isproc)
                    876:                                        cp = "Aliased newsgroup %s to %s";
                    877:                                else
                    878:                                        cp = "Please change %s to %s";
                    879:                                logerr(cp, abuf, bfr);
                    880:                                ngs[i] = AllocCpy(bfr);
                    881:                                uses[i] = 2;
                    882:                                ++havealiased;
                    883:                                ++okcount;
                    884:                        }
                    885:                (void) fclose(f);
                    886:                for (i = 0; i < ngcount; ++i) {
                    887:                        if (uses[i] == 2)
                    888:                                continue;
                    889:                        if (isproc)
                    890:                                log("Unknown newsgroup %s not localized",
                    891:                                        ngs[i]);
                    892:                        else
                    893:                                logerr("Unknown newsgroup %s", ngs[i]);
                    894: #ifdef ALWAYSALIAS
                    895:                        ++okcount;      /* so we know to exit below */
                    896:                }
                    897:                if (!isproc && okcount > 0)
                    898: #else /* !ALWAYSALIAS */
                    899:                }
                    900:                if (!isproc)
                    901: #endif /* !ALWAYSALIAS */
                    902:                        newssave(infp, (char *) NULL);
                    903:                /*
                    904:                 * Unfortunately, if you alias an unmoderated group to a
                    905:                 * moderated group, you must recheck the active file to see
                    906:                 * if the new group is moderated. Rude but necessary.
                    907:                 */
                    908:                if (havealiased)
                    909:                        goto recheck;   
                    910:        }
                    911:        /*
                    912:        ** Zap duplicates.
                    913:        */
                    914:        for (i = 0; i < ngcount - 1; ++i) {
                    915:                if (uses[i] == 0)
                    916:                        continue;
                    917:                for (j = i + 1; j < ngcount; ++j) {
                    918:                        if (uses[j] == 0)
                    919:                                continue;
                    920:                        if (STRCMP(ngs[i], ngs[j]) != 0)
                    921:                                continue;
                    922:                        logerr("Duplicate %s removed", ngs[j]);
                    923:                        if (uses[i] < uses[j])
                    924:                                uses[i] = uses[j];
                    925:                        uses[j] = 0;
                    926:                }
                    927:        }
                    928:        for (pass = 1; pass <= 2; ++pass) {
                    929:                register int    avail;
                    930: 
                    931:                if (pass == 1) {
                    932:                        /*
                    933:                        ** Rewrite header.nbuf.
                    934:                        */
                    935:                        cp = header.nbuf;
                    936:                        avail = sizeof header.nbuf;
                    937:                } else {
                    938:                        /*
                    939:                        ** Fill in nbuf.
                    940:                        */
                    941:                        cp = nbuf;
                    942:                        avail = sizeof nbuf;
                    943:                }
                    944:                for (i = 0; i < ngcount; ++i) {
                    945:                        if (uses[i] < pass)
                    946:                                continue;
                    947:                        j = strlen(ngs[i]);
                    948:                        if (j + 2 > avail) {
                    949:                                logerr("Redone Newsgroups too long");
                    950:                                break;
                    951:                        }
                    952:                        (void) strcpy(cp, ngs[i]);
                    953:                        cp += j;
                    954:                        *cp++ = (pass == 1) ? NGDELIM : '\0';
                    955:                        avail -= (j + 1);
                    956:                }
                    957:                if (pass == 1) {
                    958:                        if (cp == header.nbuf)
                    959:                                *cp = '\0';
                    960:                        else    *(cp - 1) = '\0';
                    961:                } else  *cp = '\0';
                    962:        }
                    963:        /*
                    964:        ** Free aliases.
                    965:        */
                    966:        for (i = 0; i < ngcount; ++i)
                    967:                if (ngs[i] < tbuf || ngs[i] > &tbuf[sizeof tbuf - 1])
                    968:                        free(ngs[i]);
                    969:        return nbuf[0] == '\0';
                    970: }
                    971: 
                    972: /*
                    973:  * Figure out who posted the article (which is locally entered).
                    974:  * The results are placed in the header structure hp.
                    975:  */
                    976: gensender(hp, logname)
                    977: struct hbuf *hp;
                    978: char *logname;
                    979: {
                    980:        register char *fn, *p;
                    981:        char buf[BUFLEN];
                    982:        char *fullname(), *getenv();
                    983:        int fd, n;
                    984:        extern char *mydomain();
                    985: 
                    986:        if ((fn = getenv("NAME")) == NULL) {
                    987:                (void) sprintf(buf, "%s/%s", userhome, ".name");
                    988:                if ((fd = open(buf, 0)) >= 0) {
                    989:                        n = read(fd, buf, sizeof buf);
                    990:                        (void) close(fd);
                    991:                        if (n > 0 && buf[0] >= 'A') {
                    992:                                for (p = fn = buf; *p; p++)
                    993:                                        if (*p < ' ')
                    994:                                                *p = '\0';
                    995:                        }
                    996:                }
                    997:        }
                    998: 
                    999:        if (fn == NULL)
                   1000:                fn = fullname(logname);
                   1001: 
                   1002:        (void) sprintf(hp->path, "%s", logname);
                   1003:        (void) sprintf(hp->from, "%s@%s (%s)", logname, FROMSYSNAME, fn);
                   1004: }
                   1005: 
                   1006: /*
                   1007:  * Trap interrupts.
                   1008:  */
                   1009: onsig(n)
                   1010: int n;
                   1011: {
                   1012:        static int numsigs = 0;
                   1013:        /*
                   1014:         * Most UNIX systems reset caught signals to SIG_DFL.
                   1015:         * This bad design requires that the trap be set again here.
                   1016:         * Unfortunately, if the signal recurs before the trap is set,
                   1017:         * the program will die, possibly leaving the lock in place.
                   1018:         */
                   1019:        if (++numsigs > 100) {
                   1020:                xerror("inews ran away looping on signal %d", n);
                   1021:        }
                   1022:        (void) signal(n, onsig);
                   1023:        SigTrap = n;
                   1024: }
                   1025: 
                   1026: /*
                   1027:  * If the stdin begins with "#" the input is some kind of batch.  if
                   1028:  * the first line is:
                   1029:  *     #!cunbatch
                   1030:  * or
                   1031:  *     #!c7unbatch
                   1032:  * then fork off a pipe to do the either a
                   1033:  *     "compress -d"
                   1034:  * or a
                   1035:  *     "decode | compress -d"
                   1036:  * and check their output for more batch headers.  They probably
                   1037:  * contain a batch format that looks like this:
                   1038:  *     #! rnews 1234
                   1039:  *     article with 1234 chars
                   1040:  *     #! rnews 4321
                   1041:  *     article with 4321 chars
                   1042:  * If so, then for each article, copy the indicated number of chars into
                   1043:  * a temp file, fork a copy of ourselves, make its input the temp file,
                   1044:  * and allow the copy to process the article.  This avoids an exec of
                   1045:  * rnews for each article.
                   1046:  */
                   1047: 
                   1048: checkbatch()
                   1049: {
                   1050:        int c;
                   1051:        char *cp;
                   1052: 
                   1053:        setbuf(infp, (char *)NULL);
                   1054:        while ((c = getc(infp)) == '#') {
                   1055:                /* some kind of batch, investigate further */
                   1056:                int i;
                   1057:                char cmd[BUFLEN];
                   1058:                cmd[0] = c;
                   1059:                fgets(cmd + 1, BUFLEN, infp);
                   1060:                if (strncmp(cmd, "#! cunbatch", 11) == 0) {
                   1061:                        (void) sprintf(cmd, "%s/compress", LIB);
                   1062:                        input_pipe(cmd, "compress", "-d", (char *) 0);
                   1063:                        setbuf(infp, (char *)NULL);
                   1064:                        continue;       /* look for the #! rnews */
                   1065:                } else if (strncmp(cmd, "#! c7unbatch", 12) == 0) {
                   1066:                        (void) sprintf(cmd, "%s/decode | %s/compress -d",
                   1067:                                LIB, LIB);
                   1068:                        input_pipe("/bin/sh", "news-unpack", "-c", cmd);
                   1069:                        setbuf(infp, (char *)NULL);
                   1070:                        continue;       /* look for the #! rnews */
                   1071:                } else if (strncmp(cmd, "#! rnews ", 9) == 0 ||
                   1072:                        strncmp(cmd, "! rnews ", 8) == 0) {
                   1073:                        /* instead of execing unbatch do it ourselves */
                   1074:                        register int fd, rc, wc;
                   1075:                        int piped[2];
                   1076:                        register long size, asize;
                   1077:                        char *tfilename;
                   1078:                        int pid, wpid, exstat;
                   1079: #define CPBFSZ 8192
                   1080:                        char buf[CPBFSZ];
                   1081: 
                   1082:                        tfilename = 0;
                   1083:                        cp = malloc((unsigned)BUFSIZ);
                   1084:                        if (cp != NULL)
                   1085:                                setbuf(infp, cp);
                   1086:                        do {
                   1087:                                while (STRNCMP(cmd, "#! rnews ", 9)) {
                   1088:                                        fprintf(stderr, "out of sync, skipping %s\n", cmd);
                   1089:                                        if (fgets(cmd, BUFLEN, infp) == NULL)
                   1090:                                                exit(0);
                   1091:                                }
                   1092:                                asize = atol(cmd + 9);
                   1093:                                if (asize <= 0)
                   1094:                                        xerror("checkbatch: bad batch count %ld", asize);
                   1095:                                fd = -1;
                   1096:                                size = asize;
                   1097:                                do {
                   1098:                                        if (size > CPBFSZ)
                   1099:                                                rc = CPBFSZ;
                   1100:                                        else
                   1101:                                                rc = size;
                   1102:                                        rc = fread(buf, 1, rc, infp);
                   1103:                                        if (rc <= 0)
                   1104:                                                break;
                   1105:                                        if (fd < 0) {
                   1106:                                                if (rc == asize)
                   1107:                                                        break;  /* fits in buffer */
                   1108:                                                if (!tfilename)
                   1109:                                                        tfilename = mktemp("/tmp/unbnewsXXXXXX");
                   1110:                                                if ((fd = creat(tfilename, 0666)) < 0) {
                   1111:                                                        fprintf(stderr, "rnews: creat of \"%s\" failed",
                   1112:                                                                tfilename);
                   1113:                                                        perror(" ");
                   1114:                                                        exit(1);
                   1115:                                                }
                   1116:                                        }
                   1117:                                        wc = write(fd, buf, rc);        /* write to temp file */
                   1118:                                        if (wc != rc) {
                   1119:                                                fprintf(stderr, "write of %d to \"%s\" returned %d",
                   1120:                                                        rc, tfilename, wc);
                   1121:                                                perror(" ");
                   1122:                                                exit(1);
                   1123:                                        }
                   1124:                                        size -= rc;
                   1125:                                } while (size > 0);
                   1126:                                if (fd >= 0)
                   1127:                                        (void) close(fd);
                   1128: 
                   1129:                                /*
                   1130:                                 * If we got a truncated batch, don't process
                   1131:                                 * the last article; it will probably be
                   1132:                                 * received again. 
                   1133:                                 */
                   1134:                                if ((rc < asize) && (size > 0))
                   1135:                                        break;
                   1136: 
                   1137:                                /*
                   1138:                                 * This differs from the old unbatcher in
                   1139:                                 * that we don't exec rnews, mainly because
                   1140:                                 * we ARE rnews.  Instead we fork off a copy
                   1141:                                 * of ourselves for each article and allow it
                   1142:                                 * to process. 
                   1143:                                 */
                   1144:                                if (rc == asize) {
                   1145:                                        /*
                   1146:                                         * article fits in buffer, use a pipe
                   1147:                                         * instead of a temporary file. 
                   1148:                                         */
                   1149:                                        if (pipe(piped) != 0)
                   1150:                                                xerror("checkbatch: pipe() failed");
                   1151:                                }
                   1152:                                while ((pid = fork()) == -1) {
                   1153:                                        fprintf(stderr, "fork failed, waiting...\r\n");
                   1154:                                        sleep(60);
                   1155:                                }
                   1156:                                if (pid == 0) {
                   1157:                                        if (rc == asize) {
                   1158:                                                /* article fits in buffer
                   1159:                                                 * make the output of the
                   1160:                                                 * pipe for STDIN 
                   1161:                                                 */
                   1162:                                                (void) fclose(infp);
                   1163:                                                /* redundant but why not */
                   1164:                                                (void) close(0);
                   1165:                                                if ((i = dup(piped[0])) != 0)
                   1166:                                                        xerror("dup() returned %d, should be 0", i);
                   1167:                                                (void) close(piped[0]);
                   1168:                                                (void) close(piped[1]);
                   1169:                                                infp = fdopen(0, "r");
                   1170:                                        } else  /* supstitute temp file as
                   1171:                                                 * input */
                   1172:                                                freopen(tfilename, "r", infp);
                   1173:                                        return; /* from checkbatch as if
                   1174:                                                 * normal article */
                   1175:                                }
                   1176:                                /* parent of fork */
                   1177:                                if (rc == asize) {
                   1178:                                        /* article fits in buffer */
                   1179:                                        wc = write(piped[1], buf, rc);
                   1180:                                        if (wc != rc) {
                   1181:                                                fprintf(stderr, "write of %d to pipe returned %d",
                   1182:                                                        rc, wc);
                   1183:                                                perror("rnews: write");
                   1184:                                                exit(1);
                   1185:                                        }
                   1186:                                        (void) close(piped[0]);
                   1187:                                        (void) close(piped[1]);
                   1188:                                }
                   1189:                                while ((wpid = wait(&exstat)) >= 0 && wpid != pid);
                   1190:                                (void) unlink(tfilename);
                   1191:                        } while (fgets(cmd, BUFLEN, infp) != NULL);
                   1192:                        exit(0);/* all done */
                   1193: 
                   1194:                } else {
                   1195:                        docmd(cmd);
                   1196:                        xxit(0);
                   1197:                }
                   1198:        }                       /* while a batch */
                   1199:        cp = malloc((unsigned)BUFSIZ);
                   1200:        if (cp != NULL)
                   1201:                setbuf(infp, cp);
                   1202:        if (c != EOF)
                   1203:                (void) ungetc(c, infp);
                   1204:        clearerr(infp);
                   1205: }
                   1206: 
                   1207: /*
                   1208:  * The input requires some processing so fork and exec the indicated command
                   1209:  * with its output piped to our input. 
                   1210:  */
                   1211: static 
                   1212: input_pipe(cmd, arg0, arg1, arg2)
                   1213: char *cmd, *arg0, *arg1, *arg2;
                   1214: {
                   1215:        int i, pid;
                   1216:        int piped[2];
                   1217: 
                   1218:        if (pipe(piped) != 0) {
                   1219:                perror("checkbatch: pipe() failed");
                   1220:                exit(1);
                   1221:        }
                   1222:        fflush(stdout);
                   1223:        while ((pid = vfork()) == -1) {
                   1224:                perror("checkbatch: fork failed, waiting");
                   1225:                sleep(60);
                   1226:        }
                   1227:        if (pid == 0) {         /* child process */
                   1228:                /*
                   1229:                 * setup a pipe such that the exec'ed process will read our
                   1230:                 * input file and write to the pipe 
                   1231:                 */
                   1232:                (void) close(1);
                   1233:                if ((i = dup(piped[1])) != 1)
                   1234:                        xerror("dup() returned %d, should be 1", i);
                   1235:                (void) close(piped[0]);
                   1236:                (void) close(piped[1]);
                   1237:                execl(cmd, arg0, arg1, arg2, (char *) 0);
                   1238:                perror("checkbatch");
                   1239:                xerror("Unable to exec %s to unpack news.", cmd);
                   1240:        } else {                /* parent process */
                   1241:                /* make the output of the pipe for STDIN */
                   1242:                (void) fclose(infp);
                   1243:                (void) close(0);
                   1244:                if ((i = dup(piped[0])) != 0)
                   1245:                        xerror("dup() returned %d, should be 0", i);
                   1246:                (void) close(piped[0]);
                   1247:                (void) close(piped[1]);
                   1248:                /*
                   1249:                 * there should be a way to clear any buffered input and just
                   1250:                 * replace file descriptor 0 but I can't find a portable way. 
                   1251:                 */
                   1252:                infp = fdopen(0, "r");
                   1253:        }
                   1254: }
                   1255: 
                   1256: #define MAXARGS 32
                   1257: 
                   1258: docmd(p)
                   1259: register char *p;
                   1260: {
                   1261:        char *args[MAXARGS];
                   1262:        register char **ap = args;
                   1263:        char path[BUFSIZ];
                   1264:        char *rindex(), *cp;
                   1265: 
                   1266:        while (*p && !isspace(*p))              /* skip leading #! crud */
                   1267:                p++;
                   1268: 
                   1269:        while (isspace(*p))
                   1270:                p++;
                   1271: 
                   1272:        while (*p != '\0') {
                   1273:                *ap++ = p;
                   1274:                if (ap >= &args[MAXARGS]) {
                   1275:                        logerr("inews: unbatch: Too many args to %s", args[0]);
                   1276:                        exit(2);
                   1277:                }
                   1278:                while (*p && !isspace(*p))
                   1279:                        p++;
                   1280:                if (*p)
                   1281:                        *p++ = '\0';
                   1282:                while (isspace(*p))
                   1283:                        p++;
                   1284:        }
                   1285:        *ap = (char *)0;
                   1286: 
                   1287:        if (ap == args) {
                   1288:                logerr("inews: unbatch: no command to execute");
                   1289:                exit(2);
                   1290:        }
                   1291: 
                   1292:        /* strip off any leading pathname in case someone gets tricky */
                   1293:        cp = rindex(args[0], '/');
                   1294:        if (cp++ == NULL)
                   1295:                cp = args[0];
                   1296: 
                   1297: # ifdef HOME
                   1298:        sprintf(path, "%s/%s/%s", logdir(HOME), LIBDIR, cp);
                   1299: # else /* !HOME */
                   1300:        sprintf(path, "%s/%s", LIBDIR, cp);
                   1301: # endif /* HOME */
                   1302: 
                   1303:        /*
                   1304:         * "path" is absolute, no searching is needed,  we use
                   1305:         * 'execvp' solely so that sh scripts will be handled
                   1306:         */
                   1307:        (void) execvp(path, args);
                   1308:        perror(path);
                   1309:        xxit(2);
                   1310: }
                   1311: 
                   1312: /*
                   1313:  *     Exit and cleanup.
                   1314:  */
                   1315: xxit(status)
                   1316: int status;
                   1317: {
                   1318:        (void) unlink(INFILE);
                   1319:        (void) unlink(ARTICLE);
                   1320:        while (lockcount > 0)
                   1321:                unlock();
                   1322:        idunlock();
                   1323:        exit(status);
                   1324: }
                   1325: 
                   1326: rwaccess(fname)
                   1327: char *fname;
                   1328: {
                   1329:        int fd;
                   1330: 
                   1331:        fd = open(fname, 2);
                   1332:        if (fd < 0)
                   1333:                return 0;
                   1334:        (void) close(fd);
                   1335:        return 1;
                   1336: }
                   1337: 
                   1338: exists(fname)
                   1339: char *fname;
                   1340: {
                   1341:        int fd;
                   1342: 
                   1343:        fd = open(fname, 0);
                   1344:        if (fd < 0)
                   1345:                return 0;
                   1346:        (void) close(fd);
                   1347:        return 1;
                   1348: }
                   1349: 
                   1350: int    lockcount = 0;                  /* no. of times we've called lock */
                   1351: 
                   1352: #ifdef VMS
                   1353: 
                   1354: #define        SUBLOCK "/tmp/netnews.lck.1"
                   1355: 
                   1356: /*
                   1357:  * Newsystem locking.
                   1358:  * These routines are different for VMS because we can not
                   1359:  * effectively simulate links, and VMS supports multiple
                   1360:  * version numbers of files
                   1361:  */
                   1362: lock()
                   1363: {
                   1364:        register int i;
                   1365:        register int fd;
                   1366: 
                   1367:        if (lockcount++ == 0) {
                   1368:                i = DEADTIME;
                   1369:                while ((fd = creat(SUBLOCK, 0444)) < 0) {
                   1370:                        if (--i < 0) {
                   1371:                                (void) unlink(SUBLOCK);
                   1372:                                logerr("News system locked up");
                   1373:                        }
                   1374:                        if (i < -3)
                   1375:                                xerror("Unable to unlock news system");
                   1376:                        sleep((unsigned)1);
                   1377:                }
                   1378:                (void) close(fd);
                   1379:        }
                   1380: }
                   1381: 
                   1382: unlock()
                   1383: {
                   1384:        if (--lockcount == 0)
                   1385:                (void) unlink(SUBLOCK); 
                   1386: }
                   1387: 
                   1388: #else /* !VMS */
                   1389: 
                   1390: /*
                   1391:  * Newsystem locking.
                   1392:  */
                   1393: 
                   1394: #if defined(BSD4_2) || defined(LOCKF)
                   1395: #ifdef LOCKF
                   1396: #include <unistd.h>
                   1397: #else /* !LOCKF */
                   1398: #include <sys/file.h>
                   1399: #endif /* !LOCKF */
                   1400: static int LockFd = -1;
                   1401: lock()
                   1402: {
                   1403:        LockFd = open(SUBFILE, 2);
                   1404:        if (LockFd < 0)
                   1405:                logerr("Can't open(\"%s\", 2) to lock", SUBFILE);
                   1406:        /* This will sleep until the other program releases the lock */
                   1407:        /* We may need to alarm out of this, but I don't think so */
                   1408: #ifdef LOCKF
                   1409:        if (lockf(LockFd, F_LOCK, 0L) < 0)
                   1410: #else
                   1411:        if (flock(LockFd, LOCK_EX) < 0)
                   1412: #endif
                   1413:                xerror("Can't get lock on %s: %s", SUBFILE, errmsg(errno));
                   1414: }
                   1415: 
                   1416: unlock()
                   1417: {
                   1418:        (void) close(LockFd);
                   1419: }
                   1420: #else /* !BSD4_2 */
                   1421: lock()
                   1422: {
                   1423:        register int i;
                   1424:        extern int errno;
                   1425: 
                   1426:        if (lockcount++ == 0) {
                   1427:                i = DEADTIME;
                   1428:                while (link(SUBFILE, LOCKFILE)) {
                   1429:                        if (errno != EEXIST)
                   1430:                                break;
                   1431:                        if (--i < 0)
                   1432:                                xerror("News system locked up");
                   1433:                        sleep((unsigned)1);
                   1434:                }
                   1435:        }
                   1436: }
                   1437: 
                   1438: unlock()
                   1439: {
                   1440:        if (--lockcount == 0)
                   1441:                (void) unlink(LOCKFILE);
                   1442: }
                   1443: #endif /* !BSD4_2 */
                   1444: #endif /* !VMS */
                   1445: 
                   1446: /* VARARGS1 */
                   1447: error(message, arg1, arg2, arg3)
                   1448: char *message;
                   1449: long arg1, arg2, arg3;
                   1450: {
                   1451:        char buffer[LBUFLEN];
                   1452: 
                   1453:        fflush(stdout);
                   1454:        (void) sprintf(buffer, message, arg1, arg2, arg3);
                   1455:        logerr(buffer);
                   1456:        xxit(mode == PROC ? 0 : 1);
                   1457: }

unix.superglobalmegacorp.com

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