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