1: /*
   2:  * recnews [to newsgroup] [from user]
   3:  *
   4:  * Process a news article which has been mailed to some group like msgs.
   5:  * Such articles are in normal mail format and have never seen the insides
   6:  * of netnews.  If the "to newsgroup" is included, the article is posted
   7:  * to this newsgroup instead of trying to intuit it from the headers.
   8:  * If the "from user" is included, the return address is forged to look
   9:  * like that user instead of what getuid or a from line says.
  10:  *
  11:  * It is recommended that you always include the to newsgroup, since the
  12:  * intuition code is flakey and out of date.  The from user is probably
  13:  * appropriate for arpanet mailing lists being funnelled at ucbvax but
  14:  * not otherwise.  Sample lines in /usr/lib/aliases (if you run delivermail):
  15:  *	worldnews: "|/usr/lib/news/recnews net.general"
  16:  *		Allows you to mail to worldnews rather than using inews.
  17:  *		Intended for humans to mail to.
  18:  *	post-unix-wizards: "|/usr/lib/news/recnews fa.unix-wizards unix-wizards"
  19:  *		Causes mail to post-unix-wizards to be fed into fa.unix-wizards
  20:  *		and the return address forged as unix-wizards on the local
  21:  *		machine.  post-unix-wizards (on the local machine) should
  22:  *		be part of the master mailing list somewhere (on a different
  23:  *		machine.)
  24:  *
  25:  * Recnews is primarily useful in remote places on the usenet which collect
  26:  * mail from mailing lists and funnel them into the network.  It is also
  27:  * useful if you like to send mail to some user instead of invoking
  28:  * inews -t .. -n .. when you want to submit an article.  (Many mailers give
  29:  * you nice facilities like editing the message.)  It is not, however,
  30:  * essential to use recnews to be able to join usenet.
  31:  *
  32:  * WARNING: recnews disables the "recording" check - it has to because
  33:  * by the time inews is run, it's in the background and too late to
  34:  * ask permission.  If you depend heavily on recordings you probably
  35:  * should not allow recnews (and thus the mail interface) to be used.
  36:  */
  37: 
  38: #ifdef SCCSID
  39: static char *SccsId = "@(#)recnews.c	2.11	3/19/86";
  40: #endif /* SCCSID */
  41: 
  42: #include "defs.h"
  43: 
  44: #include <stdio.h>
  45: #include <ctype.h>
  46: 
  47: /*
  48:  * Note: we assume there are 2 kinds of hosts using recnews:
  49:  * Those that have delivermail (and hence this program will never
  50:  * have to deal with more than one message at a time) and those on the arpanet
  51:  * that do not (and hence all messages end with a sentinel).  It is
  52:  * supposed that regular v7 type systems without delivermail or some
  53:  * other automatic forwarding device will just use rnews.  We do
  54:  * not attempt to tell where a message ends on all systems due to the
  55:  * different conventions in effect.  (This COULD be fixed, I suppose.)
  56:  */
  57: 
  58: /*
  59:  * Kinds of lines in a message.
  60:  */
  61: #define FROM    001     /* From line */
  62: #define SUBJ    002     /* Subject */
  63: #define TO  003     /* To (newgroup based on this) */
  64: #define BLANK   004     /* blank line */
  65: #define EOM 005     /* End of message (4 ctrl A's) */
  66: #define HEADER  006     /* any unrecognized header */
  67: #define TEXT    007     /* anything unrecognized */
  68: #define INCLUSIVE 010       /* newsgroup is already in header */
  69: 
  70: /*
  71:  * Possible states program can be in.
  72:  */
  73: #define SKIPPING    0100    /* In header of message */
  74: #define READING     0200    /* In body of message */
  75: 
  76: #define BFSZ 250
  77: 
  78: #define EOT '\004'
  79: 
  80: char    from[BFSZ];     /* mailing address for replies */
  81: char    sender[BFSZ];       /* mailing address of author, if different */
  82: char    to[BFSZ];       /* Destination of mail (msgs, etc) */
  83: char    subject[BFSZ];      /* subject of message */
  84: char    newsgroup[BFSZ];    /* newsgroups of message */
  85: char    cmdbuf[BFSZ];       /* command to popen */
  86: 
  87: extern  char    *strcat(), *strcpy();
  88: extern  FILE    *popen();
  89: char    *any();
  90: 
  91: main(argc, argv)
  92: int argc;
  93: char **argv;
  94: {
  95:     char buf[BFSZ], inews[BFSZ];
  96:     register char *p, *q;
  97:     register FILE *pipe = NULL;
  98:     register int state;
  99: 
 100:     /* build inews command */
 101: #ifdef IHCC
 102:     sprintf(inews, "%s/%s/%s", logdir(HOME), LIBDIR, "inews");
 103: #else
 104:     sprintf(inews, "%s/%s", LIBDIR, "inews");
 105: #endif
 106: 
 107:     if (argc > 1)
 108:         strcpy(to, argv[1]);
 109:     if (argc > 2)
 110:         strcpy(from, argv[2]);
 111: #ifdef debug
 112:     printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n",
 113:         argv[0], argv[1], argv[2]);
 114: #endif
 115:     state = SKIPPING;
 116:     while (fgets(buf, BFSZ, stdin) != NULL) {
 117:         if (state == READING) {
 118:             fputs(buf,pipe);
 119:             continue;
 120:         }
 121:         switch (type(buf)) {
 122: 
 123:         case FROM:
 124:             frombreak(buf, from);
 125:             break;
 126: 
 127:         case SUBJ:
 128:             p = any(buf, " \t");
 129:             if (p == NULL)
 130:                 p = buf + 8;
 131:             q = subject;
 132:             while (*++p) {
 133:                 if (*p == '"')
 134:                     *q++ = '\\';
 135:                 *q++ = *p;
 136:             }
 137:             q[-1] = '\0';
 138:             break;
 139: 
 140:         case TO:
 141:             if (to[0])
 142:                 break;      /* already have one */
 143:             p = any(buf, " \t");
 144:             if (p == NULL)
 145:                 p = buf + 3;
 146:             q = to;
 147:             while (*++p) {
 148:                 if (*p == '"')
 149:                     *q++ = '\\';
 150:                 *q++ = *p;
 151:             }
 152:             q[-1] = '\0';
 153:             break;
 154: 
 155:         case INCLUSIVE:
 156:             sprintf(cmdbuf,"exec %s -p", inews);
 157:             pipe = popen(cmdbuf,"w");
 158:             if (pipe == NULL){
 159:                 perror("recnews: open failed");
 160:                 exit(1);
 161:             }
 162:             state = READING;
 163:             fputs(buf,pipe);
 164:             break;
 165: 
 166:         /*
 167: 		 * Kludge to compensate for messages without real headers
 168: 		 */
 169:         case HEADER:
 170:             break;
 171: 
 172:         case BLANK:
 173:             state = READING;
 174:             findgroup(to, newsgroup);
 175:             sprintf(cmdbuf, "exec %s -t \"%s\" -n \"%s\" -f \"%s\"",
 176:                 inews, *subject ? subject : "(none)",
 177:                 newsgroup, from);
 178: #ifdef debug
 179:             pipe = stdout;
 180:             printf("BLANK: %s\n", cmdbuf);
 181: #else
 182:             pipe = popen(cmdbuf, "w");
 183:             if (pipe == NULL) {
 184:                 perror("recnews: popen failed");
 185:                 exit(1);
 186:             }
 187: #endif
 188:             if (sender[0]) {
 189:                 fputs(sender, pipe);
 190:                 putc('\n', pipe);
 191:             }
 192:             break;
 193: 
 194:         case TEXT:
 195:             findgroup(to, newsgroup);
 196:             state = READING;
 197:             if (subject[0] == 0) {
 198:                 strcpy(subject, buf);
 199:                 if (subject[strlen(subject)-1] == '\n')
 200:                     subject[strlen(subject)-1] = '\0';
 201:             }
 202:             sprintf(cmdbuf, "exec \"%s\" -t \"%s\" -n \"%s\" -f \"%s\"",
 203:                 inews, subject, newsgroup, from);
 204: #ifdef debug
 205:             pipe = stdout;
 206:             printf("TEXT: %s\n", cmdbuf);
 207: #else
 208:             pipe = popen(cmdbuf, "w");
 209:             if (pipe == NULL) {
 210:                 perror("pipe failed");
 211:                 exit(1);
 212:             }
 213: #endif
 214:             if (sender[0]){
 215:                 fputs(sender, pipe);
 216:                 putc('\n',pipe);
 217:             }
 218:             break;
 219:         }
 220:     }
 221:     exit(0);
 222: }
 223: 
 224: type(p)
 225: register char *p;
 226: {
 227:     char *firstbl;
 228:     static char lasthdr;        /* prev line was a header */
 229: 
 230:     lasthdr = 1;
 231:     if ((*p == ' ' || *p == '\t') && lasthdr)
 232:         return HEADER;      /* continuation line */
 233:     firstbl = any(p, " \t");
 234:     while (*p == ' ' || *p == '?' || *p == '\t')
 235:         ++p;
 236: 
 237:     if (*p == '\n' || *p == 0)
 238:         return BLANK;
 239:     if (strncmp(p, ">From", 5) == 0 || strncmp(p, "From", 4) == 0)
 240:         return FROM;
 241:     if (strncmp(p, "Subj", 4)==0 || strncmp(p, "Re:", 3)==0 ||
 242:         strncmp(p, "re:", 3)==0)
 243:         return SUBJ;
 244:     if (strncmp(p, "To", 2)==0)
 245:         return TO;
 246:     if (strncmp(p, "\1\1\1\1", 4)==0)
 247:         return EOM;
 248:     if (firstbl && firstbl[-1] == ':' && isalpha(*p))
 249:         return HEADER;
 250:     lasthdr = 0;
 251:     return TEXT;
 252: }
 253: 
 254: /*
 255:  * Figure out who a message is from.
 256:  */
 257: frombreak(buf, fbuf)
 258: register char *buf, *fbuf;
 259: {
 260:     char wordfrom[BFSZ], uname[BFSZ], at[BFSZ], site[BFSZ];
 261: 
 262:     if (fbuf[0]) {  /* we already know who it's from */
 263:         if (sender[0] == 0 || buf[4] == ':') {
 264: #ifdef debug
 265:             printf("sender set to: %s", buf);
 266: #endif
 267:             strcpy(sender, buf);
 268:         }
 269:         return;
 270:     }
 271:     /* break the line into tokens. */
 272:     sscanf(buf, "%s %s %s %s", wordfrom, uname, at, site);
 273:     if (isat(at))
 274:         /*
 275: 		 * Some arpanet mail comes from "joe at mit-dms"
 276: 		 * instead of "joe@mit-dms", so handle it here.
 277: 		 */
 278:         sprintf(fbuf, "%s@%s", uname, site);
 279:     else
 280:         strcpy(fbuf, uname);
 281: }
 282: 
 283: isat(str)
 284: char *str;
 285: {
 286:     if (strcmp(str, "@")==0) return TRUE;
 287:     if (strcmp(str, "at")==0) return TRUE;
 288:     if (strcmp(str, "AT")==0) return TRUE;
 289:     return FALSE;
 290: }
 291: 
 292: findgroup(dest, group)
 293: char *dest ;
 294: char *group;
 295: {
 296: #ifdef debug
 297:     printf("findgroup(%s)\n", dest);
 298: #endif
 299: #ifdef fussy
 300:     /*
 301: 	 * Default unknown "to" fields to "general".  This gives you
 302: 	 * tight control over which newsgroups exist.
 303: 	 */
 304:     if (strcmp(dest, "msgs")==0)
 305:         strcpy(group, "msgs");
 306:     else if (strcmp(dest, "allmsgs")==0)
 307:         strcpy(group, "NET.allmsgs");
 308:     else if (strcmp(dest, "csmsgs")==0)
 309:         strcpy(group, "NET.csmsgs");
 310:     else
 311:         strcpy(group, "general");
 312: #else
 313:     /*
 314: 	 * Allow any newsgroup.  This way you don't have to recompile
 315: 	 * recnews every time you add a newsgroup.
 316: 	 */
 317:     strcpy(group, dest);
 318: #endif
 319: }
 320: 
 321: /*
 322:  * Return the ptr in sp at which a character in sq appears;
 323:  * NULL if not found
 324:  *
 325:  */
 326: 
 327: char *
 328: any(sp, sq)
 329: char *sp, *sq;
 330: {
 331:     register c1, c2;
 332:     register char *q;
 333: 
 334:     while (c1 = *sp++) {
 335:         q = sq;
 336:         while (c2 = *q++)
 337:             if (c1 == c2)
 338:                 return(--sp);
 339:     }
 340:     return(NULL);
 341: }

Defined functions

any defined in line 327; used 4 times
findgroup defined in line 292; used 2 times
frombreak defined in line 257; used 1 times
isat defined in line 283; used 1 times
main defined in line 91; never used
type defined in line 224; used 1 times

Defined variables

SccsId defined in line 39; never used
cmdbuf defined in line 85; used 8 times
from defined in line 80; used 4 times
newsgroup defined in line 84; used 4 times
sender defined in line 81; used 6 times
subject defined in line 83; used 10 times
to defined in line 82; used 5 times

Defined macros

BFSZ defined in line 76; used 13 times
BLANK defined in line 64; used 1 times
EOM defined in line 65; used 1 times
EOT defined in line 78; never used
FROM defined in line 61; used 1 times
HEADER defined in line 66; used 2 times
INCLUSIVE defined in line 68; never used
READING defined in line 74; used 4 times
SKIPPING defined in line 73; used 1 times
SUBJ defined in line 62; used 1 times
TEXT defined in line 67; used 1 times
TO defined in line 63; used 1 times
Last modified: 1986-03-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1723
Valid CSS Valid XHTML 1.0 Strict