|
|
1.1 ! root 1: /* ! 2: * inews - insert, receive, and transmit news articles. ! 3: */ ! 4: ! 5: static char *SccsId = "@(#)inews.c 2.30 6/24/83"; ! 6: ! 7: #include "iparams.h" ! 8: ! 9: /* local defines for inews */ ! 10: ! 11: #define OPTION 0 /* pick up an option string */ ! 12: #define STRING 1 /* pick up a string of arguments */ ! 13: ! 14: #define UNKNOWN 0001 /* possible modes for news program */ ! 15: #define UNPROC 0002 /* Unprocessed input */ ! 16: #define PROC 0004 /* Processed input */ ! 17: #define CANCEL 0010 /* Cancel an article */ ! 18: #define CREATENG 0020 /* Create a new newsgroup */ ! 19: ! 20: #ifndef SYSBUF ! 21: char SYSBUF[BUFSIZ]; /* to buffer std out */ ! 22: #endif ! 23: char forgedname[100]; /* A user specified -f option. */ ! 24: ! 25: struct { /* options table. */ ! 26: char optlet; /* option character. */ ! 27: char filchar; /* if to pickup string, fill character. */ ! 28: int flag; /* TRUE if have seen this opt. */ ! 29: int oldmode; /* OR of legal input modes. */ ! 30: int newmode; /* output mode. */ ! 31: char *buf; /* string buffer */ ! 32: } *optpt, options[] = { /* ! 33: optlet filchar flag oldmode newmode buf */ ! 34: 't', ' ', FALSE, UNPROC, UNKNOWN, header.title, ! 35: 'n', NGDELIM, FALSE, UNPROC, UNKNOWN, header.nbuf, ! 36: 'e', ' ', FALSE, UNPROC, UNKNOWN, header.expdate, ! 37: 'p', '\0', FALSE, UNKNOWN,PROC, filename, ! 38: 'f', '\0', FALSE, UNPROC, UNKNOWN, forgedname, ! 39: 'F', ' ', FALSE, UNPROC, UNKNOWN, header.followid, ! 40: 'c', '\0', FALSE, UNKNOWN,CANCEL, filename, ! 41: 'C', '\0', FALSE, UNKNOWN,CREATENG, header.nbuf, ! 42: #define Dflag options[8].flag ! 43: 'D', '\0', FALSE, UNPROC, UNKNOWN, filename, ! 44: #define hflag options[9].flag ! 45: 'h', '\0', FALSE, UNPROC, UNKNOWN, filename, ! 46: '\0', '\0', 0, 0, 0, (char *)NULL ! 47: }; ! 48: ! 49: FILE *mailhdr(); ! 50: ! 51: /* ! 52: * Authors: ! 53: * Matt Glickman [email protected] ! 54: * Mark Horton [email protected] ! 55: * Stephen Daniels [email protected] ! 56: * Tom Truscott [email protected] ! 57: * IHCC version adapted by: ! 58: * Larry Marek [email protected] ! 59: */ ! 60: main(argc, argv) ! 61: int argc; ! 62: register char **argv; ! 63: { ! 64: int state; /* which type of argument to pick up */ ! 65: int tlen, len; /* temps for string processing routine */ ! 66: register char *ptr; /* pointer to rest of buffer */ ! 67: int filchar; /* fill character (state = STRING) */ ! 68: char *user, *home; /* environment temps */ ! 69: struct passwd *pw; /* struct for pw lookup */ ! 70: struct group *gp; /* struct for group lookup */ ! 71: struct srec srec; /* struct for sys file lookup */ ! 72: struct utsname ubuf; ! 73: register int i; ! 74: FILE *mfd; /* mail file file-descriptor */ ! 75: char cbuf[BUFLEN]; /* command buffer */ ! 76: ! 77: /* uuxqt doesn't close all it's files */ ! 78: for (i = 3; !close(i); i++) ! 79: ; ! 80: /* set up defaults and initialize. */ ! 81: mode = UNKNOWN; ! 82: pathinit(); ! 83: ptr = rindex(*argv, '/'); ! 84: if (!ptr) ! 85: ptr = *argv - 1; ! 86: if (!strncmp(ptr+1, "rnews", 5)) ! 87: mode = PROC; ! 88: else if (argc < 2) ! 89: goto usage; ! 90: ! 91: state = OPTION; ! 92: header.title[0] = header.nbuf[0] = filename[0] = '\0'; ! 93: ! 94: /* check for existence of special files */ ! 95: if (!rwaccess(ARTFILE)) { ! 96: mfd = mailhdr(NULL, exists(ARTFILE) ? "Unwritable files!" : "Missing files!"); ! 97: if (mfd != NULL) { ! 98: fprintf(mfd,"System: %s\n\nThere was a problem with %s!!\n", SYSNAME, ARTFILE); ! 99: sprintf(cbuf, "touch %s;chmod 666 %s", ARTFILE, ARTFILE); ! 100: system(cbuf); ! 101: if (rwaccess(ARTFILE)) ! 102: fprintf(mfd, "The problem has been taken care of.\n"); ! 103: else ! 104: fprintf(mfd, "Corrective action failed - check suid bits.\n"); ! 105: mclose(mfd); ! 106: } ! 107: } ! 108: if (!rwaccess(ACTIVE)) { ! 109: mfd = mailhdr(NULL, exists(ACTIVE) ? "Unwritable files!" : "Missing files!"); ! 110: if (mfd != NULL) { ! 111: fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", SYSNAME, ACTIVE); ! 112: sprintf(cbuf, "touch %s;chmod 666 %s", ACTIVE, ACTIVE); ! 113: system(cbuf); ! 114: if (rwaccess(ACTIVE)) ! 115: fprintf(mfd, "The problem has been taken care of.\n"); ! 116: else ! 117: fprintf(mfd, "Corrective action failed - check suid bits.\n"); ! 118: mclose(mfd); ! 119: } ! 120: } ! 121: setbuf(stdout, SYSBUF); ! 122: sigtrap = FALSE; /* true if a signal has been caught */ ! 123: /* ! 124: signal(SIGQUIT, SIG_IGN); ! 125: */ ! 126: if (mode != PROC) { ! 127: signal(SIGHUP, onsig); ! 128: signal(SIGINT, onsig); ! 129: } ! 130: savmask = umask(N_UMASK); /* set up mask */ ! 131: uid = (unsigned) getuid(); ! 132: gid = (unsigned) getgid(); ! 133: duid = geteuid(); ! 134: dgid = getegid(); ! 135: if (uid == 0 && geteuid() == 0) { ! 136: /* ! 137: * Must go through with this kludge since ! 138: * some systems do not honor the setuid bit ! 139: * when root invokes a setuid program. ! 140: */ ! 141: if ((pw = getpwnam(NEWSU)) == NULL) ! 142: xerror("Cannot get NEWSU pw entry"); ! 143: ! 144: duid = pw->pw_uid; ! 145: if ((gp = getgrnam(NEWSG)) == NULL) ! 146: xerror("Cannot get NEWSG gr entry"); ! 147: dgid = gp->gr_gid; ! 148: setuid(duid); ! 149: setgid(dgid); ! 150: } ! 151: ! 152: #ifndef IHCC ! 153: /* ! 154: * We force the use of 'getuser()' to prevent forgery of articles ! 155: * by just changing $LOGNAME ! 156: */ ! 157: if ((user = getenv("USER")) == NULL) ! 158: user = getenv("LOGNAME"); ! 159: if ((home = getenv("HOME")) == NULL) ! 160: home = getenv("LOGDIR"); ! 161: #endif ! 162: if (user == NULL || home == NULL) ! 163: getuser(); ! 164: else { ! 165: if (username[0] == 0) { ! 166: strcpy(username, user); ! 167: } ! 168: strcpy(userhome, home); ! 169: } ! 170: getuser(); ! 171: strcpy(whatever, username); ! 172: ! 173: /* loop once per arg. */ ! 174: ! 175: ++argv; /* skip first arg, which is prog name. */ ! 176: ! 177: while (--argc) { ! 178: if (state == OPTION) { ! 179: if (**argv != '-') { ! 180: sprintf(bfr, "Bad option string \"%s\"", *argv); ! 181: xerror(bfr); ! 182: } ! 183: while (*++*argv != '\0') { ! 184: for (optpt = options; optpt->optlet != '\0'; ++optpt) { ! 185: if (optpt->optlet == **argv) ! 186: goto found; ! 187: } ! 188: /* unknown option letter */ ! 189: usage: ! 190: fprintf(stderr, "usage: inews -t title"); ! 191: fprintf(stderr, " [ -n newsgroups ]"); ! 192: fprintf(stderr, " [ -e expiration date ]\n"); ! 193: fprintf(stderr, "\t[ -f sender]\n\n"); ! 194: fprintf(stderr, " inews -p [ filename ]\n"); ! 195: xxit(1); ! 196: ! 197: found:; ! 198: if (optpt->flag == TRUE || (mode != UNKNOWN && ! 199: (mode&optpt->oldmode) == 0)) { ! 200: sprintf(bfr, "Bad %c option", **argv); ! 201: xerror(bfr); ! 202: } ! 203: if (mode == UNKNOWN) ! 204: mode = optpt->newmode; ! 205: filchar = optpt->filchar; ! 206: optpt->flag = TRUE; ! 207: state = STRING; ! 208: ptr = optpt->buf; ! 209: len = BUFLEN; ! 210: } ! 211: ! 212: argv++; /* done with this option arg. */ ! 213: ! 214: } else { ! 215: ! 216: /* ! 217: * Pick up a piece of a string and put it into ! 218: * the appropriate buffer. ! 219: */ ! 220: if (**argv == '-') { ! 221: state = OPTION; ! 222: argc++; /* uncount this arg. */ ! 223: continue; ! 224: } ! 225: ! 226: if ((tlen = strlen(*argv)) >= len) ! 227: xerror("Argument string too long"); ! 228: strcpy(ptr, *argv++); ! 229: ptr += tlen; ! 230: if (*(ptr-1) != filchar) ! 231: *ptr++ = filchar; ! 232: len -= tlen + 1; ! 233: *ptr = '\0'; ! 234: } ! 235: } ! 236: ! 237: /* ! 238: * ALL of the command line has now been processed. (!) ! 239: */ ! 240: ! 241: tty = isatty(fileno(stdin)); ! 242: if (!Dflag && mode != PROC && mode != CREATENG) { ! 243: if (recording(header.nbuf)) { ! 244: if (!tty) ! 245: fwait(fsubr(newssave, stdin, NULL)); ! 246: xerror("aborted due to recording"); ! 247: } ! 248: } ! 249: ! 250: /* This code is really intended to be replaced by the control message. */ ! 251: if (mode == CANCEL) { ! 252: char *p; FILE *f; ! 253: f = xfopen(filename, "r"); ! 254: hread(&header, f, TRUE); ! 255: p = index(header.path, ' '); ! 256: if (p != NULL) ! 257: *p = 0; ! 258: p = header.path; ! 259: if (strncmp(whatever, p, strlen(whatever)) ! 260: && uid != ROOTID && uid != geteuid() && uid) ! 261: xerror("Not contributor"); ! 262: cancel(); ! 263: xxit(0); ! 264: } ! 265: ! 266: if (*header.nbuf) ! 267: lcase(header.nbuf); ! 268: if (mode != PROC) { ! 269: getident(&header); ! 270: #ifdef MYORG ! 271: strcpy(header.organization, MYORG); ! 272: if (strncmp(header.organization, "Frobozz", 7) == 0) ! 273: header.organization[0] = '\0'; ! 274: if (ptr = getenv("ORGANIZATION")) ! 275: strcpy(header.organization, ptr); ! 276: /* ! 277: * Note that the organization can also be turned off by ! 278: * setting it to the null string, either in MYORG or ! 279: * $ORGANIZATION in the environment. ! 280: */ ! 281: if (header.organization[0] == '/') { ! 282: mfd = fopen(header.organization, "r"); ! 283: if (mfd) { ! 284: fgets(header.organization, sizeof header.organization, mfd); ! 285: fclose(mfd); ! 286: } ! 287: ptr = index(header.organization, '\n'); ! 288: if (ptr) ! 289: *ptr = 0; ! 290: } ! 291: #endif ! 292: if (hflag) { ! 293: /* Fill in a few to make frmread return TRUE */ ! 294: strcpy(header.subdate, "today"); ! 295: strcpy(header.path, "me"); ! 296: strcpy(header.oident, "id"); ! 297: /* Allow the user to supply some headers. */ ! 298: hread(&header, stdin, FALSE); ! 299: /* But there are certain fields we won't let him specify. */ ! 300: if (header.from) ! 301: strcpy(forgedname, header.from); ! 302: header.from[0] = '\0'; ! 303: header.path[0] = '\0'; ! 304: header.subdate[0] = '\0'; ! 305: header.sender[0] = '\0'; ! 306: if (strcmp(header.oident, "id") == 0) ! 307: header.oident[0] = '\0'; ! 308: ngcat(header.nbuf); ! 309: } ! 310: if (forgedname[0]) { ! 311: strcpy(header.from, forgedname); ! 312: sprintf(header.sender, "%s@%s%s", ! 313: username, SYSNAME, MYDOMAIN); ! 314: } else { ! 315: gensender(&header, username); ! 316: } ! 317: strcpy(header.postversion, genversion()); ! 318: } ! 319: ! 320: /* Authorize newsgroups. */ ! 321: if (mode == PROC) { ! 322: checkbatch(); ! 323: signal(SIGHUP, SIG_IGN); ! 324: signal(SIGINT, SIG_IGN); ! 325: signal(SIGQUIT, SIG_IGN); ! 326: if (hread(&header, stdin, TRUE) == NULL) ! 327: xerror("Inbound news is garbled"); ! 328: input(); ! 329: if (history(&header)) { ! 330: fprintf(stderr, "Duplicate article %s rejected\n", header.ident); ! 331: log("Duplicate article %s rejected", header.ident); ! 332: xxit(0); ! 333: } ! 334: } ! 335: ngcat(header.nbuf); ! 336: ! 337: /* Easy way to make control messages, since all.all.ctl is unblessed */ ! 338: if (mode != PROC && prefix(header.title, "cmsg ") && header.ctlmsg[0] == 0) ! 339: strcpy(header.ctlmsg, &header.title[5]); ! 340: is_ctl = mode != CREATENG && ! 341: (ngmatch(header.nbuf, "all.all.ctl,") || header.ctlmsg[0]); ! 342: #ifdef DEBUG ! 343: fprintf(stderr,"is_ctl set to %d\n", is_ctl); ! 344: #endif ! 345: ! 346: /* Must end in comma (NGDELIM) */ ! 347: #define MODGROUPS "mod.all,all.mod,all.announce," ! 348: if (ngmatch(header.nbuf, MODGROUPS) && !header.approved[0]) { ! 349: mfd = mailhdr(&header, "Moderated newsgroup"); ! 350: if (mfd) { ! 351: fprintf(mfd, "This newsgroup is moderated, and cannot be posted to directly.\n"); ! 352: fprintf(mfd, "Please mail your article to the moderator for posting.\n"); ! 353: hwrite(&header, mfd); ! 354: if (infp) ! 355: while ((i = getc(infp)) != EOF) ! 356: putc(i, mfd); ! 357: mclose(mfd); ! 358: } ! 359: xerror("Unapproved moderated newsgroup\n"); ! 360: } ! 361: ! 362: if (mode == PROC) { ! 363: strcpy(nbuf, header.nbuf); ! 364: if (s_find(&srec, FULLSYSNAME) == FALSE) ! 365: xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE); ! 366: ngsquash(nbuf, srec.s_nbuf); ! 367: ! 368: } ! 369: else if (mode != CREATENG) { ! 370: if (!*header.title) ! 371: xerror("No title"); ! 372: if (!*header.nbuf) ! 373: strcpy(header.nbuf, DFLTNG); ! 374: else if (!is_ctl) ! 375: ngfcheck(FALSE); ! 376: ngcat(header.nbuf); ! 377: strcpy(nbuf, header.nbuf); ! 378: } ! 379: else { /* mode == CREATENG */ ! 380: ngcat(header.nbuf); ! 381: strcpy(nbuf, header.nbuf); ! 382: } ! 383: ! 384: for (ptr = nbuf; (ptr = index(ptr, NGDELIM)) != NULL; *ptr++ = '\0') ! 385: ; ! 386: if (!is_ctl && header.followid[0] == '\0') ! 387: for (ptr = nbuf; *ptr;) { ! 388: if (!exists(dirname(ptr))) ! 389: ngcheck(ptr); ! 390: while (*ptr++) ! 391: ; ! 392: } ! 393: else if (mode <= UNPROC) ! 394: ctlcheck(); ! 395: for (ptr = nbuf; *ptr;) { ! 396: if (*ptr != '-') ! 397: goto out; ! 398: while (*ptr++) ! 399: ; ! 400: } ! 401: xerror("No valid newsgroups in '%s'", header.nbuf); ! 402: out: ! 403: ! 404: /* Determine input. */ ! 405: if (mode != PROC) ! 406: input(); ! 407: ! 408: #ifndef VMS ! 409: /* Go into the background so the user can get on with his business. */ ! 410: if (mode != PROC) { ! 411: i = fork(); ! 412: if (i != 0) ! 413: exit(0); ! 414: } ! 415: #endif VMS ! 416: ! 417: /* Do the actual insertion. */ ! 418: insert(); ! 419: } ! 420: ! 421: /* ! 422: * Create directory named by bfr. ! 423: * Don't if user doesn't want to. ! 424: */ ! 425: ngcheck(ngname) ! 426: char *ngname; ! 427: { ! 428: char class[120]; ! 429: char dir[256]; ! 430: char *cp; ! 431: ! 432: strcpy(dir, dirname(ngname)); ! 433: if (mode == PROC) { ! 434: #ifdef AUTONEWNG ! 435: mknewsg(dir, ngname); ! 436: #endif ! 437: return 1; ! 438: } ! 439: ! 440: /* ! 441: * If a user is trying to input to a non-existent group complain. ! 442: * First check to see if the newsgroup ever existed. To do this, try ! 443: * to find the name in the "active" file. ! 444: */ ! 445: if (mode != CREATENG && !is_ctl) { ! 446: /* Ick! Figure out if the newsgroup is in the active file. */ ! 447: sprintf(dir, "grep -s '^%s ' %s", ngname, ACTIVE); ! 448: if ((system(dir) != 0)) ! 449: xerror("There is no such newsgroup as %s.", ngname); ! 450: else { ! 451: strcpy(dir, dirname(ngname)); ! 452: mknewsg(dir, ngname); ! 453: return 0; ! 454: } ! 455: } ! 456: /* ! 457: * Only certain users are allowed to create newsgroups ! 458: */ ! 459: if (uid != ROOTID && uid != geteuid() && uid) ! 460: xerror("Please contact one of the local netnews people\n\tto create this group for you"); ! 461: ! 462: /* Broadcast the new newsgroup */ ! 463: strcpy(class, ngname); ! 464: for (cp=class; *cp && *cp!='.'; cp++) ! 465: ; ! 466: if (*cp) ! 467: *cp = 0; ! 468: else { ! 469: mknewsg(dir, ngname); ! 470: exit(0); /* Local newsgroup */ ! 471: } ! 472: sprintf(bfr, "inews -D -n %s.ctl -t cmsg newgroup %s", ngname, ngname); ! 473: printf("Please type in a paragraph describing the new newsgroup.\n"); ! 474: printf("End with control D as usual.\n"); ! 475: printf("%s\n", bfr); ! 476: fflush(stdout); ! 477: system(bfr); ! 478: exit(0); ! 479: } ! 480: ! 481: #include <errno.h> ! 482: char firstbufname[100]; ! 483: /* ! 484: * Link ARTICLE into dir for ngname and update active file. ! 485: */ ! 486: localize(ngname) ! 487: char *ngname; ! 488: { ! 489: FILE *fp; ! 490: struct stat status; ! 491: char afline[BUFLEN]; ! 492: long ngsize; ! 493: long fpos; ! 494: int i, e; ! 495: extern int errno; ! 496: ! 497: lock(); ! 498: actfp = fopen(ACTIVE, "r+"); ! 499: for(;;) { ! 500: fpos = ftell(actfp); ! 501: if (fgets(afline, sizeof afline, actfp) == NULL) { ! 502: unlock(); ! 503: return FALSE; /* No such newsgroup locally */ ! 504: } ! 505: if (prefix(afline, ngname)) { ! 506: sscanf(afline, "%s %ld", bfr, &ngsize); ! 507: if (strcmp(bfr, ngname) == 0) { ! 508: break; ! 509: } ! 510: if (ngsize < 0 || ngsize > 99998) { ! 511: log("found bad ngsize %d ng %s, setting to 1", ngsize, bfr); ! 512: ngsize = 1; ! 513: } ! 514: } ! 515: } ! 516: for (;;) { ! 517: sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1); ! 518: if (link(ARTICLE, bfr) == 0) break; ! 519: e = errno; /* keep log from clobbering it */ ! 520: fprintf(stderr, "Cannot install article as %s\n", bfr); ! 521: log("Cannot install article as %s", bfr); ! 522: if (e != EEXIST) { ! 523: log("Link into %s failed, errno %d, check dir permissions.", bfr, e); ! 524: unlock(); ! 525: return FALSE; ! 526: } ! 527: ngsize++; ! 528: } ! 529: ! 530: /* Next two lines program around a bug in 4.1BSD stdio. */ ! 531: fclose(actfp); ! 532: actfp = fopen(ACTIVE, "r+"); ! 533: ! 534: fseek(actfp, fpos, 0); ! 535: /* Has to be same size as old because of %05d. ! 536: * This will overflow with 99999 articles. ! 537: */ ! 538: fprintf(actfp, "%s %05ld\n", ngname, ngsize+1); ! 539: fclose(actfp); ! 540: unlock(); ! 541: if (firstbufname[0] == '\0') ! 542: strcpy(firstbufname, bfr); ! 543: sprintf(bfr, "%s/%ld ", ngname, ngsize+1); ! 544: addhist(bfr); ! 545: return TRUE; ! 546: } ! 547: ! 548: /* ! 549: * Localize for each newsgroup and broadcast. ! 550: */ ! 551: insert() ! 552: { ! 553: register char *ptr; ! 554: register FILE *tfp; ! 555: int badgroup = 0, goodgroup = 0; ! 556: ! 557: /* Fill up the rest of header. */ ! 558: if (mode != PROC) { ! 559: history(&header); ! 560: } ! 561: dates(&header); ! 562: addhist(header.recdate); ! 563: addhist("\t"); ! 564: log("%s %s ng %s subj '%s'", mode==PROC ? "received" : "posted", header.ident, header.nbuf, header.title); ! 565: if (mode==PROC) ! 566: log("from %s relay %s", header.from, header.relayversion); ! 567: ! 568: /* Write article to temp file. */ ! 569: tfp = xfopen(mktemp(ARTICLE), "w"); ! 570: lhwrite(&header, tfp); ! 571: while (fgets(bfr, BUFLEN, infp) != NULL) { ! 572: /* ! 573: if (!strncmp(bfr, "From ", 5)) ! 574: putc('>', tfp); ! 575: */ ! 576: fputs(bfr, tfp); ! 577: } ! 578: fclose(tfp); ! 579: fclose(infp); ! 580: ! 581: if (is_ctl) { ! 582: control(&header); ! 583: goodgroup++; ! 584: if (!localize("control")) { ! 585: sprintf(bfr, "%s/%s", SPOOL, "control"); ! 586: mknewsg(bfr, "control"); ! 587: if (!localize("control")) { ! 588: tfp = mailhdr(NULL, "No control newsgroup"); ! 589: if (tfp) { ! 590: fprintf(tfp, "Can't create newsgroup 'control'.\n"); ! 591: mclose(tfp); ! 592: } ! 593: } ! 594: } ! 595: } else { ! 596: for (ptr = nbuf; *ptr;) { ! 597: if (*ptr == '-') { ! 598: while (*ptr++) ! 599: ; ! 600: continue; ! 601: } ! 602: strcpy(bfr, dirname(ptr)); ! 603: if (!exists(bfr)) { ! 604: #ifdef AUTONEWNG ! 605: mknewsg(bfr, ptr); ! 606: #else ! 607: getapproval(ptr); ! 608: badgroup++; ! 609: #endif ! 610: } ! 611: else ! 612: goodgroup++; ! 613: if (*nbuf) ! 614: localize(ptr); ! 615: while (*ptr++) ! 616: ; ! 617: } ! 618: } ! 619: ! 620: #ifdef NOFORWARD ! 621: if (*nbuf) ! 622: #endif ! 623: if (goodgroup) ! 624: broadcast(); ! 625: savehist(); ! 626: xxit(0); ! 627: } ! 628: ! 629: input() ! 630: { ! 631: register int empty = TRUE; ! 632: register char *cp; ! 633: int c; ! 634: long chcount = 0; ! 635: FILE *tmpfp; ! 636: int consec_newlines = 0; ! 637: int linecount = 0; ! 638: ! 639: tmpfp = xfopen(mktemp(INFILE), "w"); ! 640: if (*filename) { ! 641: tty = FALSE; ! 642: infp = xfopen(filename, "r"); ! 643: } else { ! 644: infp = stdin; ! 645: } ! 646: while (!sigtrap && fgets(bfr, BUFLEN, stdin) != NULL) { ! 647: if (mode == PROC) /* zap trailing empty lines */ ! 648: { ! 649: if (bfr[0] == '\n') /* 1 empty line, to go */ ! 650: { ! 651: consec_newlines++; /* count it, in case */ ! 652: continue; /* but don't write it*/ ! 653: } ! 654: /* foo! a non-empty line. write out all saved lines. */ ! 655: while (consec_newlines > 0) ! 656: { ! 657: putc('\n', tmpfp); ! 658: consec_newlines--; ! 659: linecount++; ! 660: } ! 661: } ! 662: if (mode != PROC && tty && strcmp(bfr, ".\n") == 0) ! 663: break; ! 664: for (cp = bfr; c = *cp; cp++) { ! 665: if (isprint(c) || isspace(c) || c=='\b') ! 666: putc(c, tmpfp); ! 667: if (isprint(c)) ! 668: chcount++; ! 669: if (c == '\n') ! 670: linecount++; ! 671: } ! 672: empty = FALSE; ! 673: } ! 674: if (*filename) ! 675: fclose(infp); ! 676: ! 677: sprintf(bfr, "%s/%s", getenv("HOME"), ".signature"); ! 678: if (mode != PROC && (infp = fopen(bfr, "r"))) { ! 679: fprintf(tmpfp, "-- \n"); /* To separate */ ! 680: linecount++; ! 681: while ((c = getc(infp)) != EOF) { ! 682: putc(c, tmpfp); ! 683: if (c == '\n') ! 684: linecount++; ! 685: } ! 686: fclose(infp); ! 687: } ! 688: ! 689: fclose(tmpfp); ! 690: if (sigtrap) { ! 691: if (tty) ! 692: printf("Interrupt\n"); ! 693: if (tty && !empty) ! 694: fwait(fsubr(newssave, (char *) NULL, (char *) NULL)); ! 695: if (!tty) ! 696: log("Blown away by an interrupt %d", sigtrap); ! 697: xxit(1); ! 698: } ! 699: if (tty) ! 700: printf("EOT\n"); ! 701: fflush(stdout); ! 702: infp = fopen(INFILE, "r"); ! 703: if (chcount < 5 && mode <= UNPROC && !is_ctl) ! 704: xerror("You didn't really want to post THAT!"); ! 705: if (header.numlines[0]) { ! 706: /* ! 707: * Check line count if there's already one attached to ! 708: * the article. Could make this a fatal error - ! 709: * throwing it away if it got chopped, in hopes that ! 710: * another copy will come in later with a correct ! 711: * line count. But that seems a bit much for now. ! 712: */ ! 713: if (linecount != header.intnumlines) ! 714: log("linecount expected %d, got %d\n", header.intnumlines, linecount); ! 715: } else { ! 716: /* Attach a line count to the article. */ ! 717: header.intnumlines = linecount; ! 718: sprintf(header.numlines, "%d", linecount); ! 719: } ! 720: } ! 721: ! 722: /* ! 723: * Make the directory for a new newsgroup. ngname should be the ! 724: * full pathname of the directory. Do the other stuff too. ! 725: * The various games with setuid and chown are to try to make sure ! 726: * the directory is owned by NEWSUSR and NEWSGRP, which is tough to ! 727: * do if you aren't root. This will work on a UCB system (which allows ! 728: * setuid(geteuid()) or a USG system (which allows you to give away files ! 729: * you own with chown), otherwise you have to change your kernel to allow ! 730: * one of these things or run with your dirs 777 so that it doesn't matter ! 731: * who owns them. ! 732: */ ! 733: mknewsg(fulldir, ngname) ! 734: char *fulldir; ! 735: char *ngname; ! 736: { ! 737: int pid; ! 738: register char *p; ! 739: char sysbuf[200]; ! 740: char parent[200]; ! 741: struct stat sbuf; ! 742: ! 743: if (ngname == NULL || !isalpha(ngname[0])) ! 744: xerror("Tried to make illegal newsgroup %s", ngname); ! 745: ! 746: /* ! 747: * If the parent is 755 and we're on a USG system, the setuid(getuid) ! 748: * will fail, and since mkdir is suid, and our real uid is random, ! 749: * the mkdir will fail. So we have to temporarily chmod it to 755. ! 750: */ ! 751: strcpy(parent, fulldir); ! 752: p = rindex(parent, '/'); ! 753: if (p) ! 754: *p = '\0'; ! 755: if (stat(parent, &sbuf) < 0) ! 756: sbuf.st_mode = 0777; ! 757: chmod(parent, 0777); ! 758: ! 759: if ((pid = fork()) <= 0) { ! 760: if (setuid(geteuid())) /* This fails on some systems, but ! 761: * works on 4BSD, and 2BSD. */ ! 762: #ifndef USG ! 763: umask(0) ! 764: #endif ! 765: ; ! 766: setgid(getegid()); ! 767: /* Create the directory */ ! 768: mkparents(fulldir); ! 769: sprintf(sysbuf, "mkdir %s", fulldir); ! 770: exit(system(sysbuf)); ! 771: } else if (fwait(pid)) { ! 772: sprintf(sysbuf, "Cannot mkdir %s", fulldir); ! 773: xerror(sysbuf); ! 774: } ! 775: ! 776: chmod(parent, sbuf.st_mode); /* put is back */ ! 777: ! 778: #ifdef USG ! 779: # ifndef CHEAP ! 780: /* ! 781: * Give away the files we just created, which were assigned to our ! 782: * REAL uid. This only works on USG systems. It is an alternative ! 783: * to the setuid call above. The directories we just made are owned ! 784: * by our real uid, so we have to temporarily set our effective uid ! 785: * the same to allow the chown. Fortunately, USG lets us setuid back. ! 786: */ ! 787: setuid(getuid()); ! 788: chown(fulldir, duid, dgid); ! 789: setuid(duid); ! 790: # endif ! 791: #endif ! 792: ! 793: /* Update the "active newsgroup" file. */ ! 794: if (ngname && *ngname) { ! 795: actfp = xfopen(ACTIVE, "a"); ! 796: fprintf(actfp, "%s 00000\n", ngname); ! 797: fclose(actfp); ! 798: } ! 799: ! 800: log("make newsgroup %s in dir %s", ngname, fulldir); ! 801: } ! 802: ! 803: /* ! 804: * If any parent directories of this dir don't exist, create them. ! 805: */ ! 806: mkparents(dirname) ! 807: char *dirname; ! 808: { ! 809: char buf[200], sysbuf[200]; ! 810: register char *p; ! 811: ! 812: strcpy(buf, dirname); ! 813: p = rindex(buf, '/'); ! 814: if (p) ! 815: *p = '\0'; ! 816: if (exists(buf)) ! 817: return; ! 818: mkparents(buf); ! 819: sprintf(sysbuf, "mkdir %s", buf); ! 820: system(sysbuf); ! 821: } ! 822: ! 823: cancel() ! 824: { ! 825: register FILE *fp; ! 826: ! 827: log("cancel article %s", filename); ! 828: fp = xfopen(filename, "r"); ! 829: if (hread(&header, fp, TRUE) == NULL) ! 830: xerror("Article is garbled.\n"); ! 831: fclose(fp); ! 832: unlink(filename); ! 833: } ! 834: ! 835: /* ! 836: * An article has come in that isn't in a newsgroup we know about. ! 837: * Stash it in the junk directory and notify the local contact person. ! 838: * Note that such articles are NOT broadcast to our neighbors, on the ! 839: * assumption that they are a typographical error. We only keep them ! 840: * here because we might be a new site. ! 841: */ ! 842: getapproval(ng) ! 843: char *ng; ! 844: { ! 845: FILE *fd; ! 846: ! 847: if (localize("junk")) ! 848: return; ! 849: ! 850: sprintf(bfr, "%s/%s", SPOOL, "junk"); ! 851: mknewsg(bfr, "junk"); ! 852: if (localize("junk")) ! 853: return; ! 854: ! 855: fd = mailhdr(NULL, "Strange Newsgroup Received"); ! 856: if (fd != NULL) { ! 857: fprintf(fd, "\nNewsgroup '%s' has been posted to\nby %s.\n\n", ! 858: ng, header.from[0] ? header.from : header.path); ! 859: fprintf(fd, "I was unable to save it in the newsgroup 'junk'\n"); ! 860: fprintf(fd, "I was also unable to create the newsgroup 'junk'\n"); ! 861: mclose(fd); ! 862: } ! 863: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.