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