fe01326f38cdc900e586a9fb11a55dc72d622c3d
[mmh] / uip / whom.c
1
2 /*
3  * whom.c -- report to whom a message would be sent
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 #include <h/mh.h>
13 #include <h/signals.h>
14 #include <signal.h>
15
16 #ifndef CYRUS_SASL
17 # define SASLminc(a) (a)
18 #else /* CYRUS_SASL */
19 # define SASLminc(a)  0
20 #endif /* CYRUS_SASL */
21
22 #ifndef TLS_SUPPORT
23 # define TLSminc(a)  (a)
24 #else /* TLS_SUPPORT */
25 # define TLSminc(a)   0
26 #endif /* TLS_SUPPORT */
27
28 static struct swit switches[] = {
29 #define ALIASW              0
30     { "alias aliasfile", 0 },
31 #define CHKSW               1
32     { "check", 0 },
33 #define NOCHKSW             2
34     { "nocheck", 0 },
35 #define DRAFTSW             3
36     { "draft", 0 },
37 #define DFOLDSW             4
38     { "draftfolder +folder", 6 },
39 #define DMSGSW              5
40     { "draftmessage msg", 6 },
41 #define NDFLDSW             6
42     { "nodraftfolder", 0 },
43 #define VERSIONSW           7
44     { "version", 0 },
45 #define HELPSW              8
46     { "help", 0 },
47 #define CLIESW              9
48     { "client host", -6 },
49 #define SERVSW             10
50     { "server host", -6 },
51 #define SNOOPSW            11
52     { "snoop", -5 },
53 #define SASLSW             12
54     { "sasl", SASLminc(4) },
55 #define SASLMECHSW         13
56     { "saslmech mechanism", SASLminc(-5) },
57 #define USERSW             14
58     { "user username", SASLminc(-4) },
59 #define PORTSW             15
60     { "port server port name/number", 4 },
61 #define TLSSW              16
62     { "tls", TLSminc(-3) },
63     { NULL, 0 }
64 };
65
66
67 int
68 main (int argc, char **argv)
69 {
70     pid_t child_id;
71     int i, status, isdf = 0;
72     int distsw = 0, vecp = 0;
73     char *cp, *dfolder = NULL, *dmsg = NULL;
74     char *msg = NULL, **ap, **argp, backup[BUFSIZ];
75     char buf[BUFSIZ], **arguments, *vec[MAXARGS];
76
77 #ifdef LOCALE
78     setlocale(LC_ALL, "");
79 #endif
80     invo_name = r1bindex (argv[0], '/');
81
82     /* read user profile/context */
83     context_read();
84
85     arguments = getarguments (invo_name, argc, argv, 1);
86     argp = arguments;
87
88     vec[vecp++] = invo_name;
89     vec[vecp++] = "-whom";
90     vec[vecp++] = "-library";
91     vec[vecp++] = getcpy (m_maildir (""));
92
93     while ((cp = *argp++)) {
94         if (*cp == '-') {
95             switch (smatch (++cp, switches)) {
96                 case AMBIGSW: 
97                     ambigsw (cp, switches);
98                     done (1);
99                 case UNKWNSW: 
100                     adios (NULL, "-%s unknown", cp);
101
102                 case HELPSW: 
103                     snprintf (buf, sizeof(buf), "%s [switches] [file]", invo_name);
104                     print_help (buf, switches, 1);
105                     done (1);
106                 case VERSIONSW:
107                     print_version(invo_name);
108                     done (1);
109
110                 case CHKSW: 
111                 case NOCHKSW: 
112                 case SNOOPSW:
113                 case SASLSW:
114                     vec[vecp++] = --cp;
115                     continue;
116
117                 case DRAFTSW:
118                     msg = draft;
119                     continue;
120
121                 case DFOLDSW: 
122                     if (dfolder)
123                         adios (NULL, "only one draft folder at a time!");
124                     if (!(cp = *argp++) || *cp == '-')
125                         adios (NULL, "missing argument to %s", argp[-2]);
126                     dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
127                             *cp != '@' ? TFOLDER : TSUBCWF);
128                     continue;
129                 case DMSGSW: 
130                     if (dmsg)
131                         adios (NULL, "only one draft message at a time!");
132                     if (!(dmsg = *argp++) || *dmsg == '-')
133                         adios (NULL, "missing argument to %s", argp[-2]);
134                     continue;
135                 case NDFLDSW: 
136                     dfolder = NULL;
137                     isdf = NOTOK;
138                     continue;
139
140                 case ALIASW: 
141                 case CLIESW: 
142                 case SERVSW: 
143                 case USERSW:
144                 case PORTSW:
145                 case SASLMECHSW:
146                     vec[vecp++] = --cp;
147                     if (!(cp = *argp++) || *cp == '-')
148                         adios (NULL, "missing argument to %s", argp[-2]);
149                     vec[vecp++] = cp;
150                     continue;
151             }
152         }
153         if (msg)
154             adios (NULL, "only one draft at a time!");
155         else
156             vec[vecp++] = msg = cp;
157     }
158
159     /* allow Aliasfile: profile entry */
160     if ((cp = context_find ("Aliasfile"))) {
161         char *dp = NULL;
162
163         for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) {
164             vec[vecp++] = "-alias";
165             vec[vecp++] = *ap;
166         }
167     }
168
169     if (msg == NULL) {
170 #ifdef  WHATNOW
171         if (dfolder || (cp = getenv ("mhdraft")) == NULL || *cp == '\0')
172 #endif  /* WHATNOW */
173             cp  = getcpy (m_draft (dfolder, dmsg, 1, &isdf));
174         msg = vec[vecp++] = cp;
175     }
176     if ((cp = getenv ("mhdist"))
177             && *cp
178             && (distsw = atoi (cp))
179             && (cp = getenv ("mhaltmsg"))
180             && *cp) {
181         if (distout (msg, cp, backup) == NOTOK)
182             done (1);
183         vec[vecp++] = "-dist";
184         distsw++;
185     }
186     vec[vecp] = NULL;
187
188     closefds (3);
189
190     if (distsw) {
191         for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
192             sleep (5);
193     }
194
195     switch (distsw ? child_id : OK) {
196         case NOTOK:
197             advise (NULL, "unable to fork, so checking directly...");
198         case OK:
199             execvp (postproc, vec);
200             fprintf (stderr, "unable to exec ");
201             perror (postproc);
202             _exit (-1);
203
204         default:
205             SIGNAL (SIGHUP, SIG_IGN);
206             SIGNAL (SIGINT, SIG_IGN);
207             SIGNAL (SIGQUIT, SIG_IGN);
208             SIGNAL (SIGTERM, SIG_IGN);
209
210             status = pidwait(child_id, OK);
211
212             unlink (msg);
213             if (rename (backup, msg) == NOTOK)
214                 adios (msg, "unable to rename %s to", backup);
215             done (status);
216     }
217
218     return 0;  /* dead code to satisfy the compiler */
219 }