|
|
1.1 root 1: /*
2: * recnews [to newsgroup] [from user] [approved by]
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: * in-gamemasters: "|/usr/lib/news/recnews mail.gamemasters '' news"
25: *
26: * Recnews is primarily useful in remote places on the usenet which collect
27: * mail from mailing lists and funnel them into the network. It is also
28: * useful if you like to send mail to some user instead of invoking
29: * inews -t .. -n .. when you want to submit an article. (Many mailers give
30: * you nice facilities like editing the message.) It is not, however,
31: * essential to use recnews to be able to join usenet.
32: *
33: * WARNING: recnews disables the "recording" check - it has to because
34: * by the time inews is run, it's in the background and too late to
35: * ask permission. If you depend heavily on recordings you probably
36: * should not allow recnews (and thus the mail interface) to be used.
37: *
38: * 1) We leave the from line alone. Just escape the double quotes, but let the
39: * mailer do the rest.
40: * 2) We give precedence to "From:" over "From " or ">From " in determining
41: * who the article is really from.
42: * Modifications by rad@tek
43: *
44: * [email protected]: add third argument to cause inews to be invoked with -a,
45: * for use with local groups for mailing lists with 2.11.
46: */
47:
48: #ifdef SCCSID
49: static char *SccsId = "@(#)recnews.c 2.14 10/15/87";
50: #endif /* SCCSID */
51:
52: #include "params.h"
53:
54: /*
55: * Note: we assume there are 2 kinds of hosts using recnews:
56: * Those that have delivermail (and hence this program will never
57: * have to deal with more than one message at a time) and those on the arpanet
58: * that do not (and hence all messages end with a sentinel). It is
59: * supposed that regular v7 type systems without delivermail or some
60: * other automatic forwarding device will just use rnews. We do
61: * not attempt to tell where a message ends on all systems due to the
62: * different conventions in effect. (This COULD be fixed, I suppose.)
63: */
64:
65: /*
66: * Kinds of lines in a message.
67: */
68: #define FROM 001 /* From line */
69: #define SUBJ 002 /* Subject */
70: #define TO 003 /* To (newgroup based on this) */
71: #define BLANK 004 /* blank line */
72: #define EOM 005 /* End of message (4 ctrl A's) */
73: #define HEADER 006 /* any unrecognized header */
74: #define TEXT 007 /* anything unrecognized */
75: #define INCLUSIVE 010 /* newsgroup is already in header */
76:
77: /*
78: * Possible states program can be in.
79: */
80: #define SKIPPING 0100 /* In header of message */
81: #define READING 0200 /* In body of message */
82:
83: #define BFSZ 250
84:
85: #define EOT '\004'
86:
87: char from[BFSZ]; /* mailing address for replies */
88: char sender[BFSZ]; /* mailing address of author, if different */
89: char to[BFSZ]; /* Destination of mail (msgs, etc) */
90: char subject[BFSZ]; /* subject of message */
91: char newsgroup[BFSZ]; /* newsgroups of message */
92: char approved[BFSZ]; /* Approved: */
93: int fromset; /* from passed on command line */
94: char cmdbuf[BFSZ]; /* command to popen */
95:
96: extern char *strcat(), *strcpy(), *index();
97: extern FILE *popen();
98: char *any();
99:
100: main(argc, argv)
101: int argc;
102: char **argv;
103: {
104: char buf[BFSZ], inews[BFSZ];
105: register char *p, *q;
106: register FILE *pipe = NULL;
107: register int state;
108:
109: /* build inews command */
110: #ifdef LOGDIR
111: sprintf(inews, "%s/%s/%s", logdir(HOME), LIBDIR, "inews");
112: #else
113: sprintf(inews, "%s/%s", LIBDIR, "inews");
114: #endif
115:
116: if (argc > 1)
117: strcpy(to, argv[1]);
118: if (argc > 2)
119: strcpy(from, argv[2]);
120: if (argc > 3 && *argv[3]) {
121: sprintf(approved,"-a %s", argv[3]);
122: }
123:
124: /*
125: * Flag that we know who message is from to avoid trying to
126: * decipher the From line.
127: */
128: if (argc > 2 && (argv[2][0] != '\0'))
129: fromset++;
130:
131: #ifdef debug
132: printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n",
133: argv[0], argv[1], argv[2]);
134: #endif
135: state = SKIPPING;
136: while (fgets(buf, BFSZ, stdin) != NULL) {
137: if (state == READING) {
138: fputs(buf,pipe);
139: continue;
140: }
141: switch (type(buf)) {
142:
143: case FROM:
144: frombreak(buf, from);
145: break;
146:
147: case SUBJ:
148: p = any(buf, " \t");
149: if (p == NULL)
150: p = buf + 8;
151: q = subject;
152: while (*++p) {
153: if (*p == '"')
154: *q++ = '\\';
155: *q++ = *p;
156: }
157: q[-1] = '\0';
158: break;
159:
160: case TO:
161: if (to[0])
162: break; /* already have one */
163: p = any(buf, " \t");
164: if (p == NULL)
165: p = buf + 3;
166: q = to;
167: while (*++p) {
168: if (*p == '"')
169: *q++ = '\\';
170: *q++ = *p;
171: }
172: q[-1] = '\0';
173: break;
174:
175: case INCLUSIVE:
176: sprintf(cmdbuf,"exec %s -p", inews);
177: pipe = popen(cmdbuf,"w");
178: if (pipe == NULL){
179: perror("recnews: open failed");
180: exit(1);
181: }
182: state = READING;
183: fputs(buf,pipe);
184: break;
185:
186: /*
187: * Kludge to compensate for messages without real headers
188: */
189: case HEADER:
190: break;
191:
192: case BLANK:
193: state = READING;
194: strcpy(newsgroup, to);
195: sprintf(cmdbuf,
196: "exec %s -t \"%s\" -n \"%s\" -f \"%s\" %s",
197: inews, *subject ? subject : "(none)",
198: newsgroup, from, *approved ? approved : 0);
199: #ifdef debug
200: pipe = stdout;
201: printf("BLANK: %s\n", cmdbuf);
202: #else
203: pipe = popen(cmdbuf, "w");
204: if (pipe == NULL) {
205: perror("recnews: popen failed");
206: exit(1);
207: }
208: #endif
209: if (sender[0]) {
210: fputs(sender, pipe);
211: putc('\n', pipe);
212: }
213: break;
214:
215: case TEXT:
216: strcpy(newsgroup, to);
217: state = READING;
218: if (subject[0] == 0) {
219: strcpy(subject, buf);
220: if (subject[strlen(subject)-1] == '\n')
221: subject[strlen(subject)-1] = '\0';
222: }
223: sprintf(cmdbuf,
224: "exec \"%s\" -t \"%s\" -n \"%s\" -f \"%s\" %s",
225: inews, subject, newsgroup, from,
226: *approved ? approved : 0);
227: #ifdef debug
228: pipe = stdout;
229: printf("TEXT: %s\n", cmdbuf);
230: #else
231: pipe = popen(cmdbuf, "w");
232: if (pipe == NULL) {
233: perror("pipe failed");
234: exit(1);
235: }
236: #endif
237: if (sender[0]){
238: fputs(sender, pipe);
239: putc('\n',pipe);
240: }
241: break;
242: }
243: }
244: exit(0);
245: }
246:
247: type(p)
248: register char *p;
249: {
250: char *firstbl;
251: static char lasthdr = 1; /* prev line was a header */
252:
253: if ((*p == ' ' || *p == '\t') && lasthdr)
254: return HEADER; /* continuation line */
255: firstbl = any(p, " \t");
256: while (*p == ' ' || *p == '?' || *p == '\t')
257: ++p;
258:
259: if (*p == '\n' || *p == 0)
260: return BLANK;
261: if (STRNCMP(p, ">From", 5) == 0 || STRNCMP(p, "From", 4) == 0)
262: return FROM;
263: if (STRNCMP(p, "Subj", 4)==0 || STRNCMP(p, "Re:", 3)==0 ||
264: STRNCMP(p, "re:", 3)==0)
265: return SUBJ;
266: if (STRNCMP(p, "To", 2)==0)
267: return TO;
268: if (STRNCMP(p, "\1\1\1\1", 4)==0)
269: return EOM;
270: if (firstbl && firstbl[-1] == ':' && isalpha(*p))
271: return HEADER;
272: lasthdr = 0;
273: return TEXT;
274: }
275:
276: /*
277: * Figure out who a message is from.
278: */
279: frombreak(buf, fbuf)
280: register char *buf, *fbuf;
281: {
282: register char *p, *q;
283: if (fbuf[0] && fromset) { /* we already know who it's from */
284: if (sender[0] == 0 || buf[4] == ':') {
285: #ifdef debug
286: printf("sender set to: %s", buf);
287: #endif
288: strcpy(sender, buf);
289: }
290: return;
291: }
292: /*
293: * Leave fancy Froms alone - this parsing is done by mail
294: * Just quote the double quotes to prevent interpetation
295: * by the shell.
296: * rad@tek
297: */
298: p = any(buf, " \t");
299: if (p==NULL)
300: p = buf + 4;
301: q = fbuf;
302: while (*++p) {
303: if (*p == '"')
304: *q++ = '\\';
305: *q++ = *p;
306: }
307: q[-1] = '\0';
308: if ((p=index(fbuf,'\n')) != NULL)
309: *p = '\0';
310: if (buf[4] == ':')
311: fromset++;
312: }
313:
314: /*
315: * Return the ptr in sp at which a character in sq appears;
316: * NULL if not found
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.