|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.