|
|
1.1 ! root 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: * intution 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 now allow recnews (and thus the mail interface) to be used. ! 36: */ ! 37: ! 38: static char *SccsId = "@(#)recnews.c 2.4 3/3/83"; ! 39: ! 40: #include "defs.h" ! 41: ! 42: #include <stdio.h> ! 43: #include <ctype.h> ! 44: ! 45: /* ! 46: * Note: we assume there are 2 kinds of hosts using recnews: ! 47: * Those that have delivermail (and hence this program will never ! 48: * have to deal with more than one message at a time) and those on the arpanet ! 49: * that do not (and hence all messages end with a sentenel). It is ! 50: * supposed that regular v7 type systems without delivermail or some ! 51: * other automatic forwarding device will just use rnews. We do ! 52: * not attempt to tell where a message ends on all systems due to the ! 53: * different conventions in effect. (This COULD be fixed, I suppose.) ! 54: */ ! 55: ! 56: /* ! 57: * Kinds of lines in a message. ! 58: */ ! 59: #define FROM 001 /* From line */ ! 60: #define SUBJ 002 /* Subject */ ! 61: #define TO 003 /* To (newgroup based on this) */ ! 62: #define BLANK 004 /* blank line */ ! 63: #define EOM 005 /* End of message (4 ctrl A's) */ ! 64: #define HEADER 006 /* any unrecognized header */ ! 65: #define TEXT 007 /* anything unrecognized */ ! 66: ! 67: /* ! 68: * Possible states program can be in. ! 69: */ ! 70: #define SKIPPING 0100 /* In header of message */ ! 71: #define READING 0200 /* In body of message */ ! 72: ! 73: #define BFSZ 250 ! 74: ! 75: #define EOT '\004' ! 76: ! 77: char from[BFSZ]; /* mailing address for replies */ ! 78: char sender[BFSZ]; /* mailing address of author, if different */ ! 79: char to[BFSZ]; /* Destination of mail (msgs, etc) */ ! 80: char subject[BFSZ]; /* subject of message */ ! 81: char newsgroup[BFSZ]; /* newsgroups of message */ ! 82: char cmdbuf[BFSZ]; /* command to popen */ ! 83: ! 84: extern char *strcat(), *strcpy(); ! 85: extern FILE *popen(); ! 86: char *any(); ! 87: ! 88: main(argc, argv) ! 89: int argc; ! 90: char **argv; ! 91: { ! 92: char buf[BFSZ]; ! 93: register char *p; ! 94: register FILE *pipe; ! 95: register int state, pathcnt; ! 96: int t; ! 97: ! 98: if (argc > 1) ! 99: strcpy(to, argv[1]); ! 100: if (argc > 2) ! 101: strcpy(from, argv[2]); ! 102: #ifdef debug ! 103: printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n", ! 104: argv[0], argv[1], argv[2]); ! 105: #endif ! 106: state = SKIPPING; ! 107: while (fgets(buf, BFSZ, stdin) != NULL) { ! 108: t = type(buf) | state; ! 109: #ifdef debug ! 110: printf("%o\t%s", t, buf); ! 111: #endif ! 112: switch (t) { ! 113: ! 114: case FROM | SKIPPING: ! 115: frombreak(buf, from); ! 116: break; ! 117: ! 118: case FROM | READING: ! 119: fputs(buf, pipe); ! 120: break; ! 121: ! 122: case SUBJ | SKIPPING: ! 123: p = any(buf, " \t"); ! 124: if (p == NULL) ! 125: p = buf+8; ! 126: strcpy(subject, p+1); ! 127: subject[strlen(subject)-1] = 0; /* trim trailing \n */ ! 128: break; ! 129: ! 130: case SUBJ | READING: ! 131: fputs(buf, pipe); ! 132: break; ! 133: ! 134: case TO | SKIPPING: ! 135: if (to[0]) ! 136: break; /* already have one */ ! 137: p = any(buf, " \t"); ! 138: if (p == NULL) ! 139: p = buf; ! 140: strcpy(to, p+1); /* strip leading blank */ ! 141: to[strlen(to)-1] = 0; /* strip trailing \n */ ! 142: break; ! 143: ! 144: case TO | READING: ! 145: fputs(buf, pipe); ! 146: break; ! 147: ! 148: /* ! 149: * Kludge to compensate for messages without real headers ! 150: */ ! 151: case HEADER | SKIPPING: ! 152: break; ! 153: ! 154: case HEADER | READING: ! 155: fputs(buf, pipe); ! 156: break; ! 157: ! 158: case BLANK | SKIPPING: ! 159: state = READING; ! 160: findgroup(to, newsgroup); ! 161: sprintf(cmdbuf, "%s -D -t \"%s\" -n %s -f %s", INEWS, subject, newsgroup, from); ! 162: #ifdef debug ! 163: pipe = stdout; ! 164: printf("BLANK: %s\n", cmdbuf); ! 165: #else ! 166: pipe = popen(cmdbuf, "w"); ! 167: if (pipe == NULL) { ! 168: perror("recnews: popen failed"); ! 169: exit(1); ! 170: } ! 171: #endif ! 172: if (sender[0]) ! 173: fputs(sender, pipe); ! 174: break; ! 175: ! 176: case BLANK | READING: ! 177: fputs(buf, pipe); ! 178: break; ! 179: ! 180: case TEXT | SKIPPING: ! 181: findgroup(to, newsgroup); ! 182: state = READING; ! 183: if (subject[0] == 0) { ! 184: strcpy(subject, buf); ! 185: if (subject[strlen(subject)-1] == '\n') ! 186: subject[strlen(subject)-1] = '\0'; ! 187: } ! 188: sprintf(cmdbuf, "%s -D -t \"%s\" -n %s -f %s", INEWS, subject, newsgroup, from); ! 189: #ifdef debug ! 190: pipe = stdout; ! 191: printf("TEXT: %s\n", cmdbuf); ! 192: #else ! 193: pipe = popen(cmdbuf, "w"); ! 194: if (pipe == NULL) { ! 195: fprintf(stderr, "pipe failed\n"); ! 196: exit(1); ! 197: } ! 198: #endif ! 199: if (sender[0]) ! 200: fputs(sender, pipe); ! 201: break; ! 202: ! 203: case TEXT | READING: ! 204: fputs(buf, pipe); ! 205: break; ! 206: } ! 207: } ! 208: exit(0); ! 209: } ! 210: ! 211: #define itsa(kind) {lastcomma=thiscomma; lasthdr=(kind!=TEXT); return kind;} ! 212: type(p) ! 213: register char *p; ! 214: { ! 215: char *firstbl; ! 216: static char lasthdr=0; /* prev line was a header */ ! 217: static char lastcomma=0; /* prev line ended in a comma */ ! 218: int thiscomma; ! 219: ! 220: thiscomma = (p[strlen(p)-2] == ','); ! 221: if (*p == ' ' && lasthdr && lastcomma) ! 222: itsa(HEADER); /* continuation line */ ! 223: firstbl = any(p, " \t"); ! 224: while (*p == ' ' || *p == '?' || *p == '\t') ! 225: ++p; ! 226: ! 227: if (*p == '\n' || *p == 0) ! 228: itsa(BLANK); ! 229: if (strncmp(p, ">From", 5) == 0 || ! 230: strncmp(p, "From", 4) == 0) ! 231: itsa (FROM); ! 232: if (strncmp(p, "Subj", 4)==0 || ! 233: strncmp(p, "Re:", 3)==0 || ! 234: strncmp(p, "re:", 3)==0) ! 235: itsa (SUBJ); ! 236: if (strncmp(p, "To", 2)==0) ! 237: itsa(TO); ! 238: if (strncmp(p, "\1\1\1\1", 4)==0) ! 239: itsa(EOM); ! 240: if (firstbl && firstbl[-1] == ':' && isalpha(*p)) ! 241: itsa(HEADER); ! 242: itsa(TEXT); ! 243: } ! 244: ! 245: /* ! 246: * Figure out who a message is from. ! 247: */ ! 248: frombreak(buf, fbuf) ! 249: register char *buf, *fbuf; ! 250: { ! 251: register char *p; ! 252: char wordfrom[BFSZ], uname[BFSZ], at[BFSZ], site[BFSZ]; ! 253: ! 254: if (fbuf[0]) { /* we already know who it's from */ ! 255: if (sender[0] == 0) { ! 256: #ifdef debug ! 257: printf("sender set to: %s", buf); ! 258: #endif ! 259: strcpy(sender, buf); ! 260: } ! 261: return; ! 262: } ! 263: /* break the line into tokens. */ ! 264: sscanf(buf, "%s %s %s %s", wordfrom, uname, at, site); ! 265: if (isat(at)) ! 266: /* ! 267: * Some arpanet mail comes from "joe at mit-dms" ! 268: * instead of "joe@mit-dms", so handle it here. ! 269: */ ! 270: sprintf(fbuf, "%s@%s", uname, site); ! 271: else ! 272: strcpy(fbuf, uname); ! 273: } ! 274: ! 275: isat(str) ! 276: char *str; ! 277: { ! 278: if (strcmp(str, "@")==0) return TRUE; ! 279: if (strcmp(str, "at")==0) return TRUE; ! 280: if (strcmp(str, "AT")==0) return TRUE; ! 281: return FALSE; ! 282: } ! 283: ! 284: findgroup(to, group) ! 285: char *to; ! 286: char *group; ! 287: { ! 288: #ifdef debug ! 289: printf("findgroup(%s)\n", to); ! 290: #endif ! 291: #ifdef fussy ! 292: /* ! 293: * Default unknown "to" fields to "general". This gives you ! 294: * tight control over which newsgroups exist. ! 295: */ ! 296: if (strcmp(to, "msgs")==0) ! 297: strcpy(group, "msgs"); ! 298: else if (strcmp(to, "allmsgs")==0) ! 299: strcpy(group, "NET.allmsgs"); ! 300: else if (strcmp(to, "csmsgs")==0) ! 301: strcpy(group, "NET.csmsgs"); ! 302: else ! 303: strcpy(group, "general"); ! 304: #else ! 305: /* ! 306: * Allow any newsgroup. This way you don't have to recompile ! 307: * recnews everytime you add a newsgroup. ! 308: */ ! 309: strcpy(group, to); ! 310: #endif ! 311: } ! 312: ! 313: /* ! 314: * Return the ptr in sp at which a character in sq appears; ! 315: * NULL if not found ! 316: * ! 317: */ ! 318: ! 319: char * ! 320: any(sp, sq) ! 321: char *sp, *sq; ! 322: { ! 323: register c1, c2; ! 324: register char *q; ! 325: ! 326: while (c1 = *sp++) { ! 327: q = sq; ! 328: while (c2 = *q++) ! 329: if (c1 == c2) ! 330: return(--sp); ! 331: } ! 332: return(NULL); ! 333: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.