Annotation of 43BSD/contrib/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.51    3/19/86";
                     20: #endif /* SCCSID */
                     21: 
                     22: #include "iparams.h"
                     23: #include <errno.h>
                     24: #include <ctype.h>
                     25: 
                     26: /*LINTLIBRARY*/
                     27: 
                     28: #define AFSIZ  4000    /* size of text in the active file for initial malloc */
                     29: 
                     30: /*
                     31:  * Transmit this article to all interested systems.
                     32:  */
                     33: 
                     34: #ifdef u370
                     35: static struct srec srec;
                     36: #endif /* u370 */
                     37: 
                     38: static struct hbuf h, hh;
                     39: 
                     40: #ifdef MULTICAST
                     41: #define        MAXMCAST        20
                     42: #define        MAXMCS          10
                     43: 
                     44: struct multicast {
                     45:        char mc_name[SBUFLEN];          /* "multi-cast" name */
                     46:        short mc_syscnt;
                     47:        char mc_tosys[MAXMCAST][SBUFLEN];
                     48: } mcast[MAXMCS];
                     49: 
                     50: static int mccount;
                     51: #endif /* MULTICAST */
                     52: 
                     53: #ifndef DBM
                     54: char *histfile();
                     55: #endif /* !DBM */
                     56: 
                     57: broadcast()
                     58: {
                     59:        register char *hptr;
                     60:        register char *sptr;
                     61:        register FILE *fp;
                     62: #ifndef u370
                     63:        struct srec srec;
                     64: #endif
                     65:        char sentbuf[LBUFLEN];
                     66:        int nsent = 0;
                     67:        char *sentsys;
                     68: 
                     69:        /* h is a local copy of the header we can scribble on */
                     70:        fp = xfopen(ARTICLE, "r");
                     71:        if (hread(&h, fp, TRUE) == NULL)
                     72:                xerror("Cannot reread article");
                     73:        (void) fclose(fp);
                     74: 
                     75:        (void) strcpy(sentbuf, h.ident);
                     76:        (void) strcat(sentbuf, " sent to ");
                     77:        sentsys = index(sentbuf, 0);
                     78:        nsent = 0;
                     79:        /* break path into list of systems. */
                     80:        sptr = hptr = h.path;
                     81:        while ((hptr=strpbrk(hptr, NETCHRS)) != NULL) {
                     82:                *hptr++ = '\0';
                     83:                sptr = hptr;
                     84:        }
                     85:        *sptr = '\0';
                     86: 
                     87: #ifdef MULTICAST
                     88:        mccount = 0;
                     89: #endif /* MULTICAST */
                     90: 
                     91:        /* loop once per system. */
                     92:        s_openr();
                     93:        while (s_read(&srec)) {
                     94: #ifdef HIDDENNET
                     95:                if (strncmp(srec.s_name, LOCALSYSNAME, SNLN) == 0)
                     96:                        continue;
                     97: #endif /* HIDDENNET */
                     98:                if (strncmp(srec.s_name, FULLSYSNAME, SNLN) == 0)
                     99:                        continue;
                    100:                if (sptr = srec.s_nosend) {
                    101:                        while (*sptr) {
                    102:                                while (*sptr && *sptr != ',')
                    103:                                        sptr++;
                    104:                                if (*sptr == ',')
                    105:                                        *sptr++ = '\0';
                    106:                        }
                    107:                        *++sptr = '\0';
                    108:                }
                    109:                hptr = h.path;
                    110:                while (*hptr != '\0') {
                    111:                        if (strncmp(srec.s_name, hptr, SNLN) == 0)
                    112:                                goto contin;
                    113:                        if (sptr = srec.s_nosend) {
                    114:                                while (*sptr != '\0') {
                    115:                                        if (strncmp(sptr, hptr, SNLN) == 0)
                    116:                                                goto contin;
                    117:                                        while (*sptr++)
                    118:                                                ;
                    119:                                }
                    120:                        }
                    121:                        while (*hptr++ != '\0')
                    122:                                ;
                    123:                }
                    124:                if (!ngmatch(h.nbuf, srec.s_nbuf))
                    125:                        continue;
                    126:                if (h.distribution[0] != '\0' &&
                    127:                        !ngmatch(h.distribution, srec.s_nbuf) &&
                    128:                        !ngmatch(srec.s_nbuf, h.distribution))
                    129:                            continue;
                    130:                if (nsent) {
                    131:                        hptr = sentsys;
                    132:                        while ((sptr = index(hptr, ',')) != NULL) {
                    133:                                *sptr = '\0';
                    134:                                if (strcmp(hptr, srec.s_name) == 0) {
                    135:                                        *sptr = ',';
                    136:                                        goto contin;
                    137:                                }
                    138:                                *sptr++ = ',';
                    139:                                for (hptr = sptr; isspace(*hptr); hptr++)
                    140:                                        ;
                    141:                        }
                    142:                        if (strcmp(hptr, srec.s_name) == 0)
                    143:                                continue;
                    144:                }
                    145:                /* now we've found a system to send this article to */
                    146: #ifdef MULTICAST
                    147:                if (index(srec.s_flags, 'M')) {
                    148:                        /* do a "multi-cast" transmit */
                    149:                        register struct multicast *m;
                    150: 
                    151:                        if (strlen(srec.s_name) >= SBUFLEN ||
                    152:                            strlen(srec.s_xmit) >= SBUFLEN)
                    153:                                xerror("system name too long for multicast");
                    154:                        for (m = mcast; m < &mcast[mccount]; m++)
                    155:                                if (strcmp(srec.s_xmit, m->mc_name) == 0)
                    156:                                        break;
                    157:                        if (m >= &mcast[MAXMCS])
                    158:                                xerror("Too many multicasts");
                    159:                        if (m == &mcast[mccount]) {
                    160:                                mccount++;
                    161:                                m->mc_syscnt = 0;
                    162:                                strcpy(m->mc_name, srec.s_xmit);
                    163:                        }
                    164:                        if (m->mc_syscnt >= MAXMCAST)
                    165:                                xerror("Too many systems for multicast");
                    166:                        strcpy(m->mc_tosys[m->mc_syscnt++], srec.s_name);
                    167:                } else {
                    168:                        register struct multicast *m;
                    169:                        register char **yptr;
                    170:                        char *sysptrs[MAXMCAST];
                    171:                        int mc;
                    172: 
                    173:                        mc = 0;
                    174:                        for (m = mcast; m < &mcast[mccount]; m++)
                    175:                                if (strcmp(m->mc_name, srec.s_name) == 0) {
                    176:                                        yptr = sysptrs;
                    177:                                        while (mc < m->mc_syscnt)
                    178:                                                *yptr++ = m->mc_tosys[mc++];
                    179:                                        break;
                    180:                                }
                    181:                        if (!transmit(&srec,xfopen(ARTICLE,"r"),1,sysptrs,mc))
                    182:                                continue;
                    183:                }
                    184: #else /* !MULTICAST */
                    185:                if (!transmit(&srec, xfopen(ARTICLE, "r"), 1, (char **)0, 0))
                    186:                        continue;
                    187: #endif /* !MULTICAST */
                    188:                if (nsent)
                    189:                        (void) strcat(sentbuf, ", ");
                    190:                (void) strcat(sentbuf, srec.s_name);
                    191:                nsent++;
                    192:        contin:;
                    193:        }
                    194:        if (nsent)
                    195:                log(sentbuf);
                    196:        s_close();
                    197: }
                    198: 
                    199: /*
                    200:  * Transmit file to system.
                    201:  */
                    202: #define PROC 0004
                    203: #ifndef MULTICAST
                    204: /* ARGSUSED */
                    205: #endif /* !MULTICAST */
                    206: transmit(sp, ifp, maynotify, sysnames, mc)
                    207: register struct srec *sp;
                    208: register FILE *ifp;
                    209: int maynotify;
                    210: char **sysnames;
                    211: int mc;
                    212: {
                    213:        register FILE *ofp;
                    214:        register int c;
                    215:        register char *ptr;
                    216:        char TRANS[BUFLEN];
                    217:        char *argv[20];
                    218:        register int pid;
                    219:        extern char firstbufname[];
                    220: 
                    221: /* A:  afmt: the other machine runs an A news, so we xmit in A format */
                    222:        int afmt = (index(sp->s_flags, 'A') != NULL);
                    223: /* B:  use B format (this is the default - don't use this letter elsewise). */
                    224: /* F:  append name to file */
                    225:        int appfile = (index(sp->s_flags, 'F') != NULL);
                    226: /* L:  local: don't send the article unless it was generated locally */
                    227:        int local = ((ptr = index(sp->s_flags, 'L')) != NULL);
                    228: /* H:  interpolate history line into command, use existing file */
                    229:        int history = (index(sp->s_flags, 'H') != NULL);
                    230: /* M:  multi-cast: this is taken care of above, but don't reuse flag */
                    231: #ifdef MULTICAST
                    232: /* O:  multi-cast only, don't send article if not multicast hosts */
                    233:        int multisend = (index(sp->s_flags, 'O') != NULL);
                    234: #endif /* MULTICAST */
                    235: /* N:  notify: don't send the article, just tell him we have it */
                    236:        int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
                    237: /* S:  noshell: don't fork a shell to execute the xmit command */
                    238:        int noshell = (index(sp->s_flags, 'S') != NULL);
                    239: /* U:  useexist: use the -c option to uux to use the existing copy */
                    240:        int useexist = (index(sp->s_flags, 'U') != NULL);
                    241: 
                    242:        if (local && mode == PROC) {
                    243:                local = 0;
                    244:                while (isdigit(*++ptr))
                    245:                        local = local * 10 + *ptr - '0';
                    246:                for (ptr = h.path; *ptr != '\0' && local >= 0; local--)
                    247:                        while (*ptr++ != '\0')
                    248:                                ;
                    249:                if (local < 0) {
                    250:                        (void) fclose(ifp);
                    251:                        return FALSE;
                    252:                }
                    253:        }
                    254: 
                    255: #ifdef DEBUG
                    256:        printf("Transmitting to '%s'\n", sp->s_name);
                    257: #endif /* DEBUG */
                    258: 
                    259: #ifdef MULTICAST
                    260:        if (multisend && mc == 0) {
                    261:                (void) fclose(ifp);
                    262:                return FALSE;
                    263:        }
                    264: #endif /* MULTICAST */
                    265: 
                    266:        if (!appfile && !useexist && !history) {
                    267:                if (!hread(&hh, ifp, TRUE)) {
                    268:                        logerr("Bad header, not transmitting %s re %s to %s",
                    269:                                hh.ident, hh.title, sp->s_name);
                    270:                        (void) fclose(ifp);
                    271:                        return FALSE;
                    272:                }
                    273:                if (hh.nbuf[0] == '\0') {
                    274:                        fprintf(stderr, "Article not subscribed to by %s\n", sp->s_name);
                    275:                        (void) fclose(ifp);
                    276:                        return FALSE;
                    277:                }
                    278:                (void) sprintf(TRANS, "%s/trXXXXXX", SPOOL);
                    279:        }
                    280: 
                    281:        if (notify) {
                    282:                char oldid[50];
                    283:                (void) sprintf(hh.title, "ihave %s %s", hh.ident, FULLSYSNAME);
                    284:                (void) sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
                    285:                (void) strcpy(oldid, hh.ident);
                    286:                getident(&hh);
                    287:                log("tell %s about %s, notif. id %s",
                    288:                        sp->s_name, oldid, hh.ident);
                    289:        }
                    290: 
                    291:        if (appfile) {
                    292:                if (firstbufname[0] == '\0') {
                    293:                        extern char histline[];
                    294:                        localize("junk");
                    295:                        savehist(histline);
                    296:                        xerror("No file name to xmit from");
                    297:                }
                    298:                if (sp->s_xmit[0] == '\0')
                    299:                        sprintf(sp->s_xmit, "%s/%s", BATCHDIR, sp->s_name);
                    300: #ifdef IHCC
                    301:                (void) sprintf(TRANS, "%s/%s/%s", logdir(HOME), BATCHDIR, sp->s_xmit);
                    302:                ofp = fopen(TRANS, "a");
                    303: #else /* !IHCC */
                    304:                ofp = fopen(sp->s_xmit, "a");
                    305: #endif /* !IHCC */
                    306:                if (ofp == NULL)
                    307:                        xerror("Cannot append to %s", sp->s_xmit);
                    308: #ifdef MULTICAST
                    309:                fprintf(ofp, "%s", firstbufname);
                    310:                while (--mc >= 0)
                    311:                        fprintf(ofp, " %s", *sysnames++);
                    312:                fprintf(ofp, "\n");
                    313: #else /* !MULTICAST */
                    314:                fprintf(ofp, "%s\n", firstbufname);
                    315: #endif /* !MULTICAST */
                    316:                (void) fclose(ofp);
                    317:                (void) fclose(ifp);
                    318:                return TRUE;
                    319:        }
                    320:        else if (useexist) {
                    321:                if (firstbufname[0] == '\0')
                    322:                        xerror("No file name to xmit from");
                    323:                if (*sp->s_xmit == '\0')
                    324: #ifdef UXMIT
                    325:                        (void) sprintf(bfr, UXMIT, sp->s_name, firstbufname);
                    326: #else
                    327:                        xerror("UXMIT not defined for U flag");
                    328: #endif
                    329:                else
                    330: #ifdef MULTICAST
                    331:                        makeargs(bfr, sp->s_xmit, firstbufname, sysnames, mc);
                    332: #else
                    333:                        (void) sprintf(bfr, sp->s_xmit, firstbufname);
                    334: #endif
                    335:                (void) fclose(ifp);
                    336:        } else if (history) {
                    337:                extern char histline[];
                    338: 
                    339:                if (*sp->s_xmit == '\0')
                    340:                        xerror("no xmit command with H flag");
                    341: #ifdef MULTICAST
                    342:                makeargs(bfr, sp->s_xmit, histline, sysnames, mc);
                    343: #else
                    344:                (void) sprintf(bfr, sp->s_xmit, histline);
                    345: #endif
                    346:        } else {
                    347:                ofp = xfopen(mktemp(TRANS), "w");
                    348:                if (afmt) {
                    349: #ifdef OLD
                    350:                        fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, FULLSYSNAME,
                    351:                                hh.path, hh.subdate, hh.title);
                    352: #else /* !OLD */
                    353:                        logerr("Must have OLD defined to use A flag for xmit");
                    354:                        return FALSE;
                    355: #endif /* !OLD */
                    356:                } else
                    357:                        hwrite(&hh, ofp);
                    358:                if (!notify)
                    359:                        while ((c = getc(ifp)) != EOF)
                    360:                                putc(c, ofp);
                    361:                if (ferror(ofp))
                    362:                        xerror("write failed on transmit");
                    363:                (void) fclose(ifp);
                    364:                (void) fclose(ofp);
                    365:                if (*sp->s_xmit == '\0')
                    366:                        (void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
                    367:                else
                    368: #ifdef MULTICAST
                    369:                        makeargs(bfr, sp->s_xmit, TRANS, sysnames, mc);
                    370: #else /* !MULTICAST */
                    371:                        (void) sprintf(bfr, sp->s_xmit, TRANS);
                    372: #endif /* !MULTICAST */
                    373:        }
                    374: 
                    375:        /* At this point, the command to be executed is in bfr. */
                    376:        if (noshell) {
                    377:                if (pid = fork())
                    378:                        fwait(pid);
                    379:                else {
                    380:                        (void) close(0);
                    381:                        (void) open(TRANS, 0);
                    382:                        ptr = bfr;
                    383:                        for (pid = 0; pid < 19; pid++) {
                    384:                                while (isspace(*ptr))
                    385:                                        *ptr++ = 0;
                    386:                                argv[pid] = ptr;
                    387:                                while (!isspace(*++ptr) && *ptr)
                    388:                                        ;
                    389:                                if (!*ptr)
                    390:                                        break;
                    391:                        }
                    392:                        argv[++pid] = 0;
                    393:                        (void) setgid(gid);
                    394:                        (void) setuid(uid);
                    395:                        execv(argv[0], argv);
                    396:                        xerror("Can't execv %s", argv[0]);
                    397:                }
                    398:        } else {
                    399:                if (!history && sp->s_xmit[0] && !index(bfr, '<')) {
                    400:                        char newcmd[LBUFLEN];
                    401: 
                    402:                        (void) sprintf(newcmd, "(%s) <%s", bfr,
                    403:                            useexist ? firstbufname : TRANS);
                    404:                        system(newcmd);
                    405:                } else
                    406:                        system(bfr);
                    407:        }
                    408:        if (!appfile && !useexist && !history)
                    409:                (void) unlink(TRANS);
                    410:        (void) fclose(ifp);
                    411:        return TRUE;
                    412: }
                    413: 
                    414: #ifdef MULTICAST
                    415: makeargs(buf, cmd, arg2, sysargs, sac)
                    416: char *buf;
                    417: char *cmd;
                    418: char *arg2;
                    419: register char **sysargs;
                    420: int sac;
                    421: {
                    422:        register char *p = cmd;
                    423:        register char *q;
                    424:        register ac = 0;
                    425:        register char *b = buf;
                    426: 
                    427:        q = p;
                    428:        do {
                    429:                if (q = index(q, ' '))
                    430:                        *q = '\0';
                    431:                if (index(p, '%')) {
                    432:                        switch (++ac) {
                    433:                        case 1:
                    434:                                while (--sac >= 0) {
                    435:                                        sprintf(b, p, *sysargs++);
                    436:                                        b = index(b, '\0');
                    437:                                }
                    438:                                break;
                    439:                        case 2:
                    440:                                sprintf(b, p, arg2);
                    441:                                b = index(b, '\0');
                    442:                                break;
                    443:                        default:
                    444:                                if (q)
                    445:                                        *q = ' ';
                    446:                                xerror("badly formed command: %s", cmd);
                    447:                        }
                    448:                } else {
                    449:                        strcpy(b, p);
                    450:                        b = index(b, '\0');
                    451:                }
                    452:                if (q) {
                    453:                        *q = ' ';
                    454:                        p = q;
                    455:                        while (isspace(*q))
                    456:                                q++;
                    457:                }
                    458:        } while (q != NULL);
                    459: }
                    460: #endif /* MULTICAST */
                    461: 
                    462: typedef struct {
                    463:        char *dptr;
                    464:        int dsize;
                    465: } datum;
                    466: 
                    467: /*
                    468:  * Return TRUE if we have seen this file before, else FALSE.
                    469:  */
                    470: history(hp)
                    471: struct hbuf *hp;
                    472: {
                    473: #ifdef DBM
                    474:        datum lhs, rhs;
                    475:        datum fetch();
                    476: #else /* !DBM */
                    477:        register FILE *hfp;
                    478:        register char *p;
                    479: #endif /* !DBM */
                    480:        char lcident[BUFLEN];
                    481:        extern char histline[];
                    482: 
                    483: #ifdef DEBUG
                    484:        fprintf(stderr,"history(%s)\n", hp->ident);
                    485: #endif /* DEBUG */
                    486:        /*
                    487:         * Make the article ID case insensitive.
                    488:         */
                    489:        (void) strcpy(lcident, hp->ident);
                    490:        lcase(lcident);
                    491: 
                    492:        idlock(lcident);
                    493: #ifdef DBM
                    494:        initdbm(ARTFILE);
                    495:        lhs.dptr = lcident;
                    496:        lhs.dsize = strlen(lhs.dptr) + 1;
                    497:        rhs = fetch(lhs);
                    498:        if (rhs.dptr)
                    499:                return(TRUE);
                    500: #else /* !DBM */
                    501:        hfp = xfopen(histfile(lcident), "r");
                    502:        while (fgets(bfr, BUFLEN, hfp) != NULL) {
                    503:                p = index(bfr, '\t');
                    504:                if (p == NULL)
                    505:                        p = index(bfr, '\n');
                    506:                if (p != NULL)  /* can happen if nulls in file */
                    507:                        *p = 0;
                    508:                lcase(bfr);
                    509: 
                    510:                if (strcmp(bfr, lcident) == 0) {
                    511:                        (void) fclose(hfp);
                    512:                        idunlock();
                    513: #ifdef DEBUG
                    514:                        fprintf(stderr,"history returns true\n");
                    515: #endif /* DEBUG */
                    516:                        return TRUE;
                    517:                }
                    518:        }
                    519:        (void) fclose(hfp);
                    520: #endif /* !DBM */
                    521:        histline[0] = '\0';
                    522:        addhist(hp->ident);
                    523:        addhist("\t");
                    524: #ifdef DEBUG
                    525:        fprintf(stderr,"history returns false\n");
                    526: #endif
                    527:        return FALSE;
                    528: }
                    529: 
                    530: char histline[PATHLEN];
                    531: 
                    532: addhist(msg)
                    533: char *msg;
                    534: {
                    535:        (void) strcat(histline, msg);
                    536: }
                    537: 
                    538: savehist(hline)
                    539: char *hline;
                    540: {
                    541:        register FILE *hfp;
                    542:        datum lhs, rhs;
                    543:        long fpos;
                    544:        register char *p;
                    545: 
                    546:        hfp = xfopen(ARTFILE, "a");
                    547:        fpos = ftell(hfp);
                    548:        fprintf(hfp, "%s\n", hline);
                    549:        (void) fclose(hfp);
                    550: #ifdef DBM
                    551:        /* We assume that history has already been called, calling dbminit. */
                    552:        p = index(hline, '\t');
                    553:        if (p)
                    554:                *p = 0;
                    555:        lcase(hline);
                    556:        lhs.dptr = hline;
                    557:        lhs.dsize = strlen(lhs.dptr) + 1;
                    558:        rhs.dptr = (char *)&fpos;
                    559:        rhs.dsize = sizeof fpos;
                    560:        store(lhs, rhs);
                    561: #else /* !DBM */
                    562:        /* also append to proper history subfile */
                    563:        hfp = xfopen(histfile(hline), "a");
                    564:        fprintf(hfp, "%s\n", hline);
                    565:        (void) fclose(hfp);
                    566: #endif /* !DBM */
                    567:        idunlock();
                    568: }
                    569: 
                    570: /*
                    571:  * Save partial news.
                    572:  */
                    573: /* ARGSUSED */
                    574: newssave(fd, dummy)
                    575: FILE *fd;
                    576: char *dummy;
                    577: {
                    578:        register FILE *tofd, *fromfd;
                    579:        char sfname[BUFLEN];
                    580:        register int c;
                    581:        time_t tim;
                    582: 
                    583:        if (fd == NULL)
                    584:                fromfd = xfopen(INFILE, "r");
                    585:        else
                    586:                fromfd = fd;
                    587:        (void) umask(savmask);
                    588:        (void) setgid(gid);
                    589:        (void) setuid(uid);
                    590: 
                    591:        (void) sprintf(sfname, "%s/%s", userhome, PARTIAL);
                    592:        if ((tofd = fopen(sfname, "a")) == NULL)
                    593:                xerror("Cannot save partial news in %s", sfname);
                    594:        (void) time(&tim);
                    595:        fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
                    596:        while ((c = getc(fromfd)) != EOF)
                    597:                putc(c, tofd);
                    598:        (void) fclose(fromfd);
                    599:        (void) fclose(tofd);
                    600:        printf("News saved in %s\n", sfname);
                    601:        xxit(1);
                    602: }
                    603: 
                    604: /*
                    605:  * Handle dates in header.
                    606:  */
                    607: 
                    608: dates(hp)
                    609: struct hbuf *hp;
                    610: {
                    611:        time_t edt;
                    612: 
                    613:        if (*hp->subdate) {
                    614:                if (cgtdate(hp->subdate) < 0) {
                    615:                        xerror("Cannot parse submittal date '%s'", hp->subdate);
                    616:                }
                    617:        } else {
                    618:                (void) time(&edt);
                    619:                (void) strcpy(hp->subdate, arpadate(&edt));
                    620:        }
                    621: }
                    622: 
                    623: char lockname[80];
                    624: idlock(str)
                    625: char *str;
                    626: {
                    627:        register int i;
                    628:        char tempname[80];
                    629:        time_t now;
                    630:        struct stat sbuf;
                    631:        extern int errno;
                    632: #ifdef VMS
                    633:        int fd;
                    634: 
                    635:        (void) sprintf(lockname, "/tmp/%s.l.1", str);
                    636:        if ((fd = creat(lockname, 0444)) < 0) {
                    637: #else /* !VMS */
                    638:        (void) strcpy(tempname, "/tmp/LTMP.XXXXXX");
                    639:        (void) mktemp(tempname);
                    640:        (void) sprintf(lockname, "/tmp/L%s", str);
                    641: #ifdef FOURTEENMAX
                    642:        lockname[5 /* /tmp/ */ + 14] = '\0';
                    643: #endif
                    644:        i = creat(tempname, 0666);
                    645:        if (i < 0)
                    646:                xerror("Cannot creat %s: errno %d", tempname, errno);
                    647:        (void) close(i);
                    648:        while (link(tempname, lockname)) {
                    649: #endif /* !VMS */
                    650:                (void) time(&now);
                    651:                i = stat(lockname, &sbuf);
                    652:                if (i < 0) {
                    653:                        xerror("Directory permission problem in /tmp");
                    654:                }
                    655:                if (sbuf.st_mtime + 10*60 < now) {
                    656:                        (void) unlink(lockname);
                    657:                        logerr("Article %s locked up", str);
                    658:                        break;
                    659:                }
                    660:                log("waiting on lock for %s", lockname);
                    661:                sleep((unsigned)60);
                    662:        }
                    663: #ifdef VMS
                    664:        (void) close(fd);
                    665: #endif
                    666:        (void) unlink(tempname);
                    667: }
                    668: 
                    669: idunlock()
                    670: {
                    671:        (void) unlink(lockname);
                    672: }
                    673: 
                    674: /*
                    675:  * Put a unique name into header.ident.
                    676:  */
                    677: getident(hp)
                    678: struct hbuf *hp;
                    679: {
                    680:        long seqn;
                    681:        register FILE *fp;
                    682: 
                    683:        lock();
                    684:        fp = xfopen(SEQFILE, "r");
                    685:        (void) fgets(bfr, BUFLEN, fp);
                    686:        (void) fclose(fp);
                    687:        seqn = atol(bfr) + 1;
                    688: #ifdef VMS
                    689:        (void) unlink(SEQFILE);
                    690: #endif /* VMS */
                    691:        fp = xfopen(SEQFILE, "r+w");
                    692:        fprintf(fp, "%ld\n", seqn);
                    693:        (void) fclose(fp);
                    694:        unlock();
                    695: #ifdef HIDDENNET
                    696:        if (strcmp(LOCALSYSNAME, FULLSYSNAME))
                    697:                (void) sprintf(hp->ident, "<%ld@%s.%s%s>", seqn, LOCALSYSNAME, FULLSYSNAME,
                    698:                MYDOMAIN);
                    699:        else
                    700: #endif /* !HIDDENNET */
                    701:        (void) sprintf(hp->ident, "<%ld@%s%s>", seqn, FULLSYSNAME, MYDOMAIN);
                    702: }
                    703: 
                    704: /*
                    705:  * Check that header.nbuf contains only valid newsgroup names;
                    706:  * exit with error if not valid.
                    707:  *
                    708:  */
                    709: ngfcheck(isproc)
                    710: int isproc;
                    711: {
                    712:        register char *s1, *s2;
                    713:        register FILE *f;
                    714:        register char *os1;
                    715:        int ngroups = 1;
                    716:        unsigned int ngsize = AFSIZ;
                    717:        char tbuf[BUFLEN], *ngcheck;
                    718: 
                    719:        f = xfopen(ACTIVE, "r");
                    720:        ngcheck = malloc(ngsize);
                    721:        if (ngcheck == NULL)
                    722:                xerror("Can't malloc the active file");
                    723:        s1 = ngcheck;
                    724:        while (fgets(bfr, BUFLEN, f) != NULL) {
                    725:                os1 = s1;
                    726:                for(s2 = bfr; *s2 != '\0' && *s2 != ' ';) {
                    727:                        if (s1 >= &ngcheck[ngsize-2]) {
                    728:                                unsigned int offs = s1 - ngcheck;
                    729:                                ngsize += LBUFLEN;
                    730:                                ngcheck = realloc(ngcheck, ngsize);
                    731:                                if (ngcheck == NULL)
                    732:                                        xerror("Can't realloc active file");
                    733:                                s1 = ngcheck + offs;
                    734:                        }
                    735:                        *s1++ = *s2++;
                    736:                }
                    737:                *s1++ = '\0';
                    738:                if (isproc) /* don't check to see if can post to this group */
                    739:                        continue;
                    740:                while (*s2++ != '\0' && *s2 != ' ')
                    741:                        ;       /* skip max article number */
                    742:                while (*s2++ != '\0' && *s2 != ' ')
                    743:                        ;       /* skip min article number */
                    744:                if (*s2++ != '\0' && *s2 == 'n')
                    745:                        s1 = os1;       /* can't post to this group */
                    746:        }
                    747:        *s1++ = '\0';
                    748:        *s1 = '\0';
                    749:        (void) fclose(f);
                    750: 
                    751:        s1 = header.nbuf;
                    752:        s2 = nbuf;
                    753:        while (*s1 == NGDELIM || *s1 == ' ')
                    754:                s1++;   /* skip leading junk */
                    755:        do {
                    756:                /* there shouldn't be blanks, but give the jerk a break */
                    757:                if (*s1 == NGDELIM || *s1 == ' ') {
                    758:                        *s2++ = '\0';
                    759:                        while (*++s1 == NGDELIM || *s1 == ' ')
                    760:                                ;       /* remove extra commas */
                    761:                        if (*s1 != '\0')
                    762:                                ngroups++;
                    763:                } else
                    764:                        *s2++ = *s1++;
                    765:        } while (*s1 != '\0');
                    766:        if (s2[-1] == NGDELIM)  /* strip trailing commas */
                    767:                s2--;
                    768:        *s2 = '\0';
                    769: 
                    770:        s1 = nbuf;
                    771:        while (*s1 != '\0') {   /* for each newsgroup in header */
                    772:                s2 = ngcheck;
                    773:                while (*s2 != '\0') { /* for each newsgroup in active file */
                    774:                        if (strcmp(s1, s2) == 0)
                    775:                                break;
                    776:                        while (*s2++ != '\0')
                    777:                                ;
                    778:                }
                    779:                if (*s2 == '\0') {      /* not found. remove it */
                    780:                        if (!isproc) {
                    781:                                logerr("Invalid news group '%s'", s1);
                    782:                                newssave(stdin, (char *)NULL);
                    783:                        }
                    784:                        /* See if it's in our alias list */
                    785:                        f = xfopen(ALIASES,"r");
                    786:                        while (fscanf(f,"%s %s", tbuf, bfr) == 2
                    787:                                && strcmp(s1, tbuf))
                    788:                                ;
                    789:                        (void) fclose(f);
                    790:                        if (strcmp(s1, tbuf) == 0) {
                    791:                                logerr("Aliased newsgroup '%s' to '%s'", s1, bfr);
                    792:                                os1 = s1;
                    793:                                s1 = nbuf;
                    794:                                s2 = tbuf;
                    795:                                while (s1 < os1) /* copy left part */
                    796:                                        *s2++ = *s1++;
                    797:                                s1 = bfr;
                    798:                                while (*s1 != '\0') /* copy alias */
                    799:                                        *s2++ = *s1++;
                    800:                                *s2++ = '\0';
                    801:                                s1 = os1;
                    802:                                os1 = nbuf + (s2 - tbuf);
                    803:                                while (*s1++ != '\0') /* skip old group */
                    804:                                        ;
                    805:                                /* copy right part */
                    806:                                tbufcpy(s2, s1);
                    807:                                /* copy back to original buffer */
                    808:                                tbufcpy(nbuf, tbuf);
                    809:                                s1 = os1;
                    810:                        } else {
                    811:                                logerr("Unknown newsgroup '%s' removed", s1);
                    812:                                s2 = s1;
                    813:                                while (*s2++ != '\0')   /* skip the bad one */
                    814:                                        ;
                    815:                                tbufcpy(s1, s2);
                    816:                        }
                    817:                } else { /* It's in our active file */
                    818:                        os1 = s1;
                    819:                        while (*s1++ != '\0')
                    820:                                ;
                    821:                        /* check for local only distribution on incoming
                    822:                           newsgroups. This might occur if someone posted to
                    823:                           general,net.unix */
                    824:                        if(isproc && ngroups > 1 && index(os1, '.') == NULL
                    825:                                && index(header.nbuf, '.') != NULL) {
                    826:                                logerr("Local group '%s' removed", os1);
                    827:                                tbufcpy(os1, s1);
                    828:                                s1 = os1;
                    829:                        }
                    830:                }
                    831:        }
                    832:        /*  remove any duplicates */
                    833:        os1 = s1 = nbuf;
                    834:        for(;;) {
                    835:                if (*s1++ == '\0') {
                    836:                        if (*s1 == '\0')
                    837:                                break;
                    838:                        s2 = s1;
                    839:                        while (*s2 != '\0') {
                    840:                                if (strcmp(os1, s2) == 0) {
                    841:                                        logerr("Duplicate '%s' removed",os1);
                    842:                                        os1 = s2;
                    843:                                        while (*s2++ != '\0') /* skip it */
                    844:                                                ;
                    845:                                        tbufcpy(os1, s2);
                    846:                                } else
                    847:                                        while (*s2++ != '\0')
                    848:                                                ;
                    849:                        }
                    850:                        os1 = s1;
                    851:                        s1[-1] = '\0';
                    852:                }
                    853:        }
                    854:        if (nbuf[0] != '\0') {
                    855:                s1 = header.nbuf;
                    856:                s2 = nbuf;
                    857:                do {
                    858:                        while (*s2 != '\0')
                    859:                                *s1++ = *s2++;
                    860:                        *s1++ = NGDELIM;
                    861:                } while (*++s2 != '\0');
                    862:                *--s1 = '\0';
                    863:                (void) free(ngcheck);
                    864:                return FALSE;
                    865:        }
                    866:        (void) free(ngcheck);
                    867:        return TRUE;
                    868: }
                    869: 
                    870: tbufcpy(s1, s2)
                    871: register char *s1, *s2;
                    872: {
                    873:        do {
                    874:                while (*s2 != '\0')
                    875:                        *s1++ = *s2++;
                    876:                *s1++ = '\0';
                    877:        } while (*++s2 != '\0');
                    878:        *s1 = '\0';
                    879: }
                    880: 
                    881: 
                    882: /*
                    883:  * Figure out who posted the article (which is locally entered).
                    884:  * The results are placed in the header structure hp.
                    885:  */
                    886: gensender(hp, logname)
                    887: struct hbuf *hp;
                    888: char *logname;
                    889: {
                    890:        register char *fn, *p;
                    891:        char buf[BUFLEN];
                    892:        char *fullname(), *getenv();
                    893:        int fd, n;
                    894: 
                    895:        fn = getenv("NAME");
                    896: 
                    897:        if (fn == NULL) {
                    898:                (void) sprintf(buf, "%s/%s", userhome, ".name");
                    899:                fd = open(buf, 0);
                    900:                if (fd >= 0) {
                    901:                        n = read(fd, buf, sizeof buf);
                    902:                        (void) close(fd);
                    903:                        if (n > 0 && buf[0] >= 'A') {
                    904:                                fn = buf;
                    905:                                for (p=fn; *p; p++)
                    906:                                        if (*p < ' ')
                    907:                                                *p = '\0';
                    908:                        }
                    909:                }
                    910:        }
                    911: 
                    912:        if (fn == NULL)
                    913:                fn = fullname(logname);
                    914: 
                    915:        (void) sprintf(hp->path, "%s", logname);
                    916:        (void) sprintf(hp->from, "%s@%s%s (%s)", logname, FULLSYSNAME, MYDOMAIN, fn);
                    917: }
                    918: 
                    919: /*
                    920:  * Trap interrupts.
                    921:  */
                    922: onsig(n)
                    923: int n;
                    924: {
                    925:        static int numsigs = 0;
                    926:        /*
                    927:         * Most UNIX systems reset caught signals to SIG_DFL.
                    928:         * This bad design requires that the trap be set again here.
                    929:         * Unfortunately, if the signal recurs before the trap is set,
                    930:         * the program will die, possibly leaving the lock in place.
                    931:         */
                    932:        if (++numsigs > 100) {
                    933:                logerr("inews ran away looping on signal %d", n);
                    934:                xxit(1);
                    935:        }
                    936:        (void) signal(n, onsig);
                    937:        SigTrap = n;
                    938: }
                    939: 
                    940: #ifdef BATCH
                    941: /*
                    942:  * If the stdin begins with "#", we assume we have been fed a batched
                    943:  * shell script which looks like this:
                    944:  *     #! rnews 1234
                    945:  *     article with 1234 chars
                    946:  *     #! rnews 4321
                    947:  *     article with 4321 chars
                    948:  *
                    949:  * In this case we just exec the unbatcher and let it unpack and call us back.
                    950:  *
                    951:  * Note that there is a potential security hole here.  If the batcher is
                    952:  * /bin/sh, someone could ship you arbitrary stuff to run as shell commands.
                    953:  * The main protection you have is that the effective uid will be news, not
                    954:  * uucp and not the super user.  (That, plus the fact that BATCH is set to
                    955:  * "unbatch" as the system is distributed.)  If you want to run a batched link
                    956:  * and you are security conscious, do not use /bin/sh as the unbatcher.
                    957:  * the thing to do is to change BATCH in your localize.sh file from /bin/sh
                    958:  * to some restricted shell which can only run rnews.
                    959:  */
                    960: checkbatch()
                    961: {
                    962:        int c;
                    963: 
                    964:        c = getc(stdin);
                    965:        if (c != EOF)
                    966:                (void) ungetc(c, stdin);
                    967:        clearerr(stdin);
                    968:        if (c == '#') {
                    969:                char unbatcher[BUFLEN];
                    970: 
                    971:                (void) sprintf(unbatcher, "%s/%s", LIB, BATCH);
                    972:                reset_stdin();
                    973:                execl(unbatcher, "news-unpack", (char *)0);
                    974:                xerror("Unable to exec shell to unpack news.");
                    975:        }
                    976: }
                    977: 
                    978: /*
                    979:  * We've already done a read on stdin, and we want to seek back to the
                    980:  * beginning.  We want the real file descriptor (beyond buffers) to
                    981:  * reflect the true beginning.  Do whatever is necessary.
                    982:  */
                    983: reset_stdin()
                    984: {
                    985:        register FILE *ofd;
                    986:        register int c;
                    987:        char *ofdname;
                    988:        long lseek();
                    989: 
                    990:        /* First try to seek back - if so, it's a cheap way back. */
                    991:        if (lseek(0, 0L, 0) == 0L)
                    992:                return;
                    993: 
                    994:        /* Can't seek, so have to copy input to a file and use that. */
                    995:        ofdname = "/tmp/inewsXXXXXX";
                    996:        (void) mktemp(ofdname);
                    997:        ofd = fopen(ofdname, "w");
                    998:        while ((c=getc(stdin)) != EOF)
                    999:                putc(c, ofd);
                   1000:        if (ferror(ofd))
                   1001:                xerror("write failed on temp file %s", ofdname);
                   1002:        (void) fclose(stdin);
                   1003:        (void) fclose(ofd);
                   1004: 
                   1005:        /* Now for a few lower level hacks to reopen stdin and make
                   1006:         * absolutely sure that the right fd's are done for the exec.
                   1007:         */
                   1008:        (void) close(0);                /* make sure stdin is really closed. */
                   1009:        (void) open(ofdname, 0);        /* should return zero */
                   1010:        (void) unlink(ofdname);         /* to avoid cleaning it up later. */
                   1011: }
                   1012: #endif /* BATCH */
                   1013: 
                   1014: /*
                   1015:  *     Exit and cleanup.
                   1016:  */
                   1017: xxit(status)
                   1018: int status;
                   1019: {
                   1020:        (void) unlink(INFILE);
                   1021:        (void) unlink(ARTICLE);
                   1022:        while (lockcount > 0)
                   1023:                unlock();
                   1024:        idunlock();
                   1025:        exit(status);
                   1026: }
                   1027: 
                   1028: rwaccess(fname)
                   1029: char *fname;
                   1030: {
                   1031:        int fd;
                   1032: 
                   1033:        fd = open(fname, 2);
                   1034:        if (fd < 0)
                   1035:                return 0;
                   1036:        (void) close(fd);
                   1037:        return 1;
                   1038: }
                   1039: 
                   1040: exists(fname)
                   1041: char *fname;
                   1042: {
                   1043:        int fd;
                   1044: 
                   1045:        fd = open(fname, 0);
                   1046:        if (fd < 0)
                   1047:                return 0;
                   1048:        (void) close(fd);
                   1049:        return 1;
                   1050: }
                   1051: 
                   1052: int    lockcount = 0;                  /* no. of times we've called lock */
                   1053: 
                   1054: #ifdef VMS
                   1055: 
                   1056: #define        SUBLOCK "/tmp/netnews.lck.1"
                   1057: 
                   1058: /*
                   1059:  * Newsystem locking.
                   1060:  * These routines are different for VMS because we can not
                   1061:  * effectively simulate links, and VMS supports multiple
                   1062:  * version numbers of files
                   1063:  */
                   1064: lock()
                   1065: {
                   1066:        register int i;
                   1067:        register int fd;
                   1068: 
                   1069:        if (lockcount++ == 0) {
                   1070:                i = DEADTIME;
                   1071:                while ((fd = creat(SUBLOCK, 0444)) < 0) {
                   1072:                        if (--i < 0) {
                   1073:                                (void) unlink(SUBLOCK);
                   1074:                                logerr("News system locked up");
                   1075:                        }
                   1076:                        if (i < -3)
                   1077:                                xerror("Unable to unlock news system");
                   1078:                        sleep((unsigned)1);
                   1079:                }
                   1080:                (void) close(fd);
                   1081:        }
                   1082: }
                   1083: 
                   1084: unlock()
                   1085: {
                   1086:        if (--lockcount == 0)
                   1087:                (void) unlink(SUBLOCK);
                   1088: }
                   1089: 
                   1090: #else /* !VMS */
                   1091: 
                   1092: /*
                   1093:  * Newsystem locking.
                   1094:  */
                   1095: 
                   1096: #ifdef BSD4_2
                   1097: #include <sys/file.h>
                   1098: static int LockFd = -1;
                   1099: lock()
                   1100: {
                   1101:        LockFd = open(SUBFILE,0);
                   1102:        /* This will sleep until the other program releases the lock */
                   1103:        /* We may need to alarm out of this, but I don't think so */
                   1104:        (void) flock(LockFd, LOCK_EX);
                   1105: }
                   1106: 
                   1107: unlock()
                   1108: {
                   1109:        (void) flock(LockFd, LOCK_UN);
                   1110:        (void) close(LockFd);
                   1111: }
                   1112: #else /* !BSD4_2 */
                   1113: /* Why doesn't USG unix have file locking????? */
                   1114: lock()
                   1115: {
                   1116:        register int i;
                   1117:        extern int errno;
                   1118: 
                   1119:        if (lockcount++ == 0) {
                   1120:                i = DEADTIME;
                   1121:                while (link(SUBFILE, LOCKFILE)) {
                   1122:                        if (errno != EEXIST)
                   1123:                                break;
                   1124:                        if (--i < 0)
                   1125:                                xerror("News system locked up");
                   1126:                        sleep((unsigned)1);
                   1127:                }
                   1128:        }
                   1129: }
                   1130: 
                   1131: unlock()
                   1132: {
                   1133:        if (--lockcount == 0)
                   1134:                (void) unlink(LOCKFILE);
                   1135: }
                   1136: #endif /* !BSD4_2 */
                   1137: #endif /* !VMS */
                   1138: 
                   1139: /*
                   1140:  * Generate the name of the person responsible for posting this article,
                   1141:  * in order to check that two articles were posted by the same person.
                   1142:  */
                   1143: char *
                   1144: senderof(hp)
                   1145: struct hbuf *hp;
                   1146: {
                   1147:        char *q, *tp;
                   1148:        char *tailpath();
                   1149: 
                   1150:        if (hp->sender[0])
                   1151:                tp = hp->sender;
                   1152:        else if (hp->from[0])
                   1153:                tp = hp->from;
                   1154:        else
                   1155:                tp = tailpath(hp);
                   1156: 
                   1157:        /* Remove full name */
                   1158:        q = index(tp, ' ');
                   1159:        if (q)
                   1160:                *q = '\0';
                   1161: 
                   1162:        q = malloc((unsigned)(strlen(tp) + 1));
                   1163:        (void) strcpy(q, tp);
                   1164:        return q;
                   1165: }

unix.superglobalmegacorp.com

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