]> diplodocus.org Git - nmh/blob - uip/msgchk.c
Sigh. I put the documentation about the -tls switch in the long description,
[nmh] / 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 */