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