|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 27646 (0x6bfe) Types: TextFile Names: »control.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦373604645⟧ »EurOpenD3/news/bnews.2.11/src.tar.Z« └─⟦3beb569ac⟧ └─⟦this⟧ »src/control.c«
/* * This software is Copyright 1986, 1989 by Rick Adams. * * Permission is hereby granted to copy, reproduce, redistribute or * otherwise use this software as long as: there is no monetary * profit gained specifically from the use or reproduction or this * software, it is not sold, rented, traded or otherwise marketed, and * this copyright notice is included prominently in any copy * made. * * The author make no claims as to the fitness or correctness of * this software for any use whatsoever, and it is provided as is. * Any use of this software is at the user's own risk. * * Control message handling code. Deal with messages which are to be * acted on by netnews itself rather than by people. * * See defs.h "news_version" for the real version of netnews. */ #ifdef SCCSID static char *SccsId = "@(#)control.c 2.61 10/29/89"; #endif /* SCCSID */ #include "iparams.h" #define eq(msg) (STRCMP(msg, cargv[0]) == 0) int cargc; char **cargv; FILE *hfopen(); FILE *popen(), *mhopen(), *mailhdr(); FILE *controlmail; #define NCARGS 30 char *senderof(); #ifdef u370 static struct hbuf htmp; #endif /* u370 */ /* * The global structure is initialized to NOTIFY as the default (if defined) * uid to send mail to for every state. The following conditions are * dealt with (assumes NOTIFY defined): * * 1) LIB/notify exists and is empty (or contains no recognizable control * message types). * Action: force TELLME = ""; * 2) LIB/notify contains the control message name "all" and no associated * address. * Action: force TELLME = ""; * 3) LIB/notify contains the control message name "all" and has an address. * Action: set TELLME = AlloCpy(address); * 4) LIB/notify contains only some of the known control message types. * Action: initialize all addresses to "" and set declared addresses * to listed address. */ control(h) struct hbuf *h; { register char *ctlmsgtext; register struct msgtype *mp; if (STRNCMP(h->title, "cmsg ", 5) == 0) { register char *cp1, *cp2; cp1 = h->title; cp2 = h->title + 5; while (*cp1++ = *cp2++) ; } if (*h->ctlmsg) ctlmsgtext = h->ctlmsg; else ctlmsgtext = h->title; log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext); /* * Control messages have the standard format * command [args] * much like shell commands. Each site has the option * of customizing this code to deal with control messages * as they see fit, but we would like to buy back the * code, ifdeffed or otherwise parameterized, to simplify * the maintenence issues. */ argparse(ctlmsgtext); /* * We look for a match of the control message name and then * set TELLME to the value parsed from the LIB/notify file * (if any). */ for(mp=msgtype; mp->m_name; mp++) { if(eq(mp->m_name) ) { /* hit */ #ifdef NOTIFY TELLME = mp->m_who_to; /* reset whom to tell */ #endif /* NOTIFY */ return (*mp->m_func)(cargc, cargv); /* do it */ } } if( !mp->m_name ) { #ifdef NOTIFY TELLME = NOTIFY; #endif /* NOTIFY */ c_unknown(h, ctlmsgtext); } return 0; } /* * Parse the string str into separate words in cargc and cargv * as per the usual UNIX convention. Nothing fancy here, just * blanks and tabs separating words. */ argparse(str) char *str; { static char *cavpbuf[NCARGS]; static char cavbuf[256]; char *nextfree = cavbuf; if (str == '\0') error("Control message %s has no title", header.ident); cargc = (*str != '\0'); cargv = cavpbuf; cargv[0] = cavbuf; while (*str) { if (*str <= ' ') { /* skip over white space */ while (*str != '\0' && *str <= ' ') str++; if (*str == '\0') /* line ends in white space */ return; *nextfree++ = 0; cargv[cargc] = nextfree; if (cargc++ >= NCARGS) xerror("Too many arguments to control message %s", header.ident); } else *nextfree++ = *str++; } } #ifndef NFSCLIENT /* * ihave <artid> ... <remotesys> * or * ihave <remotesys> * with <artid>s in message body. * * The other system is telling you it has article <artid>, in case * you decide you want it to transmit it to you. * The assumption is that the other system only tells you about articles * in newsgroups you subscribe to. * * We turn the incoming ihave into an outgoing sendme on the fly. * It then gets saved in the SPOOL directory and transmitted to the * remote system. (This way the sendme messages can be batched.) */ c_ihave(argc, argv) register char ** argv; { register int i; char list[sizeof header.title]; extern char * findhist(); extern char * mydomain(); if (argc < 2) error("ihave: Too few arguments."); if (STRNCMP(PATHSYSNAME, argv[argc - 1], SNLN) == 0) return 0; list[0] = '\0'; if (argc > 2) { for (i = 1; i < (argc - 1); ++i) if (findhist(argv[i]) == NULL) { (void) strcat(list, " "); (void) strcat(list, argv[i]); } if (list[0] == '\0') return 0; } else { register FILE * outfp; register long outpos, inpos; char myid[256]; outfp = xfopen(INFILE, "a"); #ifdef USG /* * When fopening to append, USG systems don't * seek to EOF until write() is called. */ fseek(outfp, 0L, 2); #endif outpos = ftell(outfp); inpos = ftell(infp); while (ftell(infp) < outpos) { if (fgets(myid, sizeof myid, infp) != myid) error("iline: Can't reread article"); myid[strlen(myid) - 1] = '\0'; if (findhist(myid) == NULL) (void) fprintf(outfp, "%s\n", myid); } if (outpos == ftell(outfp)) { /* if nothing is wanted */ (void) fclose(outfp); (void) fseek(infp, inpos, 0); return 0; } (void) fclose(outfp); /* ** The close and open may just be paranoia. */ (void) fclose(infp); infp = xfopen(INFILE, "r"); (void) fseek(infp, outpos, 0); } /* ** Turn the ihave into a sendme. */ (void) sprintf(header.nbuf, "to.%s.ctl", argv[argc - 1]); (void) sprintf(header.title, "sendme%s %s", list, PATHSYSNAME); (void) strcpy(header.ctlmsg, header.title); getident(&header); (void) sprintf(header.from, "%s@%s", "usenet", FROMSYSNAME); (void) strcpy(header.path, NEWSUSR); header.subdate[0] = header.expdate[0] = '\0'; dates(&header); /* ** What else of this kind should be done? */ header.organization[0] = header.distribution[0] = '\0'; header.numlines[0] = '\0'; for (i = 0; i < NUNREC && header.unrec[i] != NULL; ++i) { free(header.unrec[i]); header.unrec[i] = NULL; } /* ** Note that we do *not* change the history line ** so that if the "ihave" message comes in again it gets rejected. */ return 0; } /* * sendme <artid> ... <remotesys> * or * sendme <remotesys> * with <artid>s in message body. * The other system wants me to send out article <artid>. * Give it to them with no fuss. */ #ifdef MULTICAST static int c_mc; static char ** c_sysnames; #endif /* MULTICAST */ c_sendme(argc, argv) register char **argv; { struct srec srec; if (argc < 2) error("sendme: Too few arguments."); if (STRNCMP(PATHSYSNAME, argv[argc - 1], SNLN) == 0) return 0; if (s_find(&srec, argv[argc - 1]) != TRUE) error("sendme: Can't find sys record for %s", argv[argc - 1]); #ifdef MULTICAST c_mc = index(srec.s_flags, 'M') != 0; if (c_mc) { struct srec trec; c_sysnames = &argv[argc - 1]; if (s_find(&trec, srec.s_xmit) != TRUE) error("sendme: Can't find sys record for %s for %s", srec.s_xmit, argv[argc - 1]); srec = trec; } else c_sysnames = NULL; #endif /* MULTICAST */ /* Send the articles. */ if (argc == 2) { register FILE * fp; char buf[256]; fp = xfopen(INFILE, "r"); while (fgets(buf, sizeof buf, fp) == buf) { buf[strlen(buf) - 1] = '\0'; /* zap trailing '\n' */ sendmefunc(buf, &srec); } (void) fclose(fp); } else { /* argc > 2 */ register int i; for (i = 1; i < (argc - 1); ++i) sendmefunc(argv[i], &srec); } return 0; } static sendmefunc(id, sp) register char * id; register struct srec * sp; { register FILE * fp; register char * cp; char savedbufname[256]; extern char firstbufname[]; extern char * dirname(); extern char * findfname(); cp = findfname(id); if (cp == NULL) { log("System %s wants unavailable article %s.", #ifdef MULTICAST (c_mc ? c_sysnames[0] : sp->s_name), id); #else /* !MULTICAST */ sp->s_name, id); #endif /* !MULTICAST */ return; } cp = dirname(cp); fp = fopen(cp, "r"); if (fp == NULL) { log("Article %s unopenable as %s.", id, cp); return; } (void) strcpy(savedbufname, firstbufname); (void) strcpy(firstbufname, cp); #ifdef MULTICAST transmit(sp, fp, FALSE, c_sysnames, c_mc); #else /* !MULTICAST */ transmit(sp, fp, FALSE, (char **) NULL, 0); #endif /* !MULTICAST */ /* transmit closes fp */ (void) strcpy(firstbufname, savedbufname); } /* * newgroup <groupname> * A new newsgroup has been created. * The body of the article, if present, is a description of the * purpose of the newsgroup. * */ c_newgroup(argc, argv) char **argv; { FILE *fd; char abuf[BUFLEN], subjline[BUFLEN]; int didcreate = 0; register char *p, *q; # ifdef NONEWGROUPS /* local allowed */ int can_change = (STRCMP(header.distribution, "local") == 0) # ifdef ORGDISTRIB /* or ORGDISTRIB */ || (STRCMP(header.distribution, ORGDISTRIB) == 0) # endif /* ORGDISTRIB */ || !ngmatch(argv[1], NONEWGROUPS); # else /* ! NONEWGROUPS */ int can_change = 1; /* allow changes for all distributions */ # endif /* NONEWGROUPS */ if (argc < 2) error("newgroup: Too few arguments."); if (header.approved[0] == '\0') { logerr("newgroup: %s not approved", argv[1]); return 1; } lock(); /* see if it already exists */ (void) rewind(actfp); clearerr(actfp); while(fgets(abuf, BUFLEN, actfp) != NULL) { p = abuf; q = argv[1]; while (*p++ == *q++) ; if (*--q == '\0' && *--p == ' ') { /* Now check if it's correctly moderated/unmoderated */ /* name 0000000 0000000 X */ /* 12345678901234567 */ p += 17; if (argc > 2 && STRCMP(argv[2], "moderated") == 0) { if (*p == 'm') { unlock(); return 0; } *p = 'm'; } else { if (*p != 'm') { unlock(); return 0; } *p = 'y'; } # ifdef NOTIFY if (can_change) (void) sprintf(subjline, "Newsgroup %s changed from %smoderated to %smoderated", argv[1], *p=='y' ? "" : "un", *p=='y' ? "un" : ""); else (void) sprintf(subjline, "Change newsgroup %s from %smoderated to %smoderated", argv[1], *p=='y' ? "" : "un", *p=='y' ? "un" : ""); fd = mailhdr((struct hbuf *)NULL, subjline); if (fd != NULL) { if(can_change) fprintf(fd, "%s has been changed from %smoderated to %smoderated as requested by\n%s\n", argv[1], *p=='y' ? "" : "un", *p=='y' ? "un":"", header.path); else { fprintf(fd, "%s\nhas requested that %s be changed from %smoderated to %smoderated\n", header.path, argv[1], *p=='y' ? "" : "un", *p=='y' ? "un" : ""); #ifdef ORGDISTRIB fprintf(fd, "You can accomplish this by re-creating the newsgroup with a distribution\n"); fprintf(fd, "of '%s' by executing the command:\n", ORGDISTRIB); fprintf(fd, "%s/inews -d %s -C %s%s\n", LIB, ORGDISTRIB, argv[1], *p=='y' ? "" : " moderated"); #else /* !ORGDISTRIB */ fprintf(fd, "You can accomplish this by re-creating the newsgroup by executing the command:\n"); fprintf(fd, "%s/inews -C %s%s\n", LIB, argv[1], *p=='y' ? "" : " moderated"); #endif /* !ORGDISTRIB */ } fprintf(fd, "\n\n%s says:\n", header.path); controlmail = fd; } # endif /* NOTIFY */ # ifdef NONEWGROUPS /* * No permission to change */ if(!can_change) { unlock(); return 0; } # endif /* NONEWGROUPS */ /* The active file was wrong about the state of the * group. Rewrite the active file */ (void) fseek(actfp, -2L, 1); /* back up 2 characters */ putc(*p, actfp); fflush(actfp); if (*p != 'm') logerr("Newsgroup %s changed from moderated to unmoderated", argv[1]); else logerr("Newsgroup %s changed from unmoderated to moderated", argv[1]); unlock(); return 0; } } /* It doesn't already exist, we must create it */ if(can_change) { didcreate++; (void) fseek(actfp, 0L, 2); clearerr(actfp); fprintf(actfp, "%s 0000000 0000001 %c\n", argv[1], (argc > 2 && STRCMP(argv[2], "moderated") == 0) ? 'm' : 'y'); #if defined(USG) || defined(MG1) /* * U G L Y K L U D G E * This utter piece of tripe is the only way I know of * to get around the fact that ATT BROKE standard IO * in System 5.2. Basically, you can't open a file for * "r+" and then try and write to it. This hack works * on all "real" USG Unix systems, It will probably * break on some obscure look alike that doesnt use the * real ATT stdio.h * also broken in WCW MG-1 42nix 2.0 * Don't blame me, blame ATT. stdio should have * already done the following line for us, but it didn't */ actfp->_flag |= _IOWRT; #endif /* USG */ fflush(actfp); } # ifdef NOTIFY if (didcreate) (void) sprintf(subjline, "Newsgroup %s created", argv[1]); else (void) sprintf(subjline, "Create newsgroup %s", argv[1]); fd = mailhdr((struct hbuf *)NULL, subjline); if (fd != NULL) { if (didcreate) fprintf(fd, "A new %snewsgroup called '%s' has been created by %s.\n", argc > 2 ? "moderated " : "", argv[1], header.path); else { fprintf(fd, "%s requested that a new %snewsgroup called '%s' be created.\n", header.path, argc > 2 ? "moderated " : "", argv[1]); fprintf(fd,"It was approved by %s\n\n",header.approved); fprintf(fd, "You can accomplish this by creating the newgroup yourself\n"); # ifdef ORGDISTRIB fprintf(fd,"with a distribution of '%s'.\n", ORGDISTRIB); fprintf(fd, "In other words, by executing the command:\n"); fprintf(fd, "%s/inews -d %s -C %s %s\n", LIB, ORGDISTRIB, argv[1], argc > 2 ? argv[2] : ""); # else /* !ORGDISTRIB */ fprintf(fd, "In other words, by executing the command:\n"); fprintf(fd, "%s/inews -C %s %s\n", LIB, argv[1], argc > 2 ? argv[2] : ""); # endif /* !ORGDISTRIB */ } fprintf(fd, "\n\n%s says:\n", header.path); controlmail = fd; } # endif /* NOTIFY */ unlock(); return 0; } /* * rmgroup <groupname> * An old newsgroup is being cancelled on a network wide basis. */ c_rmgroup(argc, argv) char **argv; { FILE *fd; int shouldremove = 0; #ifdef NOTIFY char subjline[BUFLEN]; #endif /* NOTIFY */ if (argc < 2) error("rmgroup: Too few arguments."); if (!validng(argv[1])) return 0; if (header.approved[0] == '\0') { logerr("rmgroup: %s not approved", argv[1]); return 1; } #ifdef NORMGROUPS /* Allow local removals */ if (!STRCMP("local", header.distribution) #ifdef ORGDISTRIB /* as well as organizational removals */ || !STRCMP(ORGDISTRIB, header.distribution) #endif /* ORGDISTRIB */ || !ngmatch(argv[1], NORMGROUPS)) #endif /* NORMGROUPS */ shouldremove++; #ifdef NOTIFY sprintf(subjline, "Received rmgroup for %s", argv[1]); fd = mailhdr((struct hbuf *)NULL, subjline); if (fd != NULL) { if (shouldremove) { fprintf(fd, "Newsgroup '%s' has been removed by %s.\n\n", argv[1], header.path); # ifdef USG fprintf(fd, "You may need to remove the directory %s by hand\n", dirname(argv[1])); # endif } else { fprintf(fd, "%s requested that newsgroup %s be removed.\n", header.path, argv[1]); fprintf(fd, "You should remove it by hand\n"); fprintf(fd, "To do this, execute the command\n"); fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]); } fprintf(fd, "\n\n%s says:\n", header.path); controlmail = fd; } #endif /* NOTIFY */ if (shouldremove) { int pid, status; /* We let the shell do all the work. * See the rmgrp shell script. */ dolock(); (void) sprintf(bfr, "%s/rmgroup", LIB); if (pid = fork()) { status = fwait(pid); } else { register int i; for (i =3; i<20; i++) if (close(i) < 0) break; (void) setuid(duid); execvp(bfr, argv); } rmlock(); if (status) log("rmgroup status %d", status); } return 0; } #endif /* !NFSCLIENT */ /* * cancel <artid> * Cancel the named article */ c_cancel(argc, argv) char **argv; { char *line, *p, *q, *r, *poster; char *findhist(); register FILE *fp; char whatsisname[BUFLEN], nfilename[BUFLEN]; time_t t; int su = 0; #ifndef u370 struct hbuf htmp; #endif /* !u370 */ if (argc < 2) error("cancel: Too few arguments."); #ifndef NFSCLIENT (void) strcpy(whatsisname, senderof(&header)); line = findhist(argv[1]); if (line == NULL) { log("Can't cancel %s: non-existent", argv[1]); (void) time(&t); sprintf(bfr,"%s\t%ld\tcancelled", argv[1], t); savehist(bfr); return -1; } q = index(line, '\t'); p = index(q+1, '\t'); if (p == NULL || *++p == '\0' || *p == '\n') { *q = '\0'; log("Expired article %s", line); return -1; } if (STRCMP(p, "cancelled") == 0) { *q = '\0'; log("Already Cancelled %s", line); return -1; } else log("Cancelling %s", line); if ((uid == ROOTID||uid == 0) && ( #ifdef ORGDISTRIB STRCMP(header.distribution, ORGDISTRIB) == 0 || #endif /* ORGDISTRIB */ STRCMP(header.distribution, "local") == 0)) su = 1; while (*p) { q = index(p, ' '); if (q) *q = '\0'; (void) strcpy(nfilename, dirname(p)); fp = fopen(nfilename, "r"); if (fp == NULL) { log("Can't cancel %s: %s", line, errmsg(errno)); return -1; } htmp.unrec[0] = NULL; if (hread(&htmp, fp, TRUE) == NULL) { if (bfr[0] == '/') { fp = fopen(bfr, "r"); if (fp == NULL || hread(&htmp, fp, TRUE) == NULL) error("Article is garbled."); } else error("Article is garbled."); } (void) fclose(fp); poster = senderof(&htmp); /* only compare up to '.' or ' ' */ r = index(poster,'.'); if (r == NULL) r = index(poster,' '); if (r != NULL) *r = '\0'; if (!su && STRNCMP(whatsisname, poster, strlen(poster))) { error("Not contributor: posted by %s, and you are %s", poster, whatsisname); } (void) unlink(nfilename); if (q == NULL) break; p = q+1; } #endif /* !NFSCLIENT */ return 0; } #ifndef NFSCLIENT /* * sendsys (no arguments) * * Mail the sys file to the person submitting the article. * POLICY: the contents of your sys file are public information * and as such, you should not change this code. You may feel * free to arrange for it to manually notify you, in the event * that you want to do something to clean it up before it goes out. * Secret sites on the net are expressly frowned on. * * The purpose of this command is for making a network map. The * details of your link and which newsgroups are forwarded are not * important, in case you want to sanitize them. Since the definition * of USENET is those sites getting net.announce, you can disable this * on sites not getting net articles, but if you take out the list of * forwarded newsgroups, and you have sites that only get local newsgroups, * you should make this clear, or remove those sites from what you send out. */ /* ARGSUSED */ c_sendsys(argc, argv) char **argv; { register FILE *f, *u; register int len; register char *cp; #ifdef NOTIFY if (argc < 2) { f = mailhdr((struct hbuf *)NULL, "sendsys control message"); if (f != NULL) { fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB); fprintf(f, "It has been sent.\n"); fprintf(f, "\n\n%s says:\n", header.path); controlmail = f; } } #endif /* NOTIFY */ f = mailhdr(&header, "response to your sendsys request"); u = fopen(SUBFILE, "r"); if (f == NULL || u == NULL) return 0; if (argc < 2) { while (len = fread(bfr, 1, sizeof bfr, u)) fwrite(bfr, 1, len, f); (void) fclose(u); (void) mclose(f); return 0; } cp = argv[argc -1]; len = strlen(cp); while (fgets(bfr, sizeof bfr, u) != NULL) { while (STRNCMP(bfr, cp, len) == 0 && (bfr[len] == ':' || bfr[len] == '/')) { register char *ch, c; do { ch = bfr; while (c= *ch++) putc(c, f); c = ch[-3]; /* looking for trailing \ */ } while (fgets(bfr, sizeof bfr, u) != NULL && c == '\\'); } } (void) fclose(u); (void) mclose(f); return 0; } /* * Send the version number to the right person. */ /* ARGSUSED */ c_version(argc, argv) char **argv; { register FILE *f; #ifdef NOTIFY if (argc < 2) { f = mailhdr((struct hbuf *)NULL, "version control message"); if (f != NULL) { fprintf(f, "%s requested your news version.\n", header.path); fprintf(f, "It has been sent.\n"); fprintf(f, "\n\n%s says:\n", header.path); controlmail = f; } } #endif /* NOTIFY */ f = mailhdr(&header, "Our news version"); if (f == NULL) error("Cannot send back error message"); fprintf(f, "Currently running news version %s.\n\n", news_version); (void) mclose(f); return 0; } /* * Check the active file for old or missing newsgroups * Body of article is list of valid groups */ /* ARGSUSED */ c_checkgroups(argc, argv) char **argv; { int rc; if (header.approved[0] == '\0') { logerr("checkgroups: not approved"); return 1; } if (header.distribution[0] == '\0') xerror("checkgroups must have a distribution"); (void) setuid(geteuid()); /* dont change the cat %s| to < %s, it breaks some "unix" systems */ (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB, #ifdef NOTIFY (TELLME && *TELLME) ? TELLME : NEWSUSR ); #else /* !NOTIFY */ NEWSUSR); #endif /* !NOTIFY */ rc = system(bfr); log("system(%s) status %d", bfr, rc); return 0; } #endif /* !NFSCLIENT */ /* * An unknown control message has been received. */ c_unknown(h, ctlmsgtext) struct hbuf *h; char *ctlmsgtext; { register FILE *f; log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path); #ifdef NOTIFY f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message"); if (f != NULL) { fprintf(f, "Currently running news version %s.\n\n", news_version); fprintf(f, "The header of the message follows:\n\n"); (void) hwrite(h, f); (void) mclose(f); } #endif /* NOTIFY */ return 0; } /* ARGSUSED */ c_unimp(argc, argv) char **argv; { register FILE *f; #ifdef NOTIFY f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message"); if (f != NULL) { fprintf(f, "Currently running news version B %s.\n\n", news_version); fprintf(f, "The header of the message follows:\n\n"); (void) hwrite(&header, f); (void) mclose(f); } #endif /* NOTIFY */ return 0; } /* * This is a modified version of popen, made more secure. Rather than * forking off a shell, you get a bare process. You must have exactly * one argument, and the command must be mail (or sendmail if you have it). */ #define RDR 0 #define WTR 1 static int mopen_pid[20]; char *replyname(); FILE * mhopen(hptr) struct hbuf *hptr; { int p[2]; register myside, hisside, pid; char *sendto = "usenet"; if (hptr) sendto = replyname(hptr); else { #ifdef NOTIFY if (TELLME) sendto = TELLME; #endif /* NOTIFY */ if (sendto == NULL || *sendto == '\0') return NULL; } verifyname(sendto); if(pipe(p) < 0) return NULL; myside = p[WTR]; hisside = p[RDR]; if((pid = vfork()) == 0) { /* myside and hisside reverse roles in child */ (void) close(myside); (void) close(0); (void) dup(hisside); (void) close(hisside); unlock(); (void) setgid(gid); (void) setuid(uid); #ifdef SENDMAIL execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL); #endif /* SENDMAIL */ #ifdef MMDF execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL); #endif /* MMDF */ execl("/usr/bin/mail", "mail", sendto, (char *)NULL); execl("/usr/ucb/mail", "mail", sendto, (char *)NULL); execl("/bin/mail", "mail", sendto, (char *)NULL); execl("/usr/bin/mailx", "mail", sendto, (char *)NULL); _exit(1); } if(pid == -1) return NULL; mopen_pid[myside] = pid; (void) close(hisside); return(fdopen(myside, "w")); } mclose(ptr) FILE *ptr; { register int f, r; SIGNAL_TYPE hstat, istat, qstat; int status; f = fileno(ptr); (void) fclose(ptr); istat = (int (*)())signal(SIGINT, SIG_IGN); qstat = (int (*)())signal(SIGQUIT, SIG_IGN); hstat = (int (*)())signal(SIGHUP, SIG_IGN); while((r = wait(&status)) != mopen_pid[f] && r != -1) ; if(r == -1) status = -1; signal(SIGINT, istat); signal(SIGQUIT, qstat); signal(SIGHUP, hstat); return status; } /* * mhopen a pipe to mail, write out a std header, and return the file ptr. * * We don't include a From: field because this is probably uucp, i.e. * explicitly routed. Leave it up to the recipient's mailer. * Always include the To: field because if we ge back failed mail, we * might be able to deliver it by hand if we know to wom it was addressed. * By convention, hptr==NULL means to send the message to the local contact person. */ FILE * mailhdr(hptr, subject) struct hbuf *hptr; char *subject; { FILE *fp; time_t now; char *to = "usenet"; extern char *mydomain(); #ifdef NOTIFY if (TELLME && *TELLME) to = TELLME; #endif /* NOTIFY */ if (hptr) to = replyname(hptr); if ((fp = mhopen(hptr)) != NULL) { (void) time(&now); fprintf(fp, "Date: %s\n", arpadate(&now)); #ifdef MMDF fprintf(fp, "From: The News System <usenet@%s>\n", FROMSYSNAME); #endif /* MMDF */ fprintf(fp, "To: %s\n", to); fprintf(fp, "Subject: %s\n", subject); fprintf(fp, "Responding-System: %s\n\n", LOCALSYSNAME); } return fp; } /* * verify that the name mail is being sent to does not contain any * nasty hooks to invoke funny functions from the shell or the like. */ verifyname(sendto) char *sendto; { /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */ char *nasty = "\"'\\`^|;& <>/~"; register char *p; if (sendto[0] <= ' ') { xerror("nasty mail name %s from %s", sendto, header.path); } for (p=sendto; *p; p++) { if (*p == ' ') { *p = 0; break; } } if (strpbrk(sendto, nasty) != NULL) error("nasty mail name %s from %s", sendto, header.path); for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) { if (*++nasty == '.') /* check for .. */ error("nasty mail name %s from %s", sendto, header.path); } } #ifndef NFSCLIENT /* * Checks to make sure the control message is OK to post. */ ctlcheck() { char msg[BUFLEN]; char *p; if (!is_ctl) return; if (header.ctlmsg[0]) (void) strcpy(msg, header.ctlmsg); else (void) strcpy(msg, header.title); p = index(msg, ' '); if (p) *p = 0; if (STRCMP(msg, "ihave") == 0 || STRCMP(msg, "sendbad") == 0 || STRCMP(msg, "sendme") == 0) { return; /* no restrictions */ } else if (STRCMP(msg, "newgroup") == 0) { suser(); } else if (STRCMP(msg, "rmgroup") == 0) { suser(); } else if (STRCMP(msg, "sendsys") == 0) { suser(); } else if (STRCMP(msg, "checkgroups") == 0) { suser(); } else if (STRCMP(msg, "version") == 0) { return; /* no restrictions */ } else if (STRCMP(msg, "cancel") == 0) { return; /* no restrictions at this level */ } else if (STRCMP(msg, "delsub") == 0) { if (!PREFIX(header.nbuf, "to.")) { log("Must be in a 'to.system' newsgroup."); xxit(0); } return; } else { log("Unrecognized control message - %s\n", msg); xxit(0); } } #endif /* !NFSCLIENT */ /* Make sure this guy is special. */ suser() { if (uid == 0 || uid == ROOTID) return; /* * We assume that since our real uid is the same as NEWSUSR * (the euid) we were run by rootid and it did a setuid. * Too bad we can't set just the effective uid like suid does. */ if (uid == geteuid()) return; #ifdef IHCC printf("Please use the command:\n\ttoolnews providers\n"); printf("then call one of the news people.\n"); #else printf("Get your local netnews contact to do it for you.\n"); #endif xxit(0); }