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