Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / mhmail.c
1 /* mhmail.c - simple mail program */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: mhmail.c,v 1.9 1993/08/20 15:51:29 jromine Exp $";
4 #endif  /* lint */
5
6 #include "../h/mh.h"
7 #include <stdio.h>
8 #include <signal.h>
9 #ifdef LOCALE
10 #include        <locale.h>
11 #endif
12
13 /* \f */
14
15 static struct swit switches[] = {
16 #define BODYSW  0
17     "body text", 0,
18
19 #define CCSW    1
20     "cc addrs ...", 0,
21
22 #define FROMSW  2
23     "from addr", 0,
24
25 #define SUBJSW  3
26     "subject text", 0,
27
28 #define HELPSW  4
29     "help", 4,
30
31 #define RESNDSW 5
32     "resent", -6,
33 #define QUEUESW 6
34     "queued", -6,
35
36     NULL, 0
37 };
38
39 /* \f */
40
41 static TYPESIG  intrser ();
42
43
44 static char tmpfil[BUFSIZ];
45
46 /* \f */
47
48 /* ARGSUSED */
49
50 main (argc, argv)
51 int     argc;
52 char   *argv[];
53 {
54     int     child_id,
55             status,
56             i,
57             iscc = 0,
58             nvec,
59             queued = 0,
60             resent = 0,
61             somebody;
62     char   *cp,
63            *tolist = NULL,
64            *cclist = NULL,
65            *subject = NULL,
66            *from = NULL,
67            *body = NULL,
68           **argp = argv + 1,
69             buf[100],
70            *vec[5];
71     FILE * out;
72
73 #ifdef LOCALE
74         setlocale(LC_ALL, "");
75 #endif
76     invo_name = r1bindex (argv[0], '/');
77     m_foil (NULLCP);
78
79     if (argc == 1) {
80         execlp (incproc, r1bindex (incproc, '/'), NULLCP);
81         adios (incproc, "unable to exec");
82     }
83
84 /* \f */
85
86     while (cp = *argp++) {
87         if (*cp == '-')
88             switch (smatch (++cp, switches)) {
89                 case AMBIGSW: 
90                     ambigsw (cp, switches);
91                     done (1);
92
93                 case UNKWNSW: 
94                     adios (NULLCP, "-%s unknown", cp);
95
96                 case HELPSW: 
97                     (void) sprintf (buf, "%s [addrs ... [switches]]",
98                             invo_name);
99                     help (buf, switches);
100                     done (1);
101
102                 case FROMSW: 
103                     if (!(from = *argp++) || *from == '-')
104                         adios (NULLCP, "missing argument to %s", argp[-2]);
105                     continue;
106
107                 case BODYSW: 
108                     if (!(body = *argp++) || *body == '-')
109                         adios (NULLCP, "missing argument to %s", argp[-2]);
110                     continue;
111
112                 case CCSW: 
113                     iscc++;
114                     continue;
115
116                 case SUBJSW: 
117                     if (!(subject = *argp++) || *subject == '-')
118                         adios (NULLCP, "missing argument to %s", argp[-2]);
119                     continue;
120
121                 case RESNDSW: 
122                     resent++;
123                     continue;
124
125                 case QUEUESW: 
126                     queued++;
127                     continue;
128             }
129         if (iscc)
130             cclist = cclist ? add (cp, add (", ", cclist)) : getcpy (cp);
131         else
132             tolist = tolist ? add (cp, add (", ", tolist)) : getcpy (cp);
133     }
134
135 /* \f */
136
137     if (tolist == NULL)
138         adios (NULLCP, "usage: %s addrs ... [switches]", invo_name);
139     (void) strcpy (tmpfil, m_tmpfil (invo_name));
140     if ((out = fopen (tmpfil, "w")) == NULL)
141         adios (tmpfil, "unable to write");
142     (void) chmod (tmpfil, 0600);
143
144     setsig (SIGINT, intrser);
145
146     fprintf (out, "%sTo: %s\n", resent ? "Resent-" : "", tolist);
147     if (cclist)
148         fprintf (out, "%scc: %s\n", resent ? "Resent-" : "", cclist);
149     if (subject)
150         fprintf (out, "%sSubject: %s\n", resent ? "Resent-" : "", subject);
151     if (from)
152         fprintf (out, "%sFrom: %s\n", resent ? "Resent-" : "", from);
153     if (!resent)
154         (void) fputs ("\n", out);
155
156     if (body) {
157         fprintf (out, "%s", body);
158         if (*body && *(body + strlen (body) - 1) != '\n')
159             fputs ("\n", out);
160     }
161     else {
162         for (somebody = 0;
163                 (i = fread (buf, sizeof *buf, sizeof buf, stdin)) > 0;
164                 somebody++)
165             if (fwrite (buf, sizeof *buf, i, out) != i)
166                 adios (tmpfil, "error writing");
167         if (!somebody) {
168             (void) unlink (tmpfil);
169             done (1);
170         }
171     }
172     (void) fclose (out);
173
174 /* \f */
175
176     nvec = 0;
177     vec[nvec++] = r1bindex (postproc, '/');
178     vec[nvec++] = tmpfil;
179     if (resent)
180         vec[nvec++] = "-dist";
181     if (queued)
182         vec[nvec++] = "-queued";
183     vec[nvec] = 0;
184
185     for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
186         sleep (5);
187     switch (child_id) {
188         case NOTOK:             /* report failure and then send it */
189             admonish (NULLCP, "unable to fork");
190
191         case OK:
192             execvp (postproc, vec);
193             fprintf (stderr, "unable to exec ");
194             perror (postproc);
195             _exit (-1);
196
197         default: 
198             if (status = pidXwait (child_id, postproc)) {
199                 fprintf (stderr, "Letter saved in dead.letter\n");
200                 execl ("/bin/mv", "mv", tmpfil, "dead.letter", NULLCP);
201                 execl ("/usr/bin/mv", "mv", tmpfil, "dead.letter", NULLCP);
202                 perror ("mv");
203                 _exit (-1);
204             }
205
206             (void) unlink (tmpfil);
207             done (status ? 1 : 0);
208     }
209 }
210
211 /* \f */
212
213 /* ARGSUSED */
214
215 static TYPESIG  intrser (i)
216 int     i;
217 {
218 #ifndef BSD42
219     if (i)
220         (void) signal (i, SIG_IGN);
221 #endif  /* BSD42 */
222
223     (void) unlink (tmpfil);
224     done (i != 0 ? 1 : 0);
225 }