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