|
|
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: * Control message handling code. Deal with messages which are to be ! 16: * acted on by netnews itself rather than by people. ! 17: * ! 18: * See defs.h "news_version" for the real version of netnews. ! 19: */ ! 20: ! 21: #ifdef SCCSID ! 22: static char *SccsId = "@(#)control.c 2.43 3/19/86"; ! 23: #endif /* SCCSID */ ! 24: ! 25: #include "iparams.h" ! 26: ! 27: #define eq(msg) (strcmp(msg, cargv[0]) == 0) ! 28: ! 29: int cargc; ! 30: char **cargv; ! 31: ! 32: FILE *hfopen(); ! 33: FILE *popen(), *mhopen(), *mailhdr(); ! 34: ! 35: char *senderof(); ! 36: #ifdef u370 ! 37: static struct hbuf htmp; ! 38: #endif /* u370 */ ! 39: ! 40: control(h) ! 41: struct hbuf *h; ! 42: { ! 43: register char *ctlmsgtext; ! 44: ! 45: if (strncmp(h->title, "cmsg ", 5) == 0) { ! 46: register char *cp1, *cp2; ! 47: cp1 = h->title; ! 48: cp2 = h->title + 5; ! 49: while (*cp1++ = *cp2++) ! 50: ; ! 51: } ! 52: ! 53: if (*h->ctlmsg) ! 54: ctlmsgtext = h->ctlmsg; ! 55: else ! 56: ctlmsgtext = h->title; ! 57: log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext); ! 58: /* ! 59: * Control messages have the standard format ! 60: * command [args] ! 61: * much like shell commands. Each site has the option ! 62: * of customizing this code to deal with control messages ! 63: * as they see fit, but we would like to buy back the ! 64: * code, ifdeffed or otherwise parameterized, to simplify ! 65: * the maintenence issues. ! 66: */ ! 67: argparse(ctlmsgtext); ! 68: ! 69: if (eq("cancel")) ! 70: return c_cancel(cargc, cargv); ! 71: else if (eq("newgroup")) ! 72: c_newgroup(cargc, cargv); ! 73: else if (eq("ihave")) ! 74: c_ihave(cargc, cargv); ! 75: else if (eq("sendme")) ! 76: c_sendme(cargc, cargv); ! 77: else if (eq("sendbad")) ! 78: c_sendme(cargc, cargv); ! 79: else if (eq("rmgroup")) ! 80: c_rmgroup(cargc, cargv); ! 81: else if (eq("sendsys")) ! 82: c_sendsys(cargc, cargv); ! 83: else if (eq("senduuname")) ! 84: c_senduuname(cargc, cargv); ! 85: else if (eq("version")) ! 86: c_version(cargc, cargv); ! 87: else if (eq("checkgroups")) ! 88: c_checkgroups(cargc, cargv); ! 89: else if (eq("delsub")) ! 90: c_unimp(cargc, cargv); ! 91: else ! 92: c_unknown(h, ctlmsgtext); ! 93: return 0; ! 94: } ! 95: ! 96: /* ! 97: * Parse the string str into separate words in cargc and cargv ! 98: * as per the usual UNIX convention. Nothing fancy here, just ! 99: * blanks and tabs separating words. ! 100: */ ! 101: argparse(str) ! 102: char *str; ! 103: { ! 104: static char *cavpbuf[20]; ! 105: static char cavbuf[256]; ! 106: char *nextfree = cavbuf; ! 107: ! 108: if (str == '\0') ! 109: xerror("Control message %s has no title", header.ident); ! 110: cargc = (*str != '\0'); ! 111: cargv = cavpbuf; ! 112: cargv[0] = cavbuf; ! 113: ! 114: while (*str) { ! 115: if (*str <= ' ') { ! 116: *nextfree++ = 0; ! 117: cargv[cargc] = nextfree; ! 118: cargc++; ! 119: /* skip over white space */ ! 120: while (*str != '\0' && *str <= ' ') ! 121: str++; ! 122: if (*str == '\0') /* line ends in white space */ ! 123: return; ! 124: } else ! 125: *nextfree++ = *str++; ! 126: } ! 127: } ! 128: ! 129: /* ! 130: * ihave <artid> <remotesys> ! 131: * The other system is telling you it has article <artid>, in case ! 132: * you decide you want it to transmit it to you. ! 133: */ ! 134: c_ihave(argc, argv) ! 135: char **argv; ! 136: { ! 137: char tl[256], ng[256]; ! 138: #ifndef u370 ! 139: struct hbuf htmp; ! 140: #endif /* !u370 */ ! 141: ! 142: if (argc < 2) ! 143: xerror("ihave: Not enough arguments."); ! 144: /* ! 145: * Check that we haven't already seen it (history) ! 146: * and then send back a "sendme" message if we subscribe. ! 147: */ ! 148: (void) strncpy(htmp.ident, argv[1], BUFLEN); ! 149: if (history(&htmp) == 0) { ! 150: /* Should probably check SUBFILE here. */ ! 151: (void) sprintf(tl, "sendme %s %s", argv[1], FULLSYSNAME); ! 152: (void) sprintf(ng, "to.%s.ctl", argv[2]); ! 153: xmitmsg(argv[2], tl, ng); ! 154: } ! 155: } ! 156: ! 157: /* ! 158: * sendme <artid> ... <remotesys> ! 159: * The other system wants me to send him article <artid>. ! 160: */ ! 161: c_sendme(argc, argv) ! 162: char **argv; ! 163: { ! 164: int i; ! 165: FILE *fp; ! 166: struct srec srec; ! 167: #ifndef u370 ! 168: struct hbuf htmp; ! 169: #endif /* !u370 */ ! 170: ! 171: if (argc < 2) ! 172: xerror("sendme: Not enough arguments."); ! 173: /* Don't ask for it from myself */ ! 174: if (strncmp(FULLSYSNAME, argv[argc], SNLN) == 0) ! 175: return; ! 176: /* Find the sys record */ ! 177: s_openr(); ! 178: while (s_read(&srec)) { ! 179: if (strncmp(srec.s_name, argv[argc], SNLN)) ! 180: continue; ! 181: /* It's the right one. Send them. */ ! 182: for (i=1; i<argc; i++) { ! 183: fp = hfopen(argv[i]); ! 184: htmp.unrec[0] = NULL; ! 185: if (hread(&htmp, fp, TRUE) == NULL) { ! 186: if (bfr[0] == '/') { ! 187: fp = xfopen(bfr, "r"); ! 188: if (hread(&htmp, fp, TRUE) == NULL) ! 189: xerror("Article %s is garbled.", bfr); ! 190: } else ! 191: xerror("Article %s is garbled.", argv[i]); ! 192: } ! 193: (void) fseek(fp, 0L, 0); ! 194: if (strcmp(argv[0], "sendme") == 0) { ! 195: /* check that other sys subscribes. */ ! 196: if (!ngmatch(htmp.nbuf, srec.s_nbuf) || ! 197: !(htmp.distribution[0] == '\0' || ! 198: ngmatch(htmp.distribution, srec.s_nbuf))) ! 199: continue; ! 200: } ! 201: transmit(&srec, fp, 0, (char **)0, 0); ! 202: /* transmit does fclose(fp) */ ! 203: } ! 204: return; ! 205: } ! 206: xerror("Cannot find system %s to send article %s to.", argv[argc], ! 207: argv[1]); ! 208: } ! 209: ! 210: /* ! 211: * newgroup <groupname> ! 212: * A new newsgroup has been created. ! 213: * The body of the article, if present, is a description of the ! 214: * purpose of the newsgroup. ! 215: * ! 216: */ ! 217: c_newgroup(argc, argv) ! 218: char **argv; ! 219: { ! 220: FILE *fd; ! 221: int didcreate = 0; ! 222: ! 223: if (argc < 1) ! 224: xerror("newgroup: Not enough arguments."); ! 225: if (validng(argv[1])) ! 226: return; ! 227: if (header.approved[0] == '\0') ! 228: xerror("newgroup: %s not approved", argv[1]); ! 229: ! 230: #ifndef NONEWGROUPS ! 231: #ifdef ORGDISTRIB ! 232: if (!strcmp(ORGDISTRIB, header.distribution)) { ! 233: didcreate++; ! 234: #endif /* ORGDISTRIB */ ! 235: actfp = xfopen(ACTIVE, "a"); ! 236: fprintf(actfp, "%s 00000 00001 y\n", argv[1]); ! 237: (void) fclose(actfp); ! 238: #ifdef ORGDISTRIB ! 239: } ! 240: #endif /* ORGDISTRIB */ ! 241: #endif /* !NONEWGROUPS */ ! 242: ! 243: #ifdef NOTIFY ! 244: fd = mailhdr((struct hbuf *)NULL, "creation of new newsgroup"); ! 245: if (fd != NULL) { ! 246: if (didcreate) ! 247: fprintf(fd, "A new newsgroup called '%s' has been created by %s.\n", ! 248: argv[1], header.path); ! 249: else ! 250: fprintf(fd, "%s requested that a new newsgroup called '%s' be created.\n", ! 251: header.path, argv[1]); ! 252: fprintf(fd, "It was approved by %s\n\n", header.approved); ! 253: #ifdef ORGDISTRIB ! 254: fprintf(fd, "You can accomplish this by sending a newgroup control message with a\n"); ! 255: fprintf(fd, "distribution code of %s; in other words, by executing the command:\n", ORGDISTRIB); ! 256: fprintf(fd, "%s/inews -n net.news -d %s -t \"cmsg newgroup %s\"\n", ! 257: LIB, ORGDISTRIB, argv[1]); ! 258: #endif /* ORGDISTRIB */ ! 259: (void) mclose(fd); ! 260: } ! 261: } ! 262: #endif /* NOTIFY */ ! 263: ! 264: ! 265: /* ! 266: * rmgroup <groupname> ! 267: * An old newsgroup is being cancelled on a network wide basis. ! 268: */ ! 269: c_rmgroup(argc, argv) ! 270: char **argv; ! 271: { ! 272: FILE *fd; ! 273: int shouldremove = 0; ! 274: ! 275: if (argc < 1) ! 276: xerror("rmgroup: Not enough arguments."); ! 277: if (!validng(argv[1])) ! 278: return; ! 279: if (header.approved[0] == '\0') ! 280: xerror("rmgroup: %s not approved", argv[1]); ! 281: ! 282: #ifndef MANUALLY ! 283: #ifdef ORGDISTRIB ! 284: if (!strcmp(ORGDISTRIB, header.distribution)) ! 285: #endif /* ORGDISTRIB */ ! 286: shouldremove++; ! 287: #endif /* !MANUALLY */ ! 288: #ifdef NOTIFY ! 289: fd = mailhdr((struct hbuf *)NULL, "rmgroup control message"); ! 290: if (fd != NULL) { ! 291: if (shouldremove) { ! 292: fprintf(fd, "A newsgroup called '%s' has been removed by %s.\n\n", ! 293: argv[1], header.path); ! 294: # ifdef USG ! 295: fprintf(fd, "You may need to remove the directory %s by hand\n", ! 296: dirname(argv[1])); ! 297: # endif ! 298: } else { ! 299: fprintf(fd, "%s has requested that newsgroup %s be removed.\n", ! 300: header.path, argv[1]); ! 301: fprintf(fd, "You should remove it by hand\n"); ! 302: fprintf(fd, "To do this, execute the command\n"); ! 303: fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]); ! 304: } ! 305: (void) mclose(fd); ! 306: } ! 307: #endif /* NOTIFY */ ! 308: ! 309: if (shouldremove) { ! 310: int rc; ! 311: /* We let the shell do all the work. ! 312: * See the rmgrp shell script. */ ! 313: (void) setuid(geteuid()); /* otherwise it won't rmdir the dir */ ! 314: (void) sprintf(bfr, "exec %s/rmgroup %s", LIB, argv[1]); ! 315: rc = system(bfr); ! 316: log("system(%s) status %d", bfr, rc); ! 317: } ! 318: } ! 319: ! 320: /* ! 321: * cancel <artid> ! 322: * Cancel the named article ! 323: */ ! 324: c_cancel(argc, argv) ! 325: char **argv; ! 326: { ! 327: char *line, *p, *q, *r, *poster; ! 328: char *findhist(); ! 329: register FILE *fp; ! 330: char whatsisname[BUFLEN], nfilename[BUFLEN]; ! 331: time_t t; ! 332: int su = 0; ! 333: #ifndef u370 ! 334: struct hbuf htmp; ! 335: #endif /* !u370 */ ! 336: ! 337: if (argc < 1) ! 338: xerror("cancel: Not enough arguments."); ! 339: (void) strcpy(whatsisname, senderof(&header)); ! 340: line = findhist(argv[1]); ! 341: if (line == NULL) { ! 342: struct tm *tm; ! 343: log("Can't cancel %s: non-existent", argv[1]); ! 344: (void) time(&t); ! 345: tm = localtime(&t); ! 346: #ifdef USG ! 347: sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled", ! 348: #else /* !USG */ ! 349: sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled", ! 350: #endif /* !USG */ ! 351: argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, ! 352: tm->tm_min); ! 353: savehist(bfr); ! 354: return 1; ! 355: } ! 356: ! 357: q = index(line, '\t'); ! 358: p = index(q+1, '\t'); ! 359: if (p == NULL || *++p == '\0' || *p == '\n') { ! 360: *q = '\0'; ! 361: log("Expired article %s", line); ! 362: return 1; ! 363: } ! 364: if (strcmp(p, "cancelled") == 0) { ! 365: *q = '\0'; ! 366: log("Already Cancelled %s", line); ! 367: return 1; ! 368: } else ! 369: log("Cancelling %s", line); ! 370: if ((uid == ROOTID||uid == 0) && strcmp(header.distribution, "local") == 0) ! 371: su = 1; ! 372: while (*p) { ! 373: q = index(p, ' '); ! 374: if (q) ! 375: *q = '\0'; ! 376: (void) strcpy(nfilename, dirname(p)); ! 377: fp = fopen(nfilename, "r"); ! 378: if (fp == NULL) { ! 379: log("Already Cancelled %s", line); ! 380: return 1; ! 381: } ! 382: htmp.unrec[0] = NULL; ! 383: if (hread(&htmp, fp, TRUE) == NULL) { ! 384: if (bfr[0] == '/') { ! 385: fp = fopen(bfr, "r"); ! 386: if (fp == NULL ! 387: || hread(&htmp, fp, TRUE) == NULL) ! 388: xerror("Article is garbled."); ! 389: } else ! 390: xerror("Article is garbled."); ! 391: } ! 392: (void) fclose(fp); ! 393: poster = senderof(&htmp); ! 394: /* only compare up to '.' or ' ' */ ! 395: r = index(poster,'.'); ! 396: if (r == NULL) ! 397: r = index(poster,' '); ! 398: if (r != NULL) ! 399: *r = '\0'; ! 400: if (!su && strncmp(whatsisname, poster,strlen(poster))) { ! 401: xerror("Not contributor: posted by %s, and you are %s", poster, whatsisname); ! 402: } ! 403: ! 404: (void) unlink(nfilename); ! 405: p = q+1; ! 406: } ! 407: return 0; ! 408: } ! 409: ! 410: /* ! 411: * sendsys (no arguments) ! 412: * ! 413: * Mail the sys file to the person submitting the article. ! 414: * POLICY: the contents of your sys file are public information ! 415: * and as such, you should not change this code. You may feel ! 416: * free to arrange for it to manually notify you, in the event ! 417: * that you want to do something to clean it up before it goes out. ! 418: * Secret sites on the net are expressly frowned on. ! 419: * ! 420: * The purpose of this command is for making a network map. The ! 421: * details of your link and which newsgroups are forwarded are not ! 422: * important, in case you want to sanitize them. Since the definition ! 423: * of USENET is those sites getting net.announce, you can disable this ! 424: * on sites not getting net articles, but if you take out the list of ! 425: * forwarded newsgroups, and you have sites that only get local newsgroups, ! 426: * you should make this clear, or remove those sites from what you send out. ! 427: */ ! 428: /* ARGSUSED */ ! 429: c_sendsys(argc, argv) ! 430: char **argv; ! 431: { ! 432: register FILE *f, *u; ! 433: int c; ! 434: ! 435: #ifdef NOTIFY ! 436: f = mailhdr((struct hbuf *)NULL, "sendsys control message"); ! 437: if (f != NULL) { ! 438: fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB); ! 439: fprintf(f, "It has been sent.\n"); ! 440: (void) mclose(f); ! 441: } ! 442: #endif ! 443: f = mailhdr(&header, "response to your sendsys request"); ! 444: u = fopen(SUBFILE, "r"); ! 445: if (f != NULL && u != NULL) { ! 446: while ((c=getc(u)) != EOF) ! 447: putc(c, f); ! 448: (void) fclose(u); ! 449: (void) mclose(f); ! 450: } ! 451: } ! 452: ! 453: /* ! 454: * senduuname (no arguments) ! 455: * ! 456: * Run the "uuname" command and send it back to the person who submitted ! 457: * the article. The purpose of this control message is for attempting to ! 458: * make a uucp net map. ! 459: * ! 460: * POLICY: If you view this information as not public (because you have ! 461: * a connection you consider secret, or know a site that considers itself ! 462: * secret) you can feel free to change this code in whatever way is ! 463: * appropriate, so long as it sends some response back to the sender. If ! 464: * you don't run uucp, this code does not make sense, and so an error ! 465: * message (or garbage, such as "research") will be mailed back. ! 466: * ! 467: * If you wish to add or remove sites from the output of uuname, you ! 468: * may wish to use the euuname.sh shell script here. ! 469: */ ! 470: /* ARGSUSED */ ! 471: c_senduuname(argc, argv) ! 472: char **argv; ! 473: { ! 474: char buf[256]; ! 475: FILE *fd, *u; ! 476: int c; ! 477: ! 478: #ifdef NOTIFY ! 479: fd = mailhdr((struct hbuf *)NULL, "uuname control message"); ! 480: fprintf(fd, "%s requested your uuname output\n", header.path); ! 481: (void) mclose(fd); ! 482: #endif ! 483: fd = mailhdr(&header, "response to your senduuname request"); ! 484: #ifdef UUPROG ! 485: if (UUPROG[0] == '/') ! 486: (void) strcpy(buf, UUPROG); ! 487: else ! 488: (void) sprintf(buf, "%s/%s", LIB, UUPROG); ! 489: #else ! 490: (void) strcpy(buf, "uuname"); ! 491: #endif ! 492: u = popen(buf, "r"); ! 493: if (fd != NULL && u != NULL) { ! 494: while ((c=getc(u)) != EOF) ! 495: putc(c, fd); ! 496: (void) pclose(u); ! 497: (void) mclose(fd); ! 498: } ! 499: } ! 500: ! 501: /* ! 502: * Send the version number to the right person. ! 503: */ ! 504: /* ARGSUSED */ ! 505: c_version(argc, argv) ! 506: char **argv; ! 507: { ! 508: register FILE *f; ! 509: ! 510: f = mailhdr(&header, "Our news version"); ! 511: if (f == NULL) ! 512: xerror("Cannot send back error message"); ! 513: fprintf(f, "Currently running news version %s.\n\n", news_version); ! 514: fprintf(f, "The header of your message follows:\n\n"); ! 515: (void) hwrite(&header, f); ! 516: (void) mclose(f); ! 517: } ! 518: ! 519: /* ! 520: * Check the active file for old or missing newsgroups ! 521: * Body of article is list of valid groups ! 522: */ ! 523: /* ARGSUSED */ ! 524: c_checkgroups(argc, argv) ! 525: char **argv; ! 526: { ! 527: int rc; ! 528: ! 529: (void) setuid(geteuid()); ! 530: /* dont change the cat %s| to < %s, it breaks some "unix" systems */ ! 531: (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB, ! 532: #ifdef NOTIFY ! 533: (TELLME && *TELLME) ? TELLME : NEWSUSR ); ! 534: #else /* !NOTIFY */ ! 535: NEWSUSR); ! 536: #endif /* !NOTIFY */ ! 537: rc = system(bfr); ! 538: log("system(%s) status %d", bfr, rc); ! 539: } ! 540: ! 541: /* ! 542: * An unknown control message has been received. ! 543: */ ! 544: c_unknown(h, ctlmsgtext) ! 545: struct hbuf *h; ! 546: char *ctlmsgtext; ! 547: { ! 548: register FILE *f; ! 549: ! 550: log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path); ! 551: #ifdef NOTIFY ! 552: f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message"); ! 553: if (f != NULL) { ! 554: fprintf(f, "Currently running news version %s.\n\n", news_version); ! 555: fprintf(f, "The header of the message follows:\n\n"); ! 556: (void) hwrite(h, f); ! 557: (void) mclose(f); ! 558: } ! 559: #endif /* NOTIFY */ ! 560: } ! 561: ! 562: /* ARGSUSED */ ! 563: c_unimp(argc, argv) ! 564: char **argv; ! 565: { ! 566: register FILE *f; ! 567: ! 568: #ifdef NOTIFY ! 569: f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message"); ! 570: if (f != NULL) { ! 571: fprintf(f, "Currently running news version B %s.\n\n", news_version); ! 572: fprintf(f, "The header of the message follows:\n\n"); ! 573: (void) hwrite(&header, f); ! 574: (void) mclose(f); ! 575: } ! 576: #endif /* NOTIFY */ ! 577: } ! 578: ! 579: xmitmsg(tosys, title, ng) ! 580: char *tosys, *title, *ng; ! 581: { ! 582: #ifndef u370 ! 583: struct hbuf htmp; ! 584: #endif /* !u370 */ ! 585: struct srec srec; ! 586: FILE *tfp; ! 587: char *fname; ! 588: ! 589: /* Make an article called ARTICLE */ ! 590: (void) sprintf(htmp.from, "%s@%s%s", "usenet", FULLSYSNAME, MYDOMAIN); ! 591: (void) strcpy(htmp.path, NEWSUSR); ! 592: (void) strcpy(htmp.nbuf, ng); ! 593: (void) strcpy(htmp.title, title); ! 594: (void) strcpy(htmp.ctlmsg, title); ! 595: (void) strcpy(htmp.subdate, ""); ! 596: (void) strcpy(htmp.expdate, ""); ! 597: getident(&htmp); ! 598: dates(&htmp); ! 599: tfp = xfopen(fname = mktemp("/tmp/xmsgXXXXXX"), "w"); ! 600: hwrite(&htmp, tfp); ! 601: (void) fclose(tfp); ! 602: ! 603: /* Find the sys record */ ! 604: s_openr(); ! 605: while (s_read(&srec)) { ! 606: if (strncmp(srec.s_name, tosys, SNLN)) ! 607: continue; ! 608: tfp = xfopen(fname, "r"); ! 609: (void) transmit(&srec, tfp, 0, (char **)0, 0); ! 610: (void) unlink(fname); ! 611: return; ! 612: } ! 613: log("Can't find sys record for %s", tosys); ! 614: xerror("Cannot find sys record"); ! 615: } ! 616: ! 617: /* ! 618: * This is a modified version of popen, made more secure. Rather than ! 619: * forking off a shell, you get a bare process. You must have exactly ! 620: * one argument, and the command must be mail (or sendmail if you have it). ! 621: */ ! 622: #define RDR 0 ! 623: #define WTR 1 ! 624: static int mopen_pid[20]; ! 625: char *replyname(); ! 626: ! 627: FILE * ! 628: mhopen(hptr) ! 629: struct hbuf *hptr; ! 630: { ! 631: int p[2]; ! 632: register myside, hisside, pid; ! 633: char *sendto = "usenet"; ! 634: ! 635: if (hptr) ! 636: sendto = replyname(hptr); ! 637: else { ! 638: #ifdef NOTIFY ! 639: if (TELLME && *TELLME) ! 640: sendto = TELLME; ! 641: #endif /* NOTIFY */ ! 642: if (sendto == NULL) ! 643: return NULL; ! 644: } ! 645: verifyname(sendto); ! 646: if(pipe(p) < 0) ! 647: return NULL; ! 648: myside = p[WTR]; ! 649: hisside = p[RDR]; ! 650: if((pid = fork()) == 0) { ! 651: /* myside and hisside reverse roles in child */ ! 652: (void) close(myside); ! 653: (void) close(0); ! 654: (void) dup(hisside); ! 655: (void) close(hisside); ! 656: (void) setgid(gid); ! 657: (void) setuid(uid); ! 658: #ifdef SENDMAIL ! 659: execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL); ! 660: #endif /* SENDMAIL */ ! 661: #ifdef MMDF ! 662: execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL); ! 663: #endif /* MMDF */ ! 664: execl("/bin/mail", "mail", sendto, (char *)NULL); ! 665: execl("/usr/bin/mail", "mail", sendto, (char *)NULL); ! 666: execl("/usr/ucb/mail", "mail", sendto, (char *)NULL); ! 667: _exit(1); ! 668: } ! 669: if(pid == -1) ! 670: return NULL; ! 671: mopen_pid[myside] = pid; ! 672: (void) close(hisside); ! 673: return(fdopen(myside, "w")); ! 674: } ! 675: ! 676: mclose(ptr) ! 677: FILE *ptr; ! 678: { ! 679: register f, r, (*hstat)(), (*istat)(), (*qstat)(); ! 680: int status; ! 681: ! 682: f = fileno(ptr); ! 683: (void) fclose(ptr); ! 684: istat = signal(SIGINT, SIG_IGN); ! 685: qstat = signal(SIGQUIT, SIG_IGN); ! 686: hstat = signal(SIGHUP, SIG_IGN); ! 687: while((r = wait(&status)) != mopen_pid[f] && r != -1) ! 688: ; ! 689: if(r == -1) ! 690: status = -1; ! 691: signal(SIGINT, istat); ! 692: signal(SIGQUIT, qstat); ! 693: signal(SIGHUP, hstat); ! 694: return status; ! 695: } ! 696: ! 697: /* ! 698: * mhopen a pipe to mail, write out a std header, and return the file ptr. ! 699: * ! 700: * We don't include a From: field because this is probably uucp, i.e. ! 701: * explicitly routed. Leave it up to the recipient's mailer. ! 702: * Always include the To: field because if we ge back failed mail, we ! 703: * might be able to deliver it by hand if we know to wom it was addressed. ! 704: * By convention, hptr==NULL means to send the message to the local contact person. ! 705: */ ! 706: FILE * ! 707: mailhdr(hptr, subject) ! 708: struct hbuf *hptr; ! 709: char *subject; ! 710: { ! 711: FILE *fp; ! 712: time_t now; ! 713: char *to = "usenet"; ! 714: ! 715: #ifdef NOTIFY ! 716: if (TELLME && *TELLME) ! 717: to = TELLME; ! 718: #endif /* NOTIFY */ ! 719: if (hptr) ! 720: to = replyname(hptr); ! 721: ! 722: if ((fp = mhopen(hptr)) != NULL) { ! 723: (void) time(&now); ! 724: fprintf(fp, "Date: %s\n", arpadate(&now)); ! 725: #ifdef MMDF ! 726: fprintf(fp, "From: The News System <usenet@%s%s>\n", ! 727: FULLSYSNAME, MYDOMAIN); ! 728: #endif /* MMDF */ ! 729: fprintf(fp, "To: %s\n", to); ! 730: fprintf(fp, "Subject: %s\n", subject); ! 731: #ifdef HIDDENNET ! 732: if (strcmp(LOCALSYSNAME, FULLSYSNAME)) ! 733: fprintf(fp, "Responding-System: %s.%s%s\n\n", ! 734: LOCALSYSNAME, FULLSYSNAME, MYDOMAIN); ! 735: #endif /* !HIDDENNET */ ! 736: fprintf(fp, "Responding-System: %s%s\n\n", ! 737: FULLSYSNAME, MYDOMAIN); ! 738: } ! 739: return fp; ! 740: } ! 741: ! 742: /* ! 743: * verify that the name mail is being sent to does not contain any ! 744: * nasty hooks to invoke funny functions from the shell or the like. ! 745: */ ! 746: verifyname(sendto) ! 747: char *sendto; ! 748: { ! 749: /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */ ! 750: char *nasty = "\"'\\`^|;& <>/~"; ! 751: register char *p; ! 752: ! 753: if (sendto[0] <= ' ') { ! 754: log("nasty mail name %s from %s", sendto, header.path); ! 755: xxit(1); ! 756: } ! 757: for (p=sendto; *p; p++) { ! 758: if (*p == ' ') { ! 759: *p = 0; ! 760: break; ! 761: } ! 762: } ! 763: if (strpbrk(sendto, nasty) != NULL) ! 764: xerror("nasty mail name %s from %s", sendto, header.path); ! 765: ! 766: for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) { ! 767: if (*++nasty == '.') /* check for .. */ ! 768: xerror("nasty mail name %s from %s", sendto, header.path); ! 769: } ! 770: } ! 771: ! 772: /* ! 773: * Checks to make sure the control message is OK to post. ! 774: */ ! 775: ctlcheck() ! 776: { ! 777: char msg[BUFLEN]; ! 778: char *p; ! 779: ! 780: if (!is_ctl) ! 781: return; ! 782: ! 783: if (header.ctlmsg[0]) ! 784: (void) strcpy(msg, header.ctlmsg); ! 785: else ! 786: (void) strcpy(msg, header.title); ! 787: ! 788: p = index(msg, ' '); ! 789: if (p) ! 790: *p = 0; ! 791: ! 792: if (strcmp(msg, "ihave") == 0) { ! 793: } else if (strcmp(msg, "sendme") == 0) { ! 794: return; /* no restrictions */ ! 795: } else if (strcmp(msg, "newgroup") == 0) { ! 796: suser(); ! 797: } else if (strcmp(msg, "rmgroup") == 0) { ! 798: suser(); ! 799: } else if (strcmp(msg, "sendsys") == 0) { ! 800: suser(); ! 801: } else if (strcmp(msg, "senduuname") == 0) { ! 802: suser(); ! 803: } else if (strcmp(msg, "checkgroups") == 0) { ! 804: suser(); ! 805: } else if (strcmp(msg, "version") == 0) { ! 806: return; /* no restrictions */ ! 807: } else if (strcmp(msg, "cancel") == 0) { ! 808: return; /* no restrictions at this level */ ! 809: } else if (strcmp(msg, "delsub") == 0) { ! 810: if (!prefix(header.nbuf, "to.")) { ! 811: printf("Must be in a 'to.system' newsgroup."); ! 812: xxit(0); ! 813: } ! 814: return; ! 815: } else { ! 816: printf("Unrecognized control message - %s\n", msg); ! 817: xxit(0); ! 818: } ! 819: } ! 820: ! 821: /* Make sure this guy is special. */ ! 822: suser() ! 823: { ! 824: if (uid == 0 || uid == ROOTID) ! 825: return; ! 826: /* ! 827: * We assume that since our real uid is the same as NEWSUSR ! 828: * (the euid) we were run by rootid and it did a setuid. ! 829: * Too bad we can't set just the effective uid like suid does. ! 830: */ ! 831: if (uid == geteuid()) ! 832: return; ! 833: #ifdef IHCC ! 834: printf("Please use the command:\n\ttoolnews providers\n"); ! 835: printf("then call one of the news people.\n"); ! 836: #else ! 837: printf("Get your local netnews contact to do it for you.\n"); ! 838: #endif ! 839: xxit(0); ! 840: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.