Removed unused local variables to eliminate warnings from gcc 4.6.2.
[mmh] / uip / msgchk.c
1
2 /*
3  * msgchk.c -- check for mail
4  *
5  * This code is Copyright (c) 2002, by the authors of nmh.  See the
6  * COPYRIGHT file in the root directory of the nmh distribution for
7  * complete copyright information.
8  */
9
10 #include <h/mh.h>
11 #include <h/mts.h>
12 #include <h/tws.h>
13 #include <pwd.h>
14
15 #ifdef POP
16 # include <h/popsbr.h>
17 #endif
18
19 #ifndef POP
20 # define POPminc(a) (a)
21 #else
22 # define POPminc(a)  0
23 #endif
24
25 #ifndef CYRUS_SASL
26 # define SASLminc(a) (a)
27 #else
28 # define SASLminc(a)  0
29 #endif
30
31 static struct swit switches[] = {
32 #define DATESW                   0
33     { "date", 0 },
34 #define NDATESW                  1
35     { "nodate", 0 },
36 #define NOTESW                   2
37     { "notify type", 0 },
38 #define NNOTESW                  3
39     { "nonotify type", 0 },
40 #define HOSTSW                   4
41     { "host hostname", POPminc (-4) },
42 #define USERSW                   5
43     { "user username", POPminc (-4) },
44 #define PORTSW                   6
45     { "port name/number", POPminc(-4) },
46 #define VERSIONSW                7
47     { "version", 0 },
48 #define HELPSW                   8
49     { "help", 0 },
50 #define SNOOPSW                  9
51     { "snoop", -5 },
52 #define SASLSW                  10
53     { "sasl", SASLminc(-4) },
54 #define SASLMECHSW              11
55     { "saslmech", SASLminc(-5) },
56 #define PROXYSW                 12
57     { "proxy command", POPminc(-5) },
58     { NULL, 0 }
59 };
60
61 /*
62  * Maximum numbers of users we can check (plus
63  * one for the NULL vector at the end).
64  */
65 #define MAXVEC  51
66
67 #define NT_NONE 0x0
68 #define NT_MAIL 0x1
69 #define NT_NMAI 0x2
70 #define NT_ALL  (NT_MAIL | NT_NMAI)
71
72 #define NONEOK  0x0
73 #define UUCPOLD 0x1
74 #define UUCPNEW 0x2
75 #define UUCPOK  (UUCPOLD | UUCPNEW)
76 #define MMDFOLD 0x4
77 #define MMDFNEW 0x8
78 #define MMDFOK  (MMDFOLD | MMDFNEW)
79
80
81 /*
82  * static prototypes
83  */
84 static int donote (char *, int);
85 static int checkmail (char *, char *, int, int, int);
86
87 #ifdef POP
88 static int remotemail (char *, char *, char *, char *, int, int, int, int,
89                        char *);
90 #endif
91
92
93 int
94 main (int argc, char **argv)
95 {
96     int datesw = 1, notifysw = NT_ALL;
97     int status = 0, sasl = 0;
98     int snoop = 0, vecp = 0;
99     char *cp, *host = NULL, *port = NULL, *user, *proxy = NULL; 
100     char buf[BUFSIZ], *saslmech = NULL; 
101     char **argp, **arguments, *vec[MAXVEC];
102     struct passwd *pw;
103
104 #ifdef HESIOD
105     struct hes_postoffice *po;
106     char *tmphost;
107 #endif
108
109 #ifdef LOCALE
110     setlocale(LC_ALL, "");
111 #endif
112     invo_name = r1bindex (argv[0], '/');
113
114     /* read user profile/context */
115     context_read();
116
117     mts_init (invo_name);
118     user = getusername();
119
120     arguments = getarguments (invo_name, argc, argv, 1);
121     argp = arguments;
122
123 #ifdef POP
124     if ((cp = getenv ("MHPOPDEBUG")) && *cp)
125         snoop++;
126 #endif
127
128     while ((cp = *argp++)) {
129         if (*cp == '-') {
130             switch (smatch (++cp, switches)) {
131                 case AMBIGSW: 
132                     ambigsw (cp, switches);
133                     done (1);
134                 case UNKWNSW: 
135                     adios (NULL, "-%s unknown", cp);
136
137                 case HELPSW: 
138                     snprintf (buf, sizeof(buf), "%s [switches] [users ...]",
139                         invo_name);
140                     print_help (buf, switches, 1);
141                     done (1);
142                 case VERSIONSW:
143                     print_version(invo_name);
144                     done (1);
145
146                 case DATESW:
147                     datesw++;
148                     continue;
149                 case NDATESW:
150                     datesw = 0;
151                     continue;
152
153                 case NOTESW:
154                     if (!(cp = *argp++) || *cp == '-')
155                         adios (NULL, "missing argument to %s", argp[-2]);
156                     notifysw |= donote (cp, 1);
157                     continue;
158                 case NNOTESW:
159                     if (!(cp = *argp++) || *cp == '-')
160                         adios (NULL, "missing argument to %s", argp[-2]);
161                     notifysw &= ~donote (cp, 0);
162                     continue;
163
164                 case HOSTSW: 
165                     if (!(host = *argp++) || *host == '-')
166                         adios (NULL, "missing argument to %s", argp[-2]);
167                     continue;
168
169                 case PORTSW:
170                     if (!(port = *argp++) || *port == '-')
171                         adios (NULL, "missing argument to %s", argp[-2]);
172                 continue;
173
174                 case USERSW: 
175                     if (!(cp = *argp++) || *cp == '-')
176                         adios (NULL, "missing argument to %s", argp[-2]);
177                     if (vecp >= MAXVEC-1)
178                         adios (NULL, "you can only check %d users at a time", MAXVEC-1);
179                     else
180                         vec[vecp++] = cp;
181                     continue;
182
183                 case SNOOPSW:
184                     snoop++;
185                     continue;
186
187                 case SASLSW:
188                     sasl++;
189                     continue;
190                 
191                 case SASLMECHSW:
192                     if (!(saslmech = *argp++) || *saslmech == '-')
193                         adios (NULL, "missing argument to %s", argp[-2]);
194                     continue;
195
196                 case PROXYSW:
197                     if (!(proxy = *argp++) || *proxy == '-')
198                         adios (NULL, "missing argument to %s", argp[-2]);
199                     continue;
200             }
201         }
202         if (vecp >= MAXVEC-1)
203             adios (NULL, "you can only check %d users at a time", MAXVEC-1);
204         else
205             vec[vecp++] = cp;
206     }
207
208 #ifdef POP
209     /*
210      * If -host is not specified by user
211      */
212     if (!host || !*host) {
213         /*
214          * If "pophost" is specified in mts.conf,
215          * use it as default value.
216          */
217         if (pophost && *pophost)
218             host = pophost;
219     }
220     if (!host || !*host)
221         host = NULL;
222 #endif /* POP */
223
224     if (vecp != 0)
225         vec[vecp] = NULL;
226
227 #ifdef POP
228     if (host) {
229         if (vecp == 0) {
230             status = remotemail (host, port, user, proxy, notifysw, 1,
231                                  snoop, sasl, saslmech);
232         } else {
233             for (vecp = 0; vec[vecp]; vecp++)
234                 status += remotemail (host, port, vec[vecp], proxy, notifysw, 0,
235                                       snoop, sasl, saslmech);
236         }
237     } else {
238 #endif /* POP */
239
240     if (vecp == 0) {
241         char *home;
242
243         /* Not sure this check makes sense... */
244         if (!geteuid() || NULL == (home = getenv("HOME"))) {
245             pw = getpwnam (user);
246             if (pw == NULL)
247                 adios (NULL, "unable to get information about user");
248             home = pw->pw_dir;
249         }
250         status = checkmail (user, home, datesw, notifysw, 1);
251     } else {
252         for (vecp = 0; vec[vecp]; vecp++) {
253             if ((pw = getpwnam (vec[vecp])))
254                 status += checkmail (pw->pw_name, pw->pw_dir, datesw, notifysw, 0);
255             else
256                 advise (NULL, "no such user as %s", vec[vecp]);
257         }
258     }
259 #ifdef POP
260     }           /* host == NULL */
261 #endif
262
263     done (status);
264     return 1;
265 }
266
267
268 static struct swit ntswitches[] = {
269 #define NALLSW     0
270     { "all", 0 },
271 #define NMAISW     1
272     { "mail", 0 },
273 #define NNMAISW    2
274     { "nomail", 0 },
275     { NULL, 0 }
276 };
277
278
279 static int
280 donote (char *cp, int ntflag)
281 {
282     switch (smatch (cp, ntswitches)) {
283         case AMBIGSW: 
284             ambigsw (cp, ntswitches);
285             done (1);
286         case UNKWNSW: 
287             adios (NULL, "-%snotify %s unknown", ntflag ? "" : "no", cp);
288
289         case NALLSW: 
290             return NT_ALL;
291         case NMAISW: 
292             return NT_MAIL;
293         case NNMAISW: 
294             return NT_NMAI;
295     }
296
297     return 0; /* Before 1999-07-15, garbage was returned if control got here. */
298 }
299
300
301 static int
302 checkmail (char *user, char *home, int datesw, int notifysw, int personal)
303 {
304     int mf, status;
305     char buffer[BUFSIZ];
306     struct stat st;
307
308     snprintf (buffer, sizeof(buffer), "%s/%s", mmdfldir[0] ? mmdfldir : home, mmdflfil[0] ? mmdflfil : user);
309     if (datesw) {
310         st.st_size = 0;
311         st.st_atime = st.st_mtime = 0;
312     }
313     mf = (stat (buffer, &st) == NOTOK || st.st_size == 0) ? NONEOK
314         : st.st_atime <= st.st_mtime ? MMDFNEW : MMDFOLD;
315
316     if ((mf & UUCPOK) || (mf & MMDFOK)) {
317         if (notifysw & NT_MAIL) {
318             printf (personal ? "You have " : "%s has ", user);
319             if (mf & UUCPOK)
320                 printf ("%s old-style bell", mf & UUCPOLD ? "old" : "new");
321             if ((mf & UUCPOK) && (mf & MMDFOK))
322                 printf (" and ");
323             if (mf & MMDFOK)
324                 printf ("%s%s", mf & MMDFOLD ? "old" : "new",
325                         mf & UUCPOK ? " Internet" : "");
326             printf (" mail waiting");
327         } else {
328             notifysw = 0;
329         }
330         status = 0;
331     }
332     else {
333         if (notifysw & NT_NMAI)
334             printf (personal ? "You don't %s%s" : "%s doesn't %s",
335                     personal ? "" : user, "have any mail waiting");
336         else
337             notifysw = 0;
338
339         status = 1;
340     }
341
342     if (notifysw)
343         if (datesw && st.st_atime)
344             printf ("; last read on %s", dtime (&st.st_atime, 1));
345     if (notifysw)
346         printf ("\n");
347
348     return status;
349 }
350
351
352 #ifdef POP
353 extern char response[];
354
355 static int
356 remotemail (char *host, char *port, char *user, char *proxy, int notifysw,
357             int personal, int snoop, int sasl, char *saslmech)
358 {
359     int nmsgs, nbytes, status;
360     char *pass = NULL;
361
362     if (user == NULL)
363         user = getusername ();
364     if (sasl)
365         pass = getusername ();
366     else
367         ruserpass (host, &user, &pass);
368
369     /* open the POP connection */
370     if (pop_init (host, port, user, pass, proxy, snoop, sasl, saslmech) == NOTOK
371             || pop_stat (&nmsgs, &nbytes) == NOTOK      /* check for messages  */
372             || pop_quit () == NOTOK) {                  /* quit POP connection */
373         advise (NULL, "%s", response);
374         return 1;
375     }
376
377     if (nmsgs) {
378         if (notifysw & NT_MAIL) {
379             printf (personal ? "You have " : "%s has ", user);
380             printf ("%d message%s (%d bytes)",
381                     nmsgs, nmsgs != 1 ? "s" : "", nbytes);
382         }
383         else
384             notifysw = 0;
385
386         status = 0;
387     } else {
388         if (notifysw & NT_NMAI)
389             printf (personal ? "You don't %s%s" : "%s doesn't %s",
390                     personal ? "" : user, "have any mail waiting");
391         else
392             notifysw = 0;
393         status = 1;
394     }
395     if (notifysw)
396         printf (" on %s\n", host);
397
398     return status;
399 }
400 #endif /* POP */