|
|
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.55 10/7/87"; ! 23: #endif /* SCCSID */ ! 24: ! 25: #include "iparams.h" ! 26: ! 27: #define eq(msg) (msg[0] == cargv[0][0] && strcmp(msg, cargv[0]) == 0) ! 28: ! 29: int cargc; ! 30: char **cargv; ! 31: ! 32: FILE *hfopen(); ! 33: FILE *popen(), *mhopen(), *mailhdr(); ! 34: ! 35: #define NCARGS 30 ! 36: char *senderof(); ! 37: #ifdef u370 ! 38: static struct hbuf htmp; ! 39: #endif /* u370 */ ! 40: ! 41: /* ! 42: * The global structure is initialized to NOTIFY as the default (if defined) ! 43: * uid to send mail to for every state. The following conditions are ! 44: * dealt with (assumes NOTIFY defined): ! 45: * ! 46: * 1) LIB/notify exists and is empty (or contains no recognizable control ! 47: * message types). ! 48: * Action: force TELLME = ""; ! 49: * 2) LIB/notify contains the control message name "all" and no associated ! 50: * address. ! 51: * Action: force TELLME = ""; ! 52: * 3) LIB/notify contains the control message name "all" and has an address. ! 53: * Action: set TELLME = AlloCpy(address); ! 54: * 4) LIB/notify contains only some of the known control message types. ! 55: * Action: initialize all addresses to "" and set declared addresses ! 56: * to listed address. ! 57: */ ! 58: ! 59: ! 60: control(h) ! 61: struct hbuf *h; ! 62: { ! 63: register char *ctlmsgtext; ! 64: register struct msgtype *mp; ! 65: ! 66: if (strncmp(h->title, "cmsg ", 5) == 0) { ! 67: register char *cp1, *cp2; ! 68: cp1 = h->title; ! 69: cp2 = h->title + 5; ! 70: while (*cp1++ = *cp2++) ! 71: ; ! 72: } ! 73: ! 74: if (*h->ctlmsg) ! 75: ctlmsgtext = h->ctlmsg; ! 76: else ! 77: ctlmsgtext = h->title; ! 78: log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext); ! 79: /* ! 80: * Control messages have the standard format ! 81: * command [args] ! 82: * much like shell commands. Each site has the option ! 83: * of customizing this code to deal with control messages ! 84: * as they see fit, but we would like to buy back the ! 85: * code, ifdeffed or otherwise parameterized, to simplify ! 86: * the maintenence issues. ! 87: */ ! 88: argparse(ctlmsgtext); ! 89: ! 90: /* ! 91: * We look for a match of the control message name and then ! 92: * set TELLME to the value parsed from the LIB/notify file ! 93: * (if any). ! 94: */ ! 95: for(mp=msgtype; mp->m_name; mp++) { ! 96: if(eq(mp->m_name) ) { /* hit */ ! 97: #ifdef NOTIFY ! 98: TELLME = mp->m_who_to; /* reset whom to tell */ ! 99: #endif /* NOTIFY */ ! 100: return (*mp->m_func)(cargc, cargv); /* do it */ ! 101: } ! 102: } ! 103: if( !mp->m_name ) { ! 104: #ifdef NOTIFY ! 105: TELLME = NOTIFY; ! 106: #endif /* NOTIFY */ ! 107: c_unknown(h, ctlmsgtext); ! 108: } ! 109: return 0; ! 110: } ! 111: ! 112: /* ! 113: * Parse the string str into separate words in cargc and cargv ! 114: * as per the usual UNIX convention. Nothing fancy here, just ! 115: * blanks and tabs separating words. ! 116: */ ! 117: argparse(str) ! 118: char *str; ! 119: { ! 120: static char *cavpbuf[NCARGS]; ! 121: static char cavbuf[256]; ! 122: char *nextfree = cavbuf; ! 123: ! 124: if (str == '\0') ! 125: error("Control message %s has no title", header.ident); ! 126: cargc = (*str != '\0'); ! 127: cargv = cavpbuf; ! 128: cargv[0] = cavbuf; ! 129: ! 130: while (*str) { ! 131: if (*str <= ' ') { ! 132: /* skip over white space */ ! 133: while (*str != '\0' && *str <= ' ') ! 134: str++; ! 135: if (*str == '\0') /* line ends in white space */ ! 136: return; ! 137: *nextfree++ = 0; ! 138: cargv[cargc] = nextfree; ! 139: if (cargc++ >= NCARGS) ! 140: xerror("Too many arguments to control message %s", ! 141: header.ident); ! 142: } else ! 143: *nextfree++ = *str++; ! 144: } ! 145: } ! 146: ! 147: /* ! 148: * ihave <artid> ... <remotesys> ! 149: * or ! 150: * ihave <remotesys> ! 151: * with <artid>s in message body. ! 152: * ! 153: * The other system is telling you it has article <artid>, in case ! 154: * you decide you want it to transmit it to you. ! 155: * The assumption is that the other system only tells you about articles ! 156: * in newsgroups you subscribe to. ! 157: * ! 158: * We turn the incoming ihave into an outgoing sendme on the fly. ! 159: * It then gets saved in the SPOOL directory and transmitted to the ! 160: * remote system. (This way the sendme messages can be batched.) ! 161: */ ! 162: c_ihave(argc, argv) ! 163: register char ** argv; ! 164: { ! 165: register int i; ! 166: char list[sizeof header.title]; ! 167: extern char * findhist(); ! 168: extern char * mydomain(); ! 169: ! 170: if (argc < 2) ! 171: error("ihave: Too few arguments."); ! 172: if (strncmp(PATHSYSNAME, argv[argc - 1], SNLN) == 0) ! 173: return 0; ! 174: list[0] = '\0'; ! 175: if (argc > 2) { ! 176: for (i = 1; i < (argc - 1); ++i) ! 177: if (findhist(argv[i]) == NULL) { ! 178: (void) strcat(list, " "); ! 179: (void) strcat(list, argv[i]); ! 180: } ! 181: if (list[0] == '\0') ! 182: return 0; ! 183: } else { ! 184: register FILE * outfp; ! 185: register long outpos, inpos; ! 186: char myid[256]; ! 187: ! 188: outfp = xfopen(INFILE, "a"); ! 189: outpos = ftell(outfp); ! 190: inpos = ftell(infp); ! 191: while (ftell(infp) < outpos) { ! 192: if (fgets(myid, sizeof myid, infp) != myid) ! 193: error("iline: Can't reread article"); ! 194: myid[strlen(myid) - 1] = '\0'; ! 195: if (findhist(myid) == NULL) ! 196: (void) fprintf(outfp, "%s\n", myid); ! 197: } ! 198: if (outpos == ftell(outfp)) { /* if nothing is wanted */ ! 199: (void) fclose(outfp); ! 200: (void) fseek(infp, inpos, 0); ! 201: return 0; ! 202: } ! 203: (void) fclose(outfp); ! 204: /* ! 205: ** The close and open may just be paranoia. ! 206: */ ! 207: (void) fclose(infp); ! 208: infp = xfopen(INFILE, "r"); ! 209: (void) fseek(infp, outpos, 0); ! 210: } ! 211: /* ! 212: ** Turn the ihave into a sendme. ! 213: */ ! 214: (void) sprintf(header.nbuf, "to.%s.ctl", argv[argc - 1]); ! 215: (void) sprintf(header.title, "sendme%s %s", list, PATHSYSNAME); ! 216: (void) strcpy(header.ctlmsg, header.title); ! 217: getident(&header); ! 218: (void) sprintf(header.from, "%s@%s", "usenet", FROMSYSNAME); ! 219: (void) strcpy(header.path, NEWSUSR); ! 220: header.subdate[0] = header.expdate[0] = '\0'; ! 221: dates(&header); ! 222: /* ! 223: ** What else of this kind should be done? ! 224: */ ! 225: header.organization[0] = header.distribution[0] = '\0'; ! 226: header.numlines[0] = '\0'; ! 227: for (i = 0; i < NUNREC && header.unrec[i] != NULL; ++i) { ! 228: free(header.unrec[i]); ! 229: header.unrec[i] = NULL; ! 230: } ! 231: /* ! 232: ** Note that we do *not* change the history line ! 233: ** so that if the "ihave" message comes in again it gets rejected. ! 234: */ ! 235: return 0; ! 236: } ! 237: ! 238: /* ! 239: * sendme <artid> ... <remotesys> ! 240: * or ! 241: * sendme <remotesys> ! 242: * with <artid>s in message body. ! 243: * The other system wants me to send out article <artid>. ! 244: * Give it to them with no fuss. ! 245: */ ! 246: #ifdef MULTICAST ! 247: static int c_mc; ! 248: static char ** c_sysnames; ! 249: #endif /* MULTICAST */ ! 250: c_sendme(argc, argv) ! 251: register char **argv; ! 252: { ! 253: struct srec srec; ! 254: ! 255: if (argc < 2) ! 256: error("sendme: Too few arguments."); ! 257: if (strncmp(PATHSYSNAME, argv[argc - 1], SNLN) == 0) ! 258: return 0; ! 259: if (s_find(&srec, argv[argc - 1]) != TRUE) ! 260: error("sendme: Can't find sys record for %s", argv[argc - 1]); ! 261: #ifdef MULTICAST ! 262: c_mc = index(srec.s_flags, 'M') != 0; ! 263: if (c_mc) { ! 264: struct srec trec; ! 265: ! 266: c_sysnames = &argv[argc - 1]; ! 267: if (s_find(&trec, srec.s_xmit) != TRUE) ! 268: error("sendme: Can't find sys record for %s for %s", ! 269: srec.s_xmit, argv[argc - 1]); ! 270: srec = trec; ! 271: } else c_sysnames = NULL; ! 272: #endif /* MULTICAST */ ! 273: /* Send the articles. */ ! 274: if (argc == 2) { ! 275: register FILE * fp; ! 276: char buf[256]; ! 277: ! 278: fp = xfopen(INFILE, "r"); ! 279: while (fgets(buf, sizeof buf, fp) == buf) { ! 280: buf[strlen(buf) - 1] = '\0'; /* zap trailing '\n' */ ! 281: sendmefunc(buf, &srec); ! 282: } ! 283: (void) fclose(fp); ! 284: } else { /* argc > 2 */ ! 285: register int i; ! 286: ! 287: for (i = 1; i < (argc - 1); ++i) ! 288: sendmefunc(argv[i], &srec); ! 289: } ! 290: return 0; ! 291: } ! 292: ! 293: static ! 294: sendmefunc(id, sp) ! 295: register char * id; ! 296: register struct srec * sp; ! 297: { ! 298: register FILE * fp; ! 299: register char * cp; ! 300: char savedbufname[256]; ! 301: extern char firstbufname[]; ! 302: extern char * dirname(); ! 303: extern char * findfname(); ! 304: ! 305: cp = findfname(id); ! 306: if (cp == NULL) { ! 307: log("System %s wants unavailable article %s.", ! 308: #ifdef MULTICAST ! 309: (c_mc ? c_sysnames[0] : sp->s_name), id); ! 310: #else /* !MULTICAST */ ! 311: sp->s_name, id); ! 312: #endif /* !MULTICAST */ ! 313: return; ! 314: } ! 315: cp = dirname(cp); ! 316: fp = fopen(cp, "r"); ! 317: if (fp == NULL) { ! 318: logerr("Article %s unopenable as %s.", id, cp); ! 319: return; ! 320: } ! 321: (void) strcpy(savedbufname, firstbufname); ! 322: (void) strcpy(firstbufname, cp); ! 323: #ifdef MULTICAST ! 324: transmit(sp, fp, FALSE, c_sysnames, c_mc); ! 325: #else /* !MULTICAST */ ! 326: transmit(sp, fp, FALSE, (char **) NULL, 0); ! 327: #endif /* !MULTICAST */ ! 328: /* transmit closes fp */ ! 329: (void) strcpy(firstbufname, savedbufname); ! 330: } ! 331: ! 332: /* ! 333: * newgroup <groupname> ! 334: * A new newsgroup has been created. ! 335: * The body of the article, if present, is a description of the ! 336: * purpose of the newsgroup. ! 337: * ! 338: */ ! 339: c_newgroup(argc, argv) ! 340: char **argv; ! 341: { ! 342: FILE *fd; ! 343: char abuf[BUFLEN], subjline[BUFLEN]; ! 344: int didcreate = 0; ! 345: register char *p, *q; ! 346: # ifdef NONEWGROUPS ! 347: # ifdef ORGDISTRIB ! 348: /* local or ORGDISTRIB */ ! 349: int can_change = (strcmp(header.distribution, "local") == 0) || ! 350: (strcmp(header.distribution, ORGDISTRIB) == 0); ! 351: # else /* ! ORGDISTRIB */ ! 352: /* local only */ ! 353: int can_change = strcmp(header.distribution, "local") == 0; ! 354: # endif /* ORGDISTRIB */ ! 355: # else /* ! NONEWGROUPS */ ! 356: int can_change = 1; /* allow changes for all distributions */ ! 357: # endif /* NONEWGROUPS */ ! 358: ! 359: if (argc < 2) ! 360: error("newgroup: Too few arguments."); ! 361: ! 362: if (header.approved[0] == '\0') { ! 363: logerr("newgroup: %s not approved", argv[1]); ! 364: return 1; ! 365: } ! 366: ! 367: lock(); ! 368: /* see if it already exists */ ! 369: (void) rewind(actfp); clearerr(actfp); ! 370: while(fgets(abuf, BUFLEN, actfp) != NULL) { ! 371: p = abuf; ! 372: q = argv[1]; ! 373: while (*p++ == *q++) ! 374: ; ! 375: if (*--q == '\0' && *--p == ' ') { ! 376: /* Now check if it's correctly moderated/unmoderated */ ! 377: while (*p++) ! 378: ; ! 379: p -= 3; ! 380: if (argc > 2 && strcmp(argv[2], "moderated") == 0) { ! 381: if (*p == 'm') { ! 382: unlock(); ! 383: return 0; ! 384: } ! 385: *p = 'm'; ! 386: } else { ! 387: if (*p != 'm') { ! 388: unlock(); ! 389: return 0; ! 390: } ! 391: *p = 'y'; ! 392: } ! 393: # ifdef NOTIFY ! 394: (void) sprintf(subjline, ! 395: "Newsgroup %s changed from %smoderated to %smoderated", ! 396: argv[1], *p=='y' ? "" : "un", ! 397: *p=='y' ? "un" : ""); ! 398: fd = mailhdr((struct hbuf *)NULL, subjline); ! 399: if (fd != NULL) { ! 400: if(can_change) ! 401: fprintf(fd, ! 402: "%s has been changed from %smoderated to %smoderated as requested by\n%s\n", ! 403: argv[1], *p=='y' ? "" : "un", ! 404: *p=='y' ? "un":"", header.path); ! 405: else { ! 406: fprintf(fd, ! 407: "%s\nhas requested that %s be changed from %smoderated to %smoderated\n", ! 408: header.path, argv[1], ! 409: *p=='y' ? "" : "un", ! 410: *p=='y' ? "un" : ""); ! 411: #ifdef ORGDISTRIB ! 412: fprintf(fd, ! 413: "You can accomplish this by re-creating the newsgroup with a distribution\n"); ! 414: fprintf(fd, ! 415: "of '%s' by executing the command:\n", ORGDISTRIB); ! 416: fprintf(fd, ! 417: "%s/inews -d %s -C %s%s\n", ! 418: LIB, ORGDISTRIB, argv[1], ! 419: *p=='y' ? "" : " moderated"); ! 420: #else /* !ORGDISTRIB */ ! 421: fprintf(fd, ! 422: "You can accomplish this by re-creating the newsgroup by executing the command:\n"); ! 423: fprintf(fd, "%s/inews -C %s%s\n", ! 424: LIB, argv[1], ! 425: *p=='y' ? "" : " moderated"); ! 426: #endif /* !ORGDISTRIB */ ! 427: } ! 428: (void) mclose(fd); ! 429: } ! 430: # endif /* NOTIFY */ ! 431: # ifdef NONEWGROUPS ! 432: /* ! 433: * No permission to change ! 434: */ ! 435: if(!can_change) { ! 436: unlock(); ! 437: return 0; ! 438: } ! 439: # endif /* NONEWGROUPS */ ! 440: /* The active file was wrong about the state of the ! 441: * group. Rewrite the active file ! 442: */ ! 443: (void) fseek(actfp, -2L, 1); /* back up 2 characters */ ! 444: putc(*p, actfp); ! 445: fflush(actfp); ! 446: if (*p != 'm') ! 447: logerr("Newsgroup %s changed from moderated to unmoderated", ! 448: argv[1]); ! 449: else ! 450: logerr("Newsgroup %s changed from unmoderated to moderated", ! 451: argv[1]); ! 452: unlock(); ! 453: return 0; ! 454: } ! 455: } ! 456: ! 457: /* It doesn't already exist, we must create it */ ! 458: ! 459: if(can_change) { ! 460: didcreate++; ! 461: (void) fseek(actfp, 0L, 2); clearerr(actfp); ! 462: fprintf(actfp, "%s 00000 00001 %c\n", argv[1], ! 463: (argc > 2 && strcmp(argv[2], "moderated") == 0) ! 464: ? 'm' : 'y'); ! 465: #if defined(USG) || defined(MG1) ! 466: /* ! 467: * U G L Y K L U D G E ! 468: * This utter piece of tripe is the only way I know of ! 469: * to get around the fact that ATT BROKE standard IO ! 470: * in System 5.2. Basically, you can't open a file for ! 471: * "r+" and then try and write to it. This hack works ! 472: * on all "real" USG Unix systems, It will probably ! 473: * break on some obscure look alike that doesnt use the ! 474: * real ATT stdio.h ! 475: * also broken in WCW MG-1 42nix 2.0 ! 476: * Don't blame me, blame ATT. stdio should have ! 477: * already done the following line for us, but it didn't ! 478: */ ! 479: actfp->_flag |= _IOWRT; ! 480: #endif /* USG */ ! 481: fflush(actfp); ! 482: } ! 483: ! 484: # ifdef NOTIFY ! 485: (void) sprintf(subjline, "Newsgroup %s created", argv[1]); ! 486: fd = mailhdr((struct hbuf *)NULL, subjline); ! 487: if (fd != NULL) { ! 488: if (didcreate) ! 489: fprintf(fd, ! 490: "A new %snewsgroup called '%s' has been created by %s.\n", ! 491: argc > 2 ? "moderated " : "", argv[1], ! 492: header.path); ! 493: else { ! 494: fprintf(fd, ! 495: "%s requested that a new %snewsgroup called '%s' be created.\n", ! 496: header.path, argc > 2 ? "moderated " : "", argv[1]); ! 497: fprintf(fd,"It was approved by %s\n\n",header.approved); ! 498: fprintf(fd, ! 499: "You can accomplish this by creating the newgroup yourself\n"); ! 500: # ifdef ORGDISTRIB ! 501: fprintf(fd,"with a distribution of '%s'.\n", ! 502: ORGDISTRIB); ! 503: fprintf(fd, ! 504: "In other words, by executing the command:\n"); ! 505: fprintf(fd, "%s/inews -d %s -C %s %s\n", LIB, ! 506: ORGDISTRIB, argv[1], argc > 2 ? argv[2] : ""); ! 507: # else /* !ORGDISTRIB */ ! 508: fprintf(fd, "In other words, by executing the command:\n"); ! 509: fprintf(fd, "%s/inews -C %s %s\n", LIB, argv[1], ! 510: argc > 2 ? argv[2] : ""); ! 511: # endif /* !ORGDISTRIB */ ! 512: } ! 513: (void) mclose(fd); ! 514: } ! 515: # endif /* NOTIFY */ ! 516: unlock(); ! 517: return 0; ! 518: } ! 519: ! 520: /* ! 521: * rmgroup <groupname> ! 522: * An old newsgroup is being cancelled on a network wide basis. ! 523: */ ! 524: c_rmgroup(argc, argv) ! 525: char **argv; ! 526: { ! 527: FILE *fd; ! 528: int shouldremove = 0; ! 529: #ifdef NOTIFY ! 530: char subjline[BUFLEN]; ! 531: #endif /* NOTIFY */ ! 532: ! 533: if (argc < 2) ! 534: error("rmgroup: Too few arguments."); ! 535: if (!validng(argv[1])) ! 536: return 0; ! 537: if (header.approved[0] == '\0') { ! 538: logerr("rmgroup: %s not approved", argv[1]); ! 539: return 1; ! 540: } ! 541: ! 542: #ifdef MANUALLY ! 543: #ifdef ORGDISTRIB ! 544: /* ! 545: * Allow local as well as organizational removals ! 546: */ ! 547: if (!strcmp(ORGDISTRIB, header.distribution) ! 548: || !strcmp("local", header.distribution)) ! 549: #else /* !ORGDISTRIB */ ! 550: if (!strcmp("local", header.distribution)) ! 551: #endif /* !ORGDISTRIB */ ! 552: #endif /* MANUALLY */ ! 553: shouldremove++; ! 554: #ifdef NOTIFY ! 555: sprintf(subjline, "Received rmgroup for %s", argv[1]); ! 556: fd = mailhdr((struct hbuf *)NULL, subjline); ! 557: if (fd != NULL) { ! 558: if (shouldremove) { ! 559: fprintf(fd, "Newsgroup '%s' has been removed by %s.\n\n", ! 560: argv[1], header.path); ! 561: # ifdef USG ! 562: fprintf(fd, "You may need to remove the directory %s by hand\n", ! 563: dirname(argv[1])); ! 564: # endif ! 565: } else { ! 566: fprintf(fd, "%s requested that newsgroup %s be removed.\n", ! 567: header.path, argv[1]); ! 568: fprintf(fd, "You should remove it by hand\n"); ! 569: fprintf(fd, "To do this, execute the command\n"); ! 570: fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]); ! 571: } ! 572: (void) mclose(fd); ! 573: } ! 574: #endif /* NOTIFY */ ! 575: ! 576: if (shouldremove) { ! 577: int pid, status; ! 578: /* We let the shell do all the work. ! 579: * See the rmgrp shell script. ! 580: */ ! 581: lock(); ! 582: (void) sprintf(bfr, "%s/rmgroup", LIB); ! 583: ! 584: if (pid = fork()) { ! 585: status = fwait(pid); ! 586: } else { ! 587: register int i; ! 588: for (i =3; i<20; i++) ! 589: if (close(i) < 0) ! 590: break; ! 591: (void) setuid(duid); ! 592: execvp(bfr, argv); ! 593: } ! 594: unlock(); ! 595: if (status) ! 596: log("rmgroup status %d", status); ! 597: } ! 598: return 0; ! 599: } ! 600: ! 601: /* ! 602: * cancel <artid> ! 603: * Cancel the named article ! 604: */ ! 605: c_cancel(argc, argv) ! 606: char **argv; ! 607: { ! 608: char *line, *p, *q, *r, *poster; ! 609: char *findhist(); ! 610: register FILE *fp; ! 611: char whatsisname[BUFLEN], nfilename[BUFLEN]; ! 612: time_t t; ! 613: int su = 0; ! 614: #ifndef u370 ! 615: struct hbuf htmp; ! 616: #endif /* !u370 */ ! 617: ! 618: if (argc < 2) ! 619: error("cancel: Too few arguments."); ! 620: (void) strcpy(whatsisname, senderof(&header)); ! 621: line = findhist(argv[1]); ! 622: if (line == NULL) { ! 623: struct tm *tm; ! 624: log("Can't cancel %s: non-existent", argv[1]); ! 625: (void) time(&t); ! 626: tm = localtime(&t); ! 627: #ifdef USG ! 628: sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled", ! 629: #else /* !USG */ ! 630: sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled", ! 631: #endif /* !USG */ ! 632: argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, ! 633: tm->tm_min); ! 634: savehist(bfr); ! 635: return -1; ! 636: } ! 637: ! 638: q = index(line, '\t'); ! 639: p = index(q+1, '\t'); ! 640: if (p == NULL || *++p == '\0' || *p == '\n') { ! 641: *q = '\0'; ! 642: log("Expired article %s", line); ! 643: return -1; ! 644: } ! 645: if (strcmp(p, "cancelled") == 0) { ! 646: *q = '\0'; ! 647: log("Already Cancelled %s", line); ! 648: return -1; ! 649: } else ! 650: log("Cancelling %s", line); ! 651: if ((uid == ROOTID||uid == 0) && ( ! 652: #ifdef ORGDISTRIB ! 653: strcmp(header.distribution, ORGDISTRIB) == 0 || ! 654: #endif /* ORGDISTRIB */ ! 655: strcmp(header.distribution, "local") == 0)) ! 656: su = 1; ! 657: while (*p) { ! 658: q = index(p, ' '); ! 659: if (q) ! 660: *q = '\0'; ! 661: (void) strcpy(nfilename, dirname(p)); ! 662: fp = fopen(nfilename, "r"); ! 663: if (fp == NULL) { ! 664: log("Can't cancel %s: %s", line, errmsg(errno)); ! 665: return -1; ! 666: } ! 667: htmp.unrec[0] = NULL; ! 668: if (hread(&htmp, fp, TRUE) == NULL) { ! 669: if (bfr[0] == '/') { ! 670: fp = fopen(bfr, "r"); ! 671: if (fp == NULL ! 672: || hread(&htmp, fp, TRUE) == NULL) ! 673: error("Article is garbled."); ! 674: } else ! 675: error("Article is garbled."); ! 676: } ! 677: (void) fclose(fp); ! 678: poster = senderof(&htmp); ! 679: /* only compare up to '.' or ' ' */ ! 680: r = index(poster,'.'); ! 681: if (r == NULL) ! 682: r = index(poster,' '); ! 683: if (r != NULL) ! 684: *r = '\0'; ! 685: if (!su && strncmp(whatsisname, poster,strlen(poster))) { ! 686: error("Not contributor: posted by %s, and you are %s", poster, whatsisname); ! 687: } ! 688: ! 689: (void) unlink(nfilename); ! 690: p = q+1; ! 691: } ! 692: return 0; ! 693: } ! 694: ! 695: /* ! 696: * sendsys (no arguments) ! 697: * ! 698: * Mail the sys file to the person submitting the article. ! 699: * POLICY: the contents of your sys file are public information ! 700: * and as such, you should not change this code. You may feel ! 701: * free to arrange for it to manually notify you, in the event ! 702: * that you want to do something to clean it up before it goes out. ! 703: * Secret sites on the net are expressly frowned on. ! 704: * ! 705: * The purpose of this command is for making a network map. The ! 706: * details of your link and which newsgroups are forwarded are not ! 707: * important, in case you want to sanitize them. Since the definition ! 708: * of USENET is those sites getting net.announce, you can disable this ! 709: * on sites not getting net articles, but if you take out the list of ! 710: * forwarded newsgroups, and you have sites that only get local newsgroups, ! 711: * you should make this clear, or remove those sites from what you send out. ! 712: */ ! 713: /* ARGSUSED */ ! 714: c_sendsys(argc, argv) ! 715: char **argv; ! 716: { ! 717: register FILE *f, *u; ! 718: int c; ! 719: ! 720: #ifdef NOTIFY ! 721: f = mailhdr((struct hbuf *)NULL, "sendsys control message"); ! 722: if (f != NULL) { ! 723: fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB); ! 724: fprintf(f, "It has been sent.\n"); ! 725: (void) mclose(f); ! 726: } ! 727: #endif /* NOTIFY */ ! 728: f = mailhdr(&header, "response to your sendsys request"); ! 729: u = fopen(SUBFILE, "r"); ! 730: if (f != NULL && u != NULL) { ! 731: while ((c=getc(u)) != EOF) ! 732: putc(c, f); ! 733: (void) fclose(u); ! 734: (void) mclose(f); ! 735: } ! 736: return 0; ! 737: } ! 738: ! 739: /* ! 740: * Send the version number to the right person. ! 741: */ ! 742: /* ARGSUSED */ ! 743: c_version(argc, argv) ! 744: char **argv; ! 745: { ! 746: register FILE *f; ! 747: ! 748: f = mailhdr(&header, "Our news version"); ! 749: if (f == NULL) ! 750: error("Cannot send back error message"); ! 751: fprintf(f, "Currently running news version %s.\n\n", news_version); ! 752: fprintf(f, "The header of your message follows:\n\n"); ! 753: (void) hwrite(&header, f); ! 754: (void) mclose(f); ! 755: return 0; ! 756: } ! 757: ! 758: /* ! 759: * Check the active file for old or missing newsgroups ! 760: * Body of article is list of valid groups ! 761: */ ! 762: /* ARGSUSED */ ! 763: c_checkgroups(argc, argv) ! 764: char **argv; ! 765: { ! 766: int rc; ! 767: ! 768: (void) setuid(geteuid()); ! 769: /* dont change the cat %s| to < %s, it breaks some "unix" systems */ ! 770: (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB, ! 771: #ifdef NOTIFY ! 772: (TELLME && *TELLME) ? TELLME : NEWSUSR ); ! 773: #else /* !NOTIFY */ ! 774: NEWSUSR); ! 775: #endif /* !NOTIFY */ ! 776: rc = system(bfr); ! 777: log("system(%s) status %d", bfr, rc); ! 778: return 0; ! 779: } ! 780: ! 781: /* ! 782: * An unknown control message has been received. ! 783: */ ! 784: c_unknown(h, ctlmsgtext) ! 785: struct hbuf *h; ! 786: char *ctlmsgtext; ! 787: { ! 788: register FILE *f; ! 789: ! 790: log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path); ! 791: #ifdef NOTIFY ! 792: f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message"); ! 793: if (f != NULL) { ! 794: fprintf(f, "Currently running news version %s.\n\n", news_version); ! 795: fprintf(f, "The header of the message follows:\n\n"); ! 796: (void) hwrite(h, f); ! 797: (void) mclose(f); ! 798: } ! 799: #endif /* NOTIFY */ ! 800: return 0; ! 801: } ! 802: ! 803: /* ARGSUSED */ ! 804: c_unimp(argc, argv) ! 805: char **argv; ! 806: { ! 807: register FILE *f; ! 808: ! 809: #ifdef NOTIFY ! 810: f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message"); ! 811: if (f != NULL) { ! 812: fprintf(f, "Currently running news version B %s.\n\n", news_version); ! 813: fprintf(f, "The header of the message follows:\n\n"); ! 814: (void) hwrite(&header, f); ! 815: (void) mclose(f); ! 816: } ! 817: #endif /* NOTIFY */ ! 818: return 0; ! 819: } ! 820: ! 821: /* ! 822: * This is a modified version of popen, made more secure. Rather than ! 823: * forking off a shell, you get a bare process. You must have exactly ! 824: * one argument, and the command must be mail (or sendmail if you have it). ! 825: */ ! 826: #define RDR 0 ! 827: #define WTR 1 ! 828: static int mopen_pid[20]; ! 829: char *replyname(); ! 830: ! 831: FILE * ! 832: mhopen(hptr) ! 833: struct hbuf *hptr; ! 834: { ! 835: int p[2]; ! 836: register myside, hisside, pid; ! 837: char *sendto = "usenet"; ! 838: ! 839: if (hptr) ! 840: sendto = replyname(hptr); ! 841: else { ! 842: #ifdef NOTIFY ! 843: if (TELLME) ! 844: sendto = TELLME; ! 845: #endif /* NOTIFY */ ! 846: if (sendto == NULL || *sendto == '\0') ! 847: return NULL; ! 848: } ! 849: verifyname(sendto); ! 850: if(pipe(p) < 0) ! 851: return NULL; ! 852: myside = p[WTR]; ! 853: hisside = p[RDR]; ! 854: if((pid = vfork()) == 0) { ! 855: /* myside and hisside reverse roles in child */ ! 856: (void) close(myside); ! 857: (void) close(0); ! 858: (void) dup(hisside); ! 859: (void) close(hisside); ! 860: (void) setgid(gid); ! 861: (void) setuid(uid); ! 862: #ifdef SENDMAIL ! 863: execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL); ! 864: #endif /* SENDMAIL */ ! 865: #ifdef MMDF ! 866: execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL); ! 867: #endif /* MMDF */ ! 868: execl("/usr/bin/mailx", "mail", sendto, (char *)NULL); ! 869: execl("/usr/bin/mail", "mail", sendto, (char *)NULL); ! 870: execl("/usr/ucb/mail", "mail", sendto, (char *)NULL); ! 871: execl("/bin/mail", "mail", sendto, (char *)NULL); ! 872: _exit(1); ! 873: } ! 874: if(pid == -1) ! 875: return NULL; ! 876: mopen_pid[myside] = pid; ! 877: (void) close(hisside); ! 878: return(fdopen(myside, "w")); ! 879: } ! 880: ! 881: mclose(ptr) ! 882: FILE *ptr; ! 883: { ! 884: register f, r, (*hstat)(), (*istat)(), (*qstat)(); ! 885: int status; ! 886: ! 887: f = fileno(ptr); ! 888: (void) fclose(ptr); ! 889: istat = signal(SIGINT, SIG_IGN); ! 890: qstat = signal(SIGQUIT, SIG_IGN); ! 891: hstat = signal(SIGHUP, SIG_IGN); ! 892: while((r = wait(&status)) != mopen_pid[f] && r != -1) ! 893: ; ! 894: if(r == -1) ! 895: status = -1; ! 896: signal(SIGINT, istat); ! 897: signal(SIGQUIT, qstat); ! 898: signal(SIGHUP, hstat); ! 899: return status; ! 900: } ! 901: ! 902: /* ! 903: * mhopen a pipe to mail, write out a std header, and return the file ptr. ! 904: * ! 905: * We don't include a From: field because this is probably uucp, i.e. ! 906: * explicitly routed. Leave it up to the recipient's mailer. ! 907: * Always include the To: field because if we ge back failed mail, we ! 908: * might be able to deliver it by hand if we know to wom it was addressed. ! 909: * By convention, hptr==NULL means to send the message to the local contact person. ! 910: */ ! 911: FILE * ! 912: mailhdr(hptr, subject) ! 913: struct hbuf *hptr; ! 914: char *subject; ! 915: { ! 916: FILE *fp; ! 917: time_t now; ! 918: char *to = "usenet"; ! 919: extern char *mydomain(); ! 920: ! 921: #ifdef NOTIFY ! 922: if (TELLME && *TELLME) ! 923: to = TELLME; ! 924: #endif /* NOTIFY */ ! 925: if (hptr) ! 926: to = replyname(hptr); ! 927: ! 928: if ((fp = mhopen(hptr)) != NULL) { ! 929: (void) time(&now); ! 930: fprintf(fp, "Date: %s\n", arpadate(&now)); ! 931: #ifdef MMDF ! 932: fprintf(fp, "From: The News System <usenet@%s>\n", ! 933: FROMSYSNAME); ! 934: #endif /* MMDF */ ! 935: fprintf(fp, "To: %s\n", to); ! 936: fprintf(fp, "Subject: %s\n", subject); ! 937: fprintf(fp, "Responding-System: %s\n\n", LOCALSYSNAME); ! 938: } ! 939: return fp; ! 940: } ! 941: ! 942: /* ! 943: * verify that the name mail is being sent to does not contain any ! 944: * nasty hooks to invoke funny functions from the shell or the like. ! 945: */ ! 946: verifyname(sendto) ! 947: char *sendto; ! 948: { ! 949: /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */ ! 950: char *nasty = "\"'\\`^|;& <>/~"; ! 951: register char *p; ! 952: ! 953: if (sendto[0] <= ' ') { ! 954: xerror("nasty mail name %s from %s", sendto, header.path); ! 955: } ! 956: for (p=sendto; *p; p++) { ! 957: if (*p == ' ') { ! 958: *p = 0; ! 959: break; ! 960: } ! 961: } ! 962: if (strpbrk(sendto, nasty) != NULL) ! 963: error("nasty mail name %s from %s", sendto, header.path); ! 964: ! 965: for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) { ! 966: if (*++nasty == '.') /* check for .. */ ! 967: error("nasty mail name %s from %s", sendto, header.path); ! 968: } ! 969: } ! 970: ! 971: /* ! 972: * Checks to make sure the control message is OK to post. ! 973: */ ! 974: ctlcheck() ! 975: { ! 976: char msg[BUFLEN]; ! 977: char *p; ! 978: ! 979: if (!is_ctl) ! 980: return; ! 981: ! 982: if (header.ctlmsg[0]) ! 983: (void) strcpy(msg, header.ctlmsg); ! 984: else ! 985: (void) strcpy(msg, header.title); ! 986: ! 987: p = index(msg, ' '); ! 988: if (p) ! 989: *p = 0; ! 990: ! 991: if (strcmp(msg, "ihave") == 0 || strcmp(msg, "sendbad") == 0 || ! 992: strcmp(msg, "sendme") == 0) { ! 993: return; /* no restrictions */ ! 994: } else if (strcmp(msg, "newgroup") == 0) { ! 995: suser(); ! 996: } else if (strcmp(msg, "rmgroup") == 0) { ! 997: suser(); ! 998: } else if (strcmp(msg, "sendsys") == 0) { ! 999: suser(); ! 1000: } else if (strcmp(msg, "checkgroups") == 0) { ! 1001: suser(); ! 1002: } else if (strcmp(msg, "version") == 0) { ! 1003: return; /* no restrictions */ ! 1004: } else if (strcmp(msg, "cancel") == 0) { ! 1005: return; /* no restrictions at this level */ ! 1006: } else if (strcmp(msg, "delsub") == 0) { ! 1007: if (!PREFIX(header.nbuf, "to.")) { ! 1008: log("Must be in a 'to.system' newsgroup."); ! 1009: xxit(0); ! 1010: } ! 1011: return; ! 1012: } else { ! 1013: log("Unrecognized control message - %s\n", msg); ! 1014: xxit(0); ! 1015: } ! 1016: } ! 1017: ! 1018: /* Make sure this guy is special. */ ! 1019: suser() ! 1020: { ! 1021: if (uid == 0 || uid == ROOTID) ! 1022: return; ! 1023: /* ! 1024: * We assume that since our real uid is the same as NEWSUSR ! 1025: * (the euid) we were run by rootid and it did a setuid. ! 1026: * Too bad we can't set just the effective uid like suid does. ! 1027: */ ! 1028: if (uid == geteuid()) ! 1029: return; ! 1030: #ifdef IHCC ! 1031: printf("Please use the command:\n\ttoolnews providers\n"); ! 1032: printf("then call one of the news people.\n"); ! 1033: #else ! 1034: printf("Get your local netnews contact to do it for you.\n"); ! 1035: #endif ! 1036: xxit(0); ! 1037: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.