Added -clobber switch to mhstore(1) [Bug #11160].
[mmh] / docs / historical / mh-6.8.5 / uip / send.c
1 /* send.c - send a composed message */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: send.c,v 1.14 1995/12/06 21:04:47 jromine Exp $";
4 #endif  /* lint */
5
6 #include "../h/mh.h"
7 #include <errno.h>
8 #include <stdio.h>
9 #include <signal.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #ifdef LOCALE
13 #include        <locale.h>
14 #endif
15
16 /* \f */
17
18 #ifndef TMA
19 #define TMAminc(a)      (a)
20 #else   /* TMA */
21 #define TMAminc(a)      0
22 #endif  /* TMA */
23
24 #ifdef  MIME
25 #define MIMEminc(a)     (a)
26 #else
27 #define MIMEminc(a)     0
28 #endif
29
30 static struct swit switches[] = {
31 #define ALIASW  0
32     "alias aliasfile", 0,
33
34 #define DEBUGSW 1
35     "debug", -5,
36
37 #define DRAFTSW 2
38     "draft", 0,
39
40 #define DFOLDSW 3
41     "draftfolder +folder", 6,
42 #define DMSGSW  4
43     "draftmessage msg", 6,
44 #define NDFLDSW 5
45     "nodraftfolder", 0,
46
47 #define ENCRSW  6
48     "encrypt", TMAminc (-7),
49 #define NENCRSW 7
50     "noencrypt", TMAminc (-9),
51
52 #define FILTSW  8
53     "filter filterfile", 0,
54 #define NFILTSW 9
55     "nofilter", 0,
56
57 #define FRMTSW  10
58     "format", 0,
59 #define NFRMTSW 11
60     "noformat", 0,
61
62 #define FORWSW  12
63     "forward", 0,
64 #define NFORWSW 13
65     "noforward", 0,
66
67 #define MIMESW  14
68     "mime", MIMEminc(-4),
69 #define NMIMESW 15
70     "nomime", MIMEminc(-6),
71
72 #define MSGDSW  16
73     "msgid", 0,
74 #define NMSGDSW 17
75     "nomsgid", 0,
76
77 #define PUSHSW  18
78     "push", 0,
79 #define NPUSHSW 19
80     "nopush", 0,
81
82 #define SPLITSW 20
83     "split seconds", MIMEminc(-5),
84
85 #define UNIQSW  21
86     "unique", -6,
87 #define NUNIQSW 22
88     "nounique", -8,
89
90 #define VERBSW  23
91     "verbose", 0,
92 #define NVERBSW 24
93     "noverbose", 0,
94
95 #define WATCSW  25
96     "watch", 0,
97 #define NWATCSW 26
98     "nowatch", 0,
99
100 #define WIDTHSW 27
101     "width columns", 0,
102
103 #define HELPSW  28
104     "help", 4,
105
106 #define MAILSW  29
107     "mail", -4,
108 #define SAMLSW  30
109     "saml", -4,
110 #define SENDSW  31
111     "send", -4,
112 #define SOMLSW  32
113     "soml", -4,
114
115 #define CLIESW  33
116     "client host", -6,
117 #define SERVSW  34
118     "server host", -6,
119 #define SNOOPSW 35
120     "snoop", -5,
121
122 #define QUEUESW 36
123     "queued", -6,
124
125 #define RECORSW 37
126     "record program", -6,
127 #define NRECOSW 38
128     "norecord", -8,
129
130     NULL, 0
131 };
132
133 static struct swit anyl[] = {
134 #define NOSW    0
135     "no", 0,
136 #define YESW    1
137     "yes", 0,
138 #define LISTDSW 2
139     "list", 0,
140
141     NULL, 0
142 };
143
144 /* \f */
145
146 extern int debugsw;             /* from sendsbr.c */
147 extern int forwsw;
148 extern int inplace;
149 extern int mime;
150 extern int pushsw;
151 extern int splitsw;
152 extern int unique;
153 extern int verbsw;
154
155 extern char *altmsg;            /*  .. */
156 extern char *annotext;
157 extern char *distfile;
158
159
160 extern int   errno;
161
162 /* \f */
163
164 /* ARGSUSED */
165
166 main (argc, argv)
167 int     argc;
168 char   *argv[];
169 {
170     int     msgp = 0,
171             distsw = 0,
172             vecp = 1,
173             isdf = 0,
174             msgnum,
175             status;
176     char   *cp,
177            *dfolder = NULL,
178            *maildir = NULL,
179             buf[100],
180           **ap,
181           **argp,
182            *arguments[MAXARGS],
183            *msgs[MAXARGS],
184            *vec[MAXARGS];
185     struct msgs *mp;
186     struct stat st;
187 #ifdef  UCI
188     FILE   *fp;
189 #endif  /* UCI */
190
191 #ifdef LOCALE
192         setlocale(LC_ALL, "");
193 #endif
194     invo_name = r1bindex (argv[0], '/');
195     if ((cp = m_find (invo_name)) != NULL) {
196         ap = brkstring (cp = getcpy (cp), " ", "\n");
197         ap = copyip (ap, arguments);
198     }
199     else
200         ap = arguments;
201     (void) copyip (argv + 1, ap);
202     argp = arguments;
203
204     vec[vecp++] = "-library";
205     vec[vecp++] = getcpy (m_maildir (""));
206
207 /* \f */
208
209     while (cp = *argp++) {
210         if (*cp == '-')
211             switch (smatch (++cp, switches)) {
212                 case AMBIGSW: 
213                     ambigsw (cp, switches);
214                     done (1);
215                 case UNKWNSW: 
216                     adios (NULLCP, "-%s unknown\n", cp);
217                 case HELPSW: 
218                     (void) sprintf (buf, "%s [file] [switches]", invo_name);
219                     help (buf, switches);
220                     done (1);   /* thanks, phyl */
221
222                 case DRAFTSW: 
223                     msgs[msgp++] = draft;
224                     continue;
225
226                 case DFOLDSW: 
227                     if (dfolder)
228                         adios (NULLCP, "only one draft folder at a time!");
229                     if (!(cp = *argp++) || *cp == '-')
230                         adios (NULLCP, "missing argument to %s", argp[-2]);
231                     dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
232                             *cp != '@' ? TFOLDER : TSUBCWF);
233                     continue;
234                 case DMSGSW: 
235                     if (!(cp = *argp++) || *cp == '-')
236                         adios (NULLCP, "missing argument to %s", argp[-2]);
237                     msgs[msgp++] = cp;
238                     continue;
239                 case NDFLDSW: 
240                     dfolder = NULL;
241                     isdf = NOTOK;
242                     continue;
243
244                 case PUSHSW: 
245                     pushsw++;
246                     continue;
247                 case NPUSHSW: 
248                     pushsw = 0;
249                     continue;
250
251                 case SPLITSW: 
252                     if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1)
253                         adios (NULLCP, "missing argument to %s", argp[-2]);
254                     continue;
255
256                 case UNIQSW: 
257                     unique++;
258                     continue;
259                 case NUNIQSW: 
260                     unique = 0;
261                     continue;
262
263                 case FORWSW:
264                     forwsw++;
265                     continue;
266                 case NFORWSW:
267                     forwsw = 0;
268                     continue;
269
270                 case VERBSW: 
271                     verbsw++;
272                     vec[vecp++] = --cp;
273                     continue;
274                 case NVERBSW:
275                     verbsw = 0;
276                     vec[vecp++] = --cp;
277                     continue;
278
279                 case MIMESW:
280 #ifdef  MIME
281                     mime++;
282                     vec[vecp++] = --cp;
283 #endif
284                     continue;
285                 case NMIMESW:
286 #ifdef  MIME
287                     mime = 0;
288                     vec[vecp++] = --cp;
289 #endif
290                     continue;
291
292                 case DEBUGSW: 
293                     debugsw++;  /* fall */
294                 case NFILTSW: 
295                 case FRMTSW: 
296                 case NFRMTSW: 
297                 case MSGDSW: 
298                 case NMSGDSW: 
299                 case WATCSW: 
300                 case NWATCSW: 
301                 case MAILSW: 
302                 case SAMLSW: 
303                 case SENDSW: 
304                 case SOMLSW: 
305                 case ENCRSW:
306                 case NENCRSW:
307                 case SNOOPSW: 
308                 case QUEUESW: 
309                 case NRECOSW: 
310                     vec[vecp++] = --cp;
311                     continue;
312
313                 case ALIASW: 
314                 case FILTSW: 
315                 case WIDTHSW: 
316                 case CLIESW: 
317                 case SERVSW: 
318                 case RECORSW: 
319                     vec[vecp++] = --cp;
320                     if (!(cp = *argp++) || *cp == '-')
321                         adios (NULLCP, "missing argument to %s", argp[-2]);
322                     vec[vecp++] = cp;
323                     continue;
324             }
325         else
326             msgs[msgp++] = cp;
327     }
328     if (cp = m_find ("Aliasfile")) {    /* allow Aliasfile: profile entry */
329         char *dp = NULL;
330
331         for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) {
332             vec[vecp++] = "-alias";
333             vec[vecp++] = *ap;
334         }
335     }
336
337 /* \f */
338
339     if (dfolder == NULL) {
340         if (msgp == 0) {
341 #ifdef  WHATNOW
342             if ((cp = getenv ("mhdraft")) && *cp) {
343                 msgs[msgp++] = cp;
344                 goto go_to_it;
345             }
346 #endif  /* WHATNOW */
347             msgs[msgp++] = getcpy (m_draft (NULLCP, NULLCP, 1, &isdf));
348             if (stat (msgs[0], &st) == NOTOK)
349                 adios (msgs[0], "unable to stat draft file");
350             cp = concat ("Use \"", msgs[0], "\"? ", NULLCP);
351             for (status = LISTDSW; status != YESW;) {
352                 if (!(argp = getans (cp, anyl)))
353                     done (1);
354                 switch (status = smatch (*argp, anyl)) {
355                     case NOSW: 
356                         done (0);
357                     case YESW: 
358                         break;
359                     case LISTDSW: 
360                         (void) showfile (++argp, msgs[0]);
361                         break;
362                     default:
363                         advise (NULLCP, "say what?");
364                         break;
365                 }
366             }
367         }
368         else
369             for (msgnum = 0; msgnum < msgp; msgnum++)
370                 msgs[msgnum] = getcpy (m_maildir (msgs[msgnum]));
371     }
372     else {
373         if (!m_find ("path"))
374             free (path ("./", TFOLDER));
375
376         if (!msgp)
377             msgs[msgp++] = "cur";
378         maildir = m_maildir (dfolder);
379
380         if (chdir (maildir) == NOTOK)
381             adios (maildir, "unable to change directory to");
382         if (!(mp = m_gmsg (dfolder)))
383             adios (NULLCP, "unable to read folder %s", dfolder);
384         if (mp -> hghmsg == 0)
385             adios (NULLCP, "no messages in %s", dfolder);
386
387         for (msgnum = 0; msgnum < msgp; msgnum++)
388             if (!m_convert (mp, msgs[msgnum]))
389                 done (1);
390         m_setseq (mp);
391
392         for (msgp = 0, msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
393             if (mp -> msgstats[msgnum] & SELECTED) {
394                 msgs[msgp++] = getcpy (m_name (msgnum));
395 #ifdef  notdef
396                 mp -> msgstats[msgnum] |= DELETED;
397 #endif  /* notdef */
398                 mp -> msgstats[msgnum] &= ~EXISTS;
399             }
400         mp -> msgflags |= SEQMOD;
401
402         m_sync (mp);
403     }
404 #ifdef  WHATNOW
405 go_to_it: ;
406 #endif  /* WHATNOW */
407
408 /* \f */
409
410 #ifdef  TMA
411     if ((cp = getenv ("KDS")) == NULL || *cp == 0)
412         if ((cp = m_find ("kdsproc")) && *cp)
413             (void) m_putenv ("KDS", cp);
414     if ((cp = getenv ("TMADB")) == NULL || *cp == 0)
415         if ((cp = m_find ("tmadb")) && *cp)
416             (void) m_putenv ("TMADB", m_maildir (cp));
417 #endif  /* TMA */
418
419     if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0)
420         if ((cp = m_find ("signature")) && *cp)
421             (void) m_putenv ("SIGNATURE", cp);
422 #ifdef  UCI
423         else {
424             (void) sprintf (buf, "%s/.signature", mypath);
425             if ((fp = fopen (buf, "r")) != NULL
426                 && fgets (buf, sizeof buf, fp) != NULL) {
427                     (void) fclose (fp);
428                     if (cp = index (buf, '\n'))
429                         *cp = 0;
430                     (void) m_putenv ("SIGNATURE", buf);
431             }
432         }
433 #endif  /* UCI */
434
435     for (msgnum = 0; msgnum < msgp; msgnum++)
436         if (stat (msgs[msgnum], &st) == NOTOK)
437             adios (msgs[msgnum], "unable to stat draft file");
438
439     if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0)
440         annotext = NULL;
441     if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != 0))
442         inplace = atoi (cp);
443     if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == 0)
444         altmsg = NULL;  /* used by dist interface - see below */
445
446     if ((cp = getenv ("mhdist"))
447             && *cp
448             && (distsw = atoi (cp))
449             && altmsg) {
450         vec[vecp++] = "-dist";
451         distfile = getcpy (m_scratch (altmsg, invo_name));
452         if (link (altmsg, distfile) == NOTOK) {
453             if (errno != EXDEV
454 #ifdef  EISREMOTE
455                     && errno != EISREMOTE
456 #endif  /* EISREMOTE */
457                 )
458                 adios (distfile, "unable to link %s to", altmsg);
459             free (distfile);
460             distfile = getcpy (m_tmpfil (invo_name));
461             {
462                 int     in, out;
463                 struct stat st;
464
465                 if ((in = open (altmsg, 0)) == NOTOK)
466                     adios (altmsg, "unable to open");
467                 (void) fstat(in, &st);
468                 if ((out = creat (distfile, (int) st.st_mode & 0777)) == NOTOK)
469                     adios (distfile, "unable to write");
470                 cpydata (in, out, altmsg, distfile);
471                 (void) close (in);
472                 (void) close (out);
473             }   
474         }
475     }
476     else
477         distfile = NULL;
478
479     if (altmsg == NULL || stat (altmsg, &st) == NOTOK)
480         st.st_mtime = 0, st.st_dev = 0, st.st_ino = 0;
481     if (pushsw)
482         push ();
483
484     status = 0;
485     vec[0] = r1bindex (postproc, '/');
486     closefds (3);
487
488     for (msgnum = 0; msgnum < msgp; msgnum++)
489         switch (sendsbr (vec, vecp, msgs[msgnum], &st)) {
490             case DONE: 
491                 done (++status);
492
493             case NOTOK: 
494                 status++;       /* fall */
495             case OK:
496                 break;
497         }
498
499     m_update ();
500
501     done (status);
502 }