]> diplodocus.org Git - nmh/blob - uip/msgchk.c
Changed from returning void to returning int so that main()s who call done() at
[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 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
320
321 static int
322 checkmail (char *user, char *home, int datesw, int notifysw, int personal)
323 {
324 int mf, status;
325 char buffer[BUFSIZ];
326 struct stat st;
327
328 snprintf (buffer, sizeof(buffer), "%s/%s", mmdfldir[0] ? mmdfldir : home, mmdflfil[0] ? mmdflfil : user);
329 if (datesw) {
330 st.st_size = 0;
331 st.st_atime = st.st_mtime = 0;
332 }
333 mf = (stat (buffer, &st) == NOTOK || st.st_size == 0) ? NONEOK
334 : st.st_atime <= st.st_mtime ? MMDFNEW : MMDFOLD;
335
336 if ((mf & UUCPOK) || (mf & MMDFOK)) {
337 if (notifysw & NT_MAIL) {
338 printf (personal ? "You have " : "%s has ", user);
339 if (mf & UUCPOK)
340 printf ("%s old-style bell", mf & UUCPOLD ? "old" : "new");
341 if ((mf & UUCPOK) && (mf & MMDFOK))
342 printf (" and ");
343 if (mf & MMDFOK)
344 printf ("%s%s", mf & MMDFOLD ? "old" : "new",
345 mf & UUCPOK ? " Internet" : "");
346 printf (" mail waiting");
347 } else {
348 notifysw = 0;
349 }
350 status = 0;
351 }
352 else {
353 if (notifysw & NT_NMAI)
354 printf (personal ? "You don't %s%s" : "%s doesn't %s",
355 personal ? "" : user, "have any mail waiting");
356 else
357 notifysw = 0;
358
359 status = 1;
360 }
361
362 if (notifysw)
363 if (datesw && st.st_atime)
364 printf ("; last read on %s", dtime (&st.st_atime, 1));
365 if (notifysw)
366 printf ("\n");
367
368 return status;
369 }
370
371
372 #ifdef POP
373 extern char response[];
374
375 static int
376 remotemail (char *host, char *user, int rpop, int notifysw, int personal, int snoop)
377 {
378 int nmsgs, nbytes, status;
379 char *pass = NULL;
380
381 if (user == NULL)
382 user = getusername ();
383 if (rpop > 0)
384 pass = getusername ();
385 else
386 ruserpass (host, &user, &pass);
387
388 /* open the POP connection */
389 if (pop_init (host, user, pass, snoop, rpop) == NOTOK
390 || pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages */
391 || pop_quit () == NOTOK) { /* quit POP connection */
392 advise (NULL, "%s", response);
393 return 1;
394 }
395
396 if (nmsgs) {
397 if (notifysw & NT_MAIL) {
398 printf (personal ? "You have " : "%s has ", user);
399 printf ("%d message%s (%d bytes)",
400 nmsgs, nmsgs != 1 ? "s" : "", nbytes);
401 }
402 else
403 notifysw = 0;
404
405 status = 0;
406 } else {
407 if (notifysw & NT_NMAI)
408 printf (personal ? "You don't %s%s" : "%s doesn't %s",
409 personal ? "" : user, "have any mail waiting");
410 else
411 notifysw = 0;
412 status = 1;
413 }
414 if (notifysw)
415 printf (" on %s\n", host);
416
417 return status;
418 }
419 #endif /* POP */