]>
diplodocus.org Git - nmh/blob - docs/historical/SRI-NOSC/send.c
5 #define DEBUG 1 /* Comment out normally */
10 /* Include a -msgid switch to .mh_defs to cause a
11 * Message-Id component to be added to outgoing mail.
14 char *anoyes
[], /* Std no/yes gans array */
16 locname
[], /* local host name */
17 sbmitloc
[], /* location (pathname) of submit process */
18 sbmitnam
[]; /* name of submit process */
19 struct swit switches
[]
24 "noformat", 0, /* 3 */
27 "verbose", 1, /* 6 *//* DBG dhc */
28 "noverbose", 0, /* 7 */
38 int format
0; /* re-formatting is the default */
83 fout
.b_fildes
= dup (1);
84 msgid
= from
= loc
= net
= to
= cc
= bcc
= dist
= fcc
= dist_fcc
=
85 dist_to
= dist_cc
= dist_bcc
= fcconly
= debug
= 0;
87 loc
= net
= 1; /* DBG during testing of new submit */
96 copyip (argv
+ 1, arguments
);
101 switch (smatch (++cp
, switches
))
104 ambigsw (cp
, switches
);
106 leave ("Illegal switch setting: \"%s\"", --cp
);
109 leave ("-%s unknown", cp
);
113 continue; /* -debug */
115 copy (m_maildir (draft
), msg
);
116 continue; /* -draft */
118 /* disabled for now format = 1; */
119 continue; /* -format */
122 continue; /* -noformat */
125 continue; /* -msgid */
128 continue; /* -nomsgid */
132 continue; /* -verbose */
136 continue; /* -noverbose */
138 help (concat( inp
, " [file] [switches]", 0),
143 leave ("Only one message at a time!");
149 copy (m_maildir (draft
), msg
);
150 if (stat (msg
, &field
) == -1)
152 printf ("Draft file: %s doesn't exist.\n", msg
);
156 /* cp = concat ("Use \"", msg, "\"? ", 0);
157 if (!gans (cp, anoyes))
160 if (fopen (msg
, &in
) < 0)
161 leave ("Can't open \"%s\" for reading.", msg
);
166 printf ("Message being processed...\n");
169 switch (state
= m_getfld (state
, name
, field
, sizeof field
, &in
))
175 if (!dist
&& field
[0] != 'n' && uleq (name
, "to"))
176 to
= adrlist
= add (field
, adrlist
);
178 if (!dist
&& field
[0] != 'n' && uleq (name
, "cc"))
179 cc
= adrlist
= add (field
, adrlist
);
181 if (!dist
&& uleq (name
, "bcc"))
182 adrlist
= add (field
, adrlist
);
184 if (!dist
&& uleq (name
, "fcc"))
185 fcc
= add (field
, fcc
);
187 if (field
[0] != 'n' && uleq (name
, "distribute-to"))
190 /* use presence of field as flag */
191 to
= adrlist
= add (field
, adrlist
);
194 if (field
[0] != 'n' && uleq (name
, "distribute-cc"))
195 cc
= adrlist
= add (field
, adrlist
);
197 if (field
[0] != 'n' && uleq (name
, "distribute-bcc"))
198 adrlist
= add (field
, adrlist
);
200 if (uleq (name
, "distribute-fcc"))
201 dist_fcc
= add (field
, dist_fcc
);
203 if (uleq (name
, "from"))
213 leave ("getfld returned %d", state
);
220 /* bcc = dist_bcc; */
225 leave ("Message %s has no addresses!!", msg
);
228 /****/ pin
.b_fildes
= dup (2);
229 /**** pout.b_fildes = 3;*/
231 /* if ((to && parse (to, 'c')) || */
232 /* (cc && parse (cc, 'c')) || */
233 /* (bcc && parse (bcc, 'c')) */
236 /* parptr = adrlist; */
238 /* adrlist = parptr; */
242 printf ("Address List:\n%s", adrlist
);
246 /* if (to && parse (to, 'r', dist ? "Distribute-To: " : "To: ")) */
248 /* tolist = parptr; */
250 /* if (cc && parse (cc, 'r', dist ? "Distribute-cc: " : "cc: ")) */
252 /* cclist = parptr; */
258 /* printf (tolist); */
260 /* printf (cclist); */
267 for (cp
= fcc
; *cp
&& *cp
!= '\n'; cp
++);
270 printf ("fcc: \"%s\"\n", fcc
);
272 if ((fccout
.b_fildes
= filemsg (fcc
)) == -1)
273 leave ("Problem beginning fcc message transfer");
276 /* if (parse (field, 'r', dist ? "Distributed-By: " */
277 /* : (from ? "Sender: " : "From: "))) */
280 sender
= add ((dist
) ? "Distributed-By: "
281 : (from
) ? "Sender: "
283 fieldptr
= copy ((logn
= getlogn (getruid ())), field
);
284 fieldptr
= copy (" at ", fieldptr
);
285 fieldptr
= copy ( locname
, fieldptr
);
286 copy ( "\n", fieldptr
);
287 sender
= add (field
, sender
);
289 seek (in
.b_fildes
, 0, 0);
290 /* *** INVOKE SUBMIT, AT LAST *** */
292 *ap
++ = '-'; /* indicate a switch sequence
294 /* *ap++ = 'd'; /*DBG have submit output messages */
295 *ap
++ = 'm'; /* mail, not screen-notice, yet
297 /* cputc ('s', &pout); */
298 /* ******* During initial testing, mail always sent immediately, ****** */
299 /* so that users can verify delivery... */
300 /* Can't trust new software these days... ****** */
303 *ap
++ = 'l'; /* send local mail now */
305 *ap
++ = 'n'; /* send net mail now */
307 *ap
++ = 'w'; /* user will watch deliveries */
309 /* ******* * * * * * * * * * * * * * * * * * * * * * * * * * * ****** */
311 *ap
++ = 'r'; /* return messages go to sender
316 pout
.b_fildes
= 1; /* Send msg to std output for debugging */
319 pout
.b_fildes
= 0; /* Flush send output if only an fcc */
322 if ((sbchild
= sbmitinit (arguments
, sbmitfd
)) == -1)
323 leave ("Unable to invoke submit");
324 pout
.b_fildes
= sbmitfd
[1];
327 puts (adrlist
, &pout
);
328 puts ("!\n", &pout
); /* end the address list */
329 puts2 (sender
, &pout
);
330 puts2 (dist
? "Distribution-Date: " : "Date: ", &pout
);
331 puts2 (cnvtdate (TIMREG
), &pout
);
335 puts2 (dist
? "Distribution-ID: " : "Message-ID: ", &pout
);
337 puts2 (cnvtdate (TIMJUL
), &pout
);
339 puts2 (locv (0, getpid ()), &pout
);
340 puts2 (" at ", &pout
);
341 puts2 (locname
, &pout
);
344 seek (in
.b_fildes
, 0, 0);
345 in
.b_nleft
= in
.b_nextp
= 0;
348 switch (state
= m_getfld (state
, name
, field
, sizeof field
, &in
))
354 if (format
&& uleq (name
, dist
? "distribute-to" : "to"))
358 puts2 (tolist
, &pout
);
361 if (format
&& uleq (name
, dist
? "distribute-cc" : "cc"))
365 puts2 (cclist
, &pout
);
368 if (uleq (name
, dist
? "distribute-bcc" : "bcc") ||
369 uleq (name
, dist
? "distributed-by" : "sender") ||
370 uleq (name
, dist
? "distribution-date" : "date") ||
371 uleq (name
, dist
? "distribution-id" : "message-id") ||
372 uleq (name
, dist
? "distribution-fcc" : "fcc"))
374 /* Ignore these if present */
379 puts2 (field
, &pout
);
381 while (state
== FLDPLUS
)
382 { /* read rest of field */
383 state
= m_getfld (state
, name
, field
, sizeof field
, &in
);
386 /* puts2(name, &pout); puts2(":", &pout); */
387 puts2 (field
, &pout
);
397 puts2 (field
, &pout
);
400 while (state
== BODY
)
402 state
= m_getfld (state
, name
, field
, sizeof field
, &in
);
403 puts2 (field
, &pout
);
405 if (state
== BODYEOF
)
408 leave ("Error from getfld=%d", state
);
414 if (fflush (&pout
) < 0 || errno
!= 0)
415 leave ("Problem writing data to Submit.");
419 close (fccout
.b_fildes
);
421 if (!debug
&& !fcconly
)
423 /* if ((state = read (2, &field, sizeof field)) != 1 || field[0]) */
426 printf ("Delivery being attempted...\n");
429 if (sbresp (&sbmitfd
) != 0)
430 leave ("Mail submission program ended abnormally");
433 printf ("Filed: %s:%s\n", fcc
, nmsg
);
438 printf ("Message processed.\n");
439 /* printf ("Message %s processed.\n", msg);*/
442 cp
= copy (msg
, field
);
443 /* for(cp = field; *cp++; ) ; */
447 while (--cp
>= field
&& *cp
!= '/');
448 *++cp
= ','; /* New backup convention */
450 if (link (msg
, field
) == -1 || unlink (msg
) == -1)
451 printf ("Can't rename %s to %s\n", msg
, field
);
459 leave (form
, a1
, a2
, a3
)
467 printf (form
, a1
, a2
, a3
);
472 printf ("[ Message NOT Delivered! ]\n");
480 parse (ptr
, type
, fldname
)
491 if (fflush (&pout
) < 0 || errno
!= 0)
492 leave ("Problem sending data to Submit.");
493 write (pout
.b_fildes
, "", 1);
496 while ((i
= getl (&pin
, line
, (sizeof line
) - 1)) > 0)
504 parptr
= add ("\n", parptr
);
511 printf ("Submit returned: %s", line
);
519 parptr
= add ("\n", parptr
);
524 parptr
= add (fldname
, parptr
);
525 l
=+ length (fldname
);
529 parptr
= add (", ", parptr
);
532 parptr
= add (line
+ 1, parptr
);
536 parptr
= add (line
, parptr
);
538 printf ("Error from Submit.\n");
543 int flag
; /* date format option value */
545 static char datbuf
[128];
556 i
= localtime (tvec
);
562 case TIMJUL
: /* Julian-oriented for msg-ids */
563 for (itoa (i
[5], p
); *p
; p
++);
565 for (itoa (i
[7], p
); *p
; p
++);
568 seconds
= i
[0] + (i
[1] * 60) + (seconds
* 3600);
569 litoa (seconds
, p
); /* seconds since midnight */
571 case TIMREG
: /* RFC 733 standard time string */
572 default: /* "Sat, 21 Jan 76 14:30-PDT" */
578 *p
++ = t
[8]; /* day of month */
581 *p
++ = t
[4]; /* month abbreviation eg: "JAN" */
585 *p
++ = t
[22]; /* year eg: "76" */
588 *p
++ = t
[11]; /* hours & minutes eg: "14:30" */
594 *p
++ = 'P'; /* time zone eg: "PDT" */
595 *p
++ = (i
[8]) ? 'D' : 'S';
604 getl (iob
, buf
, size
)
610 for (cp
= buf
, cnt
= size
; (c
= getc (iob
)) >= 0;)
634 printf ("compress:\n%s-----\n", parptr
);
636 for (f1
= parptr
; *f1
;)
638 for (f2
= f1
; *f2
++ != '\n';);
643 for (f3
= f2
; *f3
++ != '\n';);
647 while (*f2
++ != '\n');
649 while (*f1
++ != '\n');
660 while (*c1
!= '\n' && *c2
!= '\n')
673 fp
= m_maildir (folder
);
674 if (stat (fp
, &stbuf
) < 0)
676 /* nmsg = concat ("Create folder \"",
678 if (!gans (nmsg, anoyes))
682 printf ("Can't create folder.\n");
688 perror (concat ("Can't chdir to ", fp
, 0));
691 if (!(mp
= m_gmsg ()))
693 printf ("Can't read folder %s\n", folder
);
696 nmsg
= m_name (mp
-> hghmsg
+ 1);
697 copy (nmsg
, copy ("/", copy (m_maildir (fp
), fccfile
)));
698 if ((i
= creat (fccfile
, m_gmprot ())) == -1)
699 printf ("Can't create %s\n", fccfile
);
708 if (fflush (iob
) < 0 || errno
!= 0)
709 leave ("Problem writing out data");
711 /* subroutines to interface to submit */
713 #define CLOSEFD -1 /* if equals fdarray[i], close (i); */
714 #define PUREXEC 0 /* simply exec over current process */
715 #define FRKEXEC 1 /* run it in lower process */
716 #define SPNEXEC 2 /* separate new process from old */
717 #define FRKWAIT 1 /* wait for FRKEXEC to complete */
718 #define FRKPIGO 2 /* Parent's signals off during FRKWAIT */
719 #define FRKCIGO 4 /* Childs signals off before execl */
720 /*#define EXECR 8 ** Use execr, instead of execv */
735 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
736 -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
739 sbmitinit (args
, ioary
)
744 struct pstruct sbpout
;
749 if (pipe (&sbpout
) == -1)
751 regfdary
[0] = sbpout
.prd
;
752 regfdary
[1] = fout
.b_fildes
;
754 if ((sbmitid
= newpgml (FRKEXEC
, 0, regfdary
,
755 sbmitloc
, sbmitnam
, args
, 0)) == -1)
763 dbglog ("Ready to close");
765 ioary
[1] = sbpout
.pwrt
;
770 sbmitadr (name
, ioary
)
779 for (from
= name
, to
= linebuf
; *to
= *from
++; to
++);
780 for (from
= "\n"; *to
++ = *from
++;);
783 if (write (ioary
[1], linebuf
, tmp
) == -1)
786 return (sbresp (ioary
));
793 return (childend ());
796 newpgml (proctyp
, pgmflags
, fdarray
, pgm
, pgmparm
)
805 /* printf ("newpgml: calling newpgmv\n"); */
807 retval
= newpgmv (proctyp
, pgmflags
, fdarray
, pgm
, parmptr
);
811 newpgmv (proctyp
, pgmflags
, fdarray
, pgm
, pgmparm
)
824 if (proctyp
!= PUREXEC
)
826 /* printf ("This is a forking call.\n"); */
827 for (tried
= NUMTRY
; (childid
= fork ()) == -1 && tried
--; sleep (1));
830 /* printf ("Successful fork\n"); */
832 { /* parent process */
833 if (pgmflags
& FRKPIGO
)
834 { /* disable parent signals */
835 /* printf ("Parent to be
836 non-interruptible\n"); */
837 osig
[0] = signal (1, 1);
838 osig
[1] = signal (2, 1);
839 osig
[2] = signal (3, 1);
841 if ((proctyp
== FRKEXEC
) && (pgmflags
& FRKWAIT
))
843 /* printf ("Parent is to wait\n"); */
844 while ((tmp
= wait (&tmp2
)) != childid
&& tmp
!= -1);
845 /* printf ("Parent done waiting\n"); */
846 if (pgmflags
& FRKPIGO
)
856 if (proctyp
== SPNEXEC
)
857 { /* want it to be a spawn */
858 /* printf ("This is a spawn\n"); */
859 for (tried
= NUMTRY
; (tmp
= fork ()) < 0 && tried
--;
861 if (tmp
!= 0) /* split the grandparent from the */
862 exit (tmp
< 0 ? -2 : 0);
863 /* grandchild: kill middle proc */
867 { /* re-align fd array list */
868 fout
.b_fildes
= fdarray
[1];
869 for (tmp
= 0; tmp
< highfd
; tmp
++)
870 { /* first do the re-positions */
871 if (fdarray
[tmp
] != CLOSEFD
&& fdarray
[tmp
] != tmp
)
873 dbglog ("Closing %2d\n", tmp
);
876 while ((tmp2
= dup (fdarray
[tmp
])) < tmp
&& tmp2
!= -1);
877 dbglog ("Last dup'd %d into %d\n", fdarray
[tmp
], tmp2
);
879 /* did we get right fd? */
882 for (tmp
= 0; tmp
< highfd
; tmp
++)
883 if (fdarray
[tmp
] == CLOSEFD
)
885 dbglog ("Closing %2d\n", tmp
);
887 close (tmp
); /* get rid of unwanted ones */
892 if (pgmflags
& FRKCIGO
)
894 /* printf ("Child's interrupts to be
901 /* printf ("Execing %s\n", pgm); */
902 /* if (pgmflags & EXECR) */
903 /* execr (pgm, pgmparm); */
905 execv (pgm
, pgmparm
);
906 /* printf ("Exec not successful\n"); */
907 if (proctyp
== PUREXEC
)
910 printf ("Unable to exec \"%s\"\n", pgm
);
912 for (tmp
= 0; tmp
< 20 && pgmparm
[tmp
][0] != 0 ; tmp
++)
914 printf ("Parm %d = \"%s\"\n", tmp
, pgmparm
[tmp
]); flush ();
924 /* close (sbmitfd[0]); */
926 while ((tmp
= wait (&tmp2
)) != sbchild
&& tmp
!= -1);