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: }

Defined functions

argparse defined in line 101; used 1 times
  • in line 67
c_cancel defined in line 324; used 1 times
  • in line 70
c_checkgroups defined in line 524; used 1 times
  • in line 88
c_ihave defined in line 134; used 1 times
  • in line 74
c_newgroup defined in line 217; used 1 times
  • in line 72
c_rmgroup defined in line 269; used 1 times
  • in line 80
c_sendme defined in line 161; used 2 times
c_sendsys defined in line 429; used 1 times
  • in line 82
c_senduuname defined in line 471; used 1 times
  • in line 84
c_unimp defined in line 563; used 1 times
  • in line 90
c_unknown defined in line 544; used 1 times
  • in line 92
c_version defined in line 505; used 1 times
  • in line 86
control defined in line 40; used 1 times
ctlcheck defined in line 775; used 1 times
mailhdr defined in line 706; used 14 times
mclose defined in line 676; used 12 times
mhopen defined in line 627; used 2 times
suser defined in line 822; used 5 times
verifyname defined in line 746; used 1 times
xmitmsg defined in line 579; used 1 times

Defined variables

SccsId defined in line 22; never used
cargc defined in line 29; used 14 times
cargv defined in line 30; used 15 times
htmp defined in line 37; used 26 times
mopen_pid defined in line 624; used 2 times

Defined macros

RDR defined in line 622; used 1 times
WTR defined in line 623; used 1 times
eq defined in line 27; used 11 times
Last modified: 1986-03-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3166
Valid CSS Valid XHTML 1.0 Strict