]> diplodocus.org Git - nmh/blob - docs/historical/mh-jun-1982/Extras/sndmsg.c
Updated documentation and comments about sendmail/pipe.
[nmh] / docs / historical / mh-jun-1982 / Extras / sndmsg.c
1 #ifdef COMMENT
2 Proprietary Rand Corporation, 1981.
3 Further distribution of this software
4 subject to the terms of the Rand
5 license agreement.
6 #endif
7
8 #include "mh.h";
9 #include "/rnd/borden/h/iobuf.h"
10 #include "/rnd/borden/h/stat.h"
11
12 /*#define DEBUG 1 /* Comment out normally */
13
14 /* Include a -msgid switch to .mh_profile to cause a
15 * Message-Id component to be added to outgoing mail.
16 */
17
18 char *anoyes[]; /* Std no/yes gans array */
19 struct swit switches[] {
20 "debug", -1, /* 0 */
21 "format", 0, /* 1 */
22 "noformat", 0, /* 2 */
23 "msgid", 0, /* 3 */
24 "nomsgid", 0, /* 4 */
25 "verbose", 0, /* 5 */
26 "noverbose", 0, /* 6 */
27 "help", 4, /* 7 */
28 0, 0
29 };
30 struct iobuf in, pin, pout, fout, fccout;
31 int format 1; /* re-formatting is the default */
32
33 char *logn, *parptr, *nmsg, fccfile[256];
34
35 main(argc, argv)
36 char *argv[];
37 {
38 int debug;
39 register char *cp, *msg;
40 register int state;
41 char *to, *cc, *bcc, *dist_to, *dist_cc, *dist_bcc;
42 char *tolist, *cclist, *adrlist, *sender, *fcc, *dist_fcc;
43 char name[NAMESZ], field[512];
44 int specfld, dist, fcconly;
45 int from, loc, net, verbose, msgid;
46 int toseen, ccseen;
47 char *ap;
48 char *arguments[50], **argp;
49
50 fout.b_fildes = dup(1);
51 msgid = from = loc = net = to = cc = bcc = dist = fcc = dist_fcc =
52 dist_to = dist_cc = dist_bcc = fcconly = debug =
53 toseen = ccseen = 0;
54 state = FLD;
55 msg = 0;
56 copyip(argv+1, arguments);
57 argp = arguments;
58 while(cp = *argp++) {
59 if(*cp == '-')
60 switch(smatch(++cp, switches)) {
61 case -2:ambigsw(cp, switches); /* ambiguous */
62 goto leave;
63 /* unknown */
64 case -1:printf("sndmsg: -%s unknown\n", cp);
65 goto leave;
66 case 0: verbose++; debug++; continue; /* -debug */
67 case 1: format = 1; continue; /* -format */
68 case 2: format = 0; continue; /* -noformat */
69 case 3: msgid = 1; continue; /* -msgid */
70 case 4: msgid = 0; continue; /* -nomsgid */
71 case 5: loc = 1; net = 1; continue; /* -verbose */
72 case 6: loc = 0; net = 0; continue; /* -noverbose */
73 case 7: help("sndmsg [file] [switches]",
74 switches);
75 goto leave;
76 }
77 if(msg) {
78 printf("Only one message at a time!\n");
79 goto leave;
80 } else
81 msg = cp;
82 }
83 if(!msg) {
84 printf("No Message specified.\n");
85 goto leave;
86 }
87 if(fopen(msg, &in) < 0) {
88 printf("Can't open \"%s\" for reading.\n", msg);
89 goto leave;
90 }
91
92 state = FLD;
93
94 for(;;)
95 switch(state = m_getfld(state, name, field, sizeof field, &in)) {
96
97 case FLD:
98 case FLDEOF:
99 case FLDPLUS:
100 if(!dist && uleq(name, "to"))
101 to = add(field, to);
102 else if(!dist && uleq(name, "cc"))
103 cc = add(field, cc);
104 else if(!dist && uleq(name, "bcc"))
105 bcc = add(field, bcc);
106 else if(!dist && uleq(name, "fcc"))
107 fcc = add(field, fcc);
108 else if(uleq(name, "distribute-to"))
109 { dist++; /* use presence of field as flag */
110 dist_to = add(field, dist_to);
111 }
112 else if(uleq(name, "distribute-cc"))
113 dist_cc = add(field, dist_cc);
114 else if(uleq(name, "distribute-bcc"))
115 dist_bcc = add(field, dist_bcc);
116 else if(uleq(name, "distribute-fcc"))
117 dist_fcc = add(field, dist_fcc);
118 else if(uleq(name, "from"))
119 from++;
120
121 if(state == FLDEOF)
122 goto done;
123 continue;
124
125 case BODY:
126 case BODYEOF:
127 goto done;
128
129 default:
130 printf("getfld returned %d\n", state);
131 goto leave;
132 }
133
134 done:
135 if (dist)
136 { to = dist_to;
137 cc = dist_cc;
138 bcc = dist_bcc;
139 fcc = dist_fcc;
140 }
141 if (!(to || cc))
142 if(!fcc) {
143 printf("Message %s has no addresses!!\n", msg);
144 goto leave;
145 } else
146 fcconly++;
147 pin.b_fildes = dup(2);
148 pout.b_fildes = 3;
149
150 if(to)
151 if(parse(to, 'c'))
152 goto leave;
153 if(cc)
154 if(parse(cc, 'c'))
155 goto leave;
156 if(bcc)
157 if(parse(bcc, 'c'))
158 goto leave;
159
160 compress();
161 adrlist = parptr; parptr = 0;
162 if(verbose) {
163 printf("Address List:\n%s", adrlist);
164 flush();
165 }
166
167 if(to)
168 if(parse(to, 'r', dist ? "Distribute-To: " : "To: "))
169 goto leave;
170 tolist = parptr; parptr = 0;
171 if(cc)
172 if(parse(cc, 'r', dist ? "Distribute-cc: " : "cc: "))
173 goto leave;
174 cclist = parptr; parptr = 0;
175
176 if(verbose) {
177 if (tolist) printf(tolist);
178 if (cclist) printf(cclist);
179 flush();
180 }
181 if(fcc) {
182 if(*fcc == ' ')
183 fcc++;
184 for(cp = fcc; *cp && *cp != '\n'; cp++) ;
185 *cp = 0;
186 if(debug)
187 printf("fcc: \"%s\"\n", fcc); flush();
188 if((fccout.b_fildes = filemsg(fcc)) == -1)
189 goto leave;
190 }
191 copy("\n", copy((logn = getlogn(getruid())), field));
192 if(parse(field, 'r', dist ? "Distributed-By: " :
193 (from ? "Sender: ":"From: ")))
194 goto leave;
195 sender = parptr; parptr = 0;
196 seek(in.b_fildes, 0, 0);
197 if(debug)
198 pout.b_fildes = 1; /* Send msg to std output for debugging */
199 else if(fcconly)
200 pout.b_fildes = 0; /* Flush send output if only an fcc */
201 cputc('s', &pout);
202 if(loc)
203 cputc('l', &pout);
204 if(net)
205 cputc('n', &pout);
206 cputc('\n', &pout);
207 puts(logn, &pout);
208 cputc('\n', &pout);
209 puts(adrlist, &pout);
210 puts("!\n", &pout);
211 puts2(sender, &pout);
212 puts2(dist ? "Distribution-Date: " : "Date: ", &pout);
213 puts2(gd(), &pout);
214 if(msgid) {
215 puts2(dist ? "Distribution-ID: " : "Message-ID: ", &pout);
216 puts2(gmid(), &pout);
217 }
218 seek(in.b_fildes, 0, 0);
219 in.b_nleft = in.b_nextp = 0;
220
221 state = FLD;
222
223 for(;;)
224 switch(state = m_getfld(state, name, field, sizeof field, &in)) {
225
226 case FLD:
227 case FLDEOF:
228 case FLDPLUS:
229 specfld = 0;
230 if(format && uleq(name,dist ? "distribute-to":"to")) {
231 if(!toseen) {
232 toseen++;
233 specfld++;
234 if (tolist)
235 puts2(tolist,&pout);
236 }
237 } else if (format && uleq(name,dist ?"distribute-cc":"cc")) {
238 if(!ccseen) {
239 ccseen++;
240 specfld++;
241 if (cclist)
242 puts2(cclist,&pout);
243 }
244 } else if (uleq(name,dist ? "distribute-bcc" : "bcc") ||
245 uleq(name,dist ? "distributed-by" : "sender") ||
246 uleq(name,dist ? "distribution-date" : "date") ||
247 uleq(name,dist ? "distribution-id" : "message-id") ||
248 uleq(name,dist ? "distribution-fcc" : "fcc")) {
249 specfld++; /* Ignore these if present */
250 } else {
251 puts2(name, &pout);
252 puts2(":", &pout);
253 puts2(field, &pout);
254 }
255 while(state == FLDPLUS) { /* read rest of field */
256 state=m_getfld(state, name, field, sizeof field, &in);
257 if (specfld) continue;
258 /* puts2(name, &pout);
259 puts2(":", &pout); */
260 puts2(field, &pout);
261 }
262 if(state == FLDEOF)
263 goto endit;
264 continue;
265 case BODY:
266 case BODYEOF:
267 if(field[0]) {
268 puts2("\n", &pout);
269 puts2(field, &pout);
270 }
271
272 while(state == BODY) {
273 state=m_getfld(state, name, field, sizeof field, &in);
274 puts2(field, &pout);
275 }
276 if(state == BODYEOF)
277 goto endit;
278 default:
279 printf("Error from getfld=%d\n", state);
280 goto leave;
281 }
282 endit:
283 if(pout.b_fildes)
284 fflush(&pout);
285 if(fccout.b_fildes) {
286 fflush(&fccout);
287 close(fccout.b_fildes);
288 }
289 if(!debug && !fcconly) {
290 write(3, "", 1);
291 if((state = read(2, &field, sizeof field)) != 1 || field[0]) {
292 printf("Error from adrparse.\n");
293 goto leave;
294 }
295 }
296 if(fccout.b_fildes)
297 printf("Filed: %s:%s\n", fcc, nmsg);
298 if(!debug) {
299 if(!fcconly) {
300 printf("Message %s sent.\n", msg);
301 flush();
302 }
303 cp = copy(msg, field);
304 /* for(cp = field; *cp++; ) ; */
305 cp[1] = 0;
306 do
307 *cp = cp[-1];
308 while(--cp >= field && *cp != '/');
309 *++cp = ','; /* New backup convention */
310 unlink(field);
311 if(link(msg, field) == -1 || unlink(msg) == -1)
312 printf("Can't rename %s to %s\n", msg, field);
313 }
314 m_update();
315 flush();
316 done(0);
317 leave:
318 printf("[Message NOT Delivered!]\n");
319 if(fccout.b_fildes)
320 unlink(fccfile);
321 m_update();
322 flush();
323 done(1);
324 }
325
326
327 parse(ptr, type, fldname)
328 char *fldname;
329 {
330 register int i;
331 register int l;
332 char line[128];
333
334 putc(type, &pout);
335 puts("\n", &pout);
336 puts(ptr, &pout);
337 fflush(&pout);
338 write(3, "", 1);
339 l = 0;
340
341 while((i = getl(&pin, line, (sizeof line) - 1)) > 0) {
342 line[i] = 0;
343 if(line[0] == 0)
344 { if (type == 'r')
345 { if (l > 0)
346 parptr = add("\n",parptr);
347 }
348 return(0);
349 }
350 else if(line[0] == '?') {
351 printf("Adrparse: %s", line);
352 return(1);
353 }
354 if (type == 'r')
355 { line[--i] = 0;
356 if (l+i > 70)
357 { parptr = add("\n",parptr);
358 l = 0;
359 }
360 if (l == 0)
361 { parptr = add(fldname,parptr);
362 l =+ length(fldname);
363 }
364 else
365 { parptr = add(", ",parptr);
366 l =+ 2;
367 }
368 parptr = add(line+1, parptr);
369 l =+ i;
370 }
371 else
372 parptr = add(line, parptr);
373 }
374 printf("Error from adrparse.\n");
375 return(1);
376 }
377
378 gmid()
379 {
380 static char bufmid[128];
381 long now;
382 register char *cp, *c2;
383 register int *ip;
384
385 cp = bufmid;
386 *cp++ = '<';
387 cp = copy(locv(0, getruid()), cp);
388 *cp++ = '.';
389 time(&now);
390 cp = copy(locv(now), cp);
391 cp = copy("@Rand-Unix>\n", cp);
392 *cp = 0;
393 return(bufmid);
394 }
395
396 #ifdef COMMENT
397 gmid()
398 {
399 static char bufmid[128];
400 long now;
401 register char *cp, *c2;
402
403 cp = bufmid;
404 cp = copy("<[Rand-Unix]", cp);
405 time(&now);
406 c2 = cdate(&now);
407 c2[9] = ' ';
408 c2[18] = 0;
409 cp = copy(c2, cp);
410 *cp++ = '.';
411 cp = copy(logn, cp);
412 *cp++ = '>';
413 *cp++ = '\n';
414 *cp = 0;
415 return(bufmid);
416 }
417 #endif
418
419 gd()
420 {
421 register char *t, *p;
422 register int *i;
423 static bufgd[32];
424 extern char *tzname[];
425 long now;
426
427 time(&now);
428 t = ctime(&now);
429 p = bufgd;
430
431 *p++ = t[8];
432 *p++ = t[9];
433 *p++ = ' ';
434 *p++ = t[4];
435 *p++ = t[5];
436 *p++ = t[6];
437 *p++ = ' ';
438 *p++ = t[20];
439 *p++ = t[21];
440 *p++ = t[22];
441 *p++ = t[23];
442 *p++ = ' ';
443 *p++ = 'a';
444 *p++ = 't';
445 *p++ = ' ';
446 *p++ = t[11];
447 *p++ = t[12];
448 *p++ = t[14];
449 *p++ = t[15];
450 *p++ = '-';
451 i = localtime(&now);
452 t = tzname[i[8]];
453 *p++ = *t++;
454 *p++ = *t++;
455 *p++ = *t++;
456 *p++ = '\n';
457 *p++ = 0;
458 return(bufgd);
459 }
460
461
462 getl(iob, buf, size)
463 {
464 register char *cp;
465 register int cnt, c;
466
467 cp = buf; cnt = size;
468
469 while((c = getc(iob)) >= 0) {
470 *cp++ = c;
471 --cnt;
472 if(c == 0 || c == '\n' || cnt == 0)
473 break;
474 }
475 return(size - cnt);
476 }
477
478
479 compress()
480 {
481 register char *f1, *f2, *f3;
482
483 #ifdef DEBUG
484 printf("compress:\n%s-----\n", parptr);
485 #endif
486 for(f1 = parptr; *f1; ) {
487 for(f2 = f1; *f2++ != '\n'; ) ;
488 while(*f2) {
489 if(eqqq(f1, f2)) {
490 for(f3 = f2; *f3++ != '\n'; ) ;
491 copy(f3, f2);
492 } else
493 while(*f2++ != '\n') ;
494 }
495 while(*f1++ != '\n') ;
496 }
497 }
498
499
500 eqqq(s1, s2)
501 {
502 register char *c1, *c2;
503
504 c1 = s1; c2 = s2;
505 while(*c1 != '\n' && *c2 != '\n')
506 if((*c1++|040) != (*c2++|040))
507 return(0);
508 return((*c1|040) == (*c2|040));
509 }
510
511
512 filemsg(folder)
513 char *folder;
514 {
515 register int i;
516 register char *fp;
517 struct inode stbuf;
518 struct msgs *mp;
519
520 fp = m_maildir(folder);
521 if(stat(fp, &stbuf) < 0) {
522 nmsg = concat("Create folder \"",
523 fp, "\"? ", 0);
524 if(!gans(nmsg, anoyes))
525 return(-1);
526 if(!makedir(fp)) {
527 printf("Can't create folder.\n");
528 return(-1);
529 }
530 }
531 if(chdir(fp) < 0) {
532 perror(concat("Can't chdir to ", fp, 0));
533 return(-1);
534 }
535 if(!(mp = m_gmsg())) {
536 printf("Can't read folder %s\n", folder);
537 return(-1);
538 }
539 nmsg = m_name(mp->hghmsg + 1);
540 copy(nmsg, copy("/", copy(m_maildir(fp), fccfile)));
541 if((i = creat(fccfile, m_gmprot())) == -1)
542 printf("Can't create %s\n", fccfile);
543 return(i);
544 }
545
546
547 puts2(str, iob)
548 {
549 puts(str, &fccout);
550 puts(str, i