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