]> diplodocus.org Git - nmh/blob - uip/msgchk.c
Make sure we ignore config.h.in~
[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 uid_t uid;
100 char *cp, *host = NULL, *port = NULL, *user, *proxy = NULL;
101 char buf[BUFSIZ], *saslmech = NULL;
102 char **argp, **arguments, *vec[MAXVEC];
103 struct passwd *pw;
104
105 #ifdef HESIOD
106 struct hes_postoffice *po;
107 char *tmphost;
108 #endif
109
110 #ifdef LOCALE
111 setlocale(LC_ALL, "");
112 #endif
113 invo_name = r1bindex (argv[0], '/');
114
115 /* read user profile/context */
116 context_read();
117
118 mts_init (invo_name);
119 uid = getuid ();
120 user = getusername();
121
122 arguments = getarguments (invo_name, argc, argv, 1);
123 argp = arguments;
124
125 #ifdef POP
126 if ((cp = getenv ("MHPOPDEBUG")) && *cp)
127 snoop++;
128 #endif
129
130 while ((cp = *argp++)) {
131 if (*cp == '-') {
132 switch (smatch (++cp, switches)) {
133 case AMBIGSW:
134 ambigsw (cp, switches);
135 done (1);
136 case UNKWNSW:
137 adios (NULL, "-%s unknown", cp);
138
139 case HELPSW:
140 snprintf (buf, sizeof(buf), "%s [switches] [users ...]",
141 invo_name);
142 print_help (buf, switches, 1);
143 done (1);
144 case VERSIONSW:
145 print_version(invo_name);
146 done (1);
147
148 case DATESW:
149 datesw++;
150 continue;
151 case NDATESW:
152 datesw = 0;
153 continue;
154
155 case NOTESW:
156 if (!(cp = *argp++) || *cp == '-')
157 adios (NULL, "missing argument to %s", argp[-2]);
158 notifysw |= donote (cp, 1);
159 continue;
160 case NNOTESW:
161 if (!(cp = *argp++) || *cp == '-')
162 adios (NULL, "missing argument to %s", argp[-2]);
163 notifysw &= ~donote (cp, 0);
164 continue;
165
166 case HOSTSW:
167 if (!(host = *argp++) || *host == '-')
168 adios (NULL, "missing argument to %s", argp[-2]);
169 continue;
170
171 case PORTSW:
172 if (!(port = *argp++) || *port == '-')
173 adios (NULL, "missing argument to %s", argp[-2]);
174 continue;
175
176 case USERSW:
177 if (!(cp = *argp++) || *cp == '-')
178 adios (NULL, "missing argument to %s", argp[-2]);
179 if (vecp >= MAXVEC-1)
180 adios (NULL, "you can only check %d users at a time", MAXVEC-1);
181 else
182 vec[vecp++] = cp;
183 continue;
184
185 case SNOOPSW:
186 snoop++;
187 continue;
188
189 case SASLSW:
190 sasl++;
191 continue;
192
193 case SASLMECHSW:
194 if (!(saslmech = *argp++) || *saslmech == '-')
195 adios (NULL, "missing argument to %s", argp[-2]);
196 continue;
197
198 case PROXYSW:
199 if (!(proxy = *argp++) || *proxy == '-')
200 adios (NULL, "missing argument to %s", argp[-2]);
201 continue;
202 }
203 }
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 }
209
210 #ifdef POP
211 /*
212 * If -host is not specified by user
213 */
214 if (!host || !*host) {
215 /*
216 * If "pophost" is specified in mts.conf,
217 * use it as default value.
218 */
219 if (pophost && *pophost)
220 host = pophost;
221 }
222 if (!host || !*host)
223 host = NULL;
224 #endif /* POP */
225
226 if (vecp != 0)
227 vec[vecp] = NULL;
228
229 #ifdef POP
230 if (host) {
231 if (vecp == 0) {
232 status = remotemail (host, port, user, proxy, notifysw, 1,
233 snoop, sasl, saslmech);
234 } else {
235 for (vecp = 0; vec[vecp]; vecp++)
236 status += remotemail (host, port, vec[vecp], proxy, notifysw, 0,
237 snoop, sasl, saslmech);
238 }
239 } else {
240 #endif /* POP */
241
242 if (vecp == 0) {
243 char *home;
244
245 /* Not sure this check makes sense... */
246 if (!geteuid() || NULL == (home = getenv("HOME"))) {
247 pw = getpwnam (user);
248 if (pw == NULL)
249 adios (NULL, "unable to get information about user");
250 home = pw->pw_dir;
251 }
252 status = checkmail (user, home, datesw, notifysw, 1);
253 } else {
254 for (vecp = 0; vec[vecp]; vecp++) {
255 if ((pw = getpwnam (vec[vecp])))
256 status += checkmail (pw->pw_name, pw->pw_dir, datesw, notifysw, 0);
257 else
258 advise (NULL, "no such user as %s", vec[vecp]);
259 }
260 }
261 #ifdef POP
262 } /* host == NULL */
263 #endif
264
265 done (status);
266 return 1;
267 }
268
269
270 static struct swit ntswitches[] = {
271 #define NALLSW 0
272 { "all", 0 },
273 #define NMAISW 1
274 { "mail", 0 },
275 #define NNMAISW 2
276 { "nomail", 0 },
277 { NULL, 0 }
278 };
279
280
281 static int
282 donote (char *cp, int ntflag)
283 {
284 switch (smatch (cp, ntswitches)) {
285 case AMBIGSW:
286 ambigsw (cp, ntswitches);
287 done (1);
288 case UNKWNSW:
289 adios (NULL, "-%snotify %s unknown", ntflag ? "" : "no", cp);
290
291 case NALLSW:
292 return NT_ALL;
293 case NMAISW:
294 return NT_MAIL;
295 case NNMAISW:
296 return NT_NMAI;
297 }
298
299 return 0; /* Before 1999-07-15, garbage was returned if control got here. */
300 }
301
302
303 static int
304 checkmail (char *user, char *home, int datesw, int notifysw, int personal)
305 {
306 int mf, status;
307 char buffer[BUFSIZ];
308 struct stat st;
309
310 snprintf (buffer, sizeof(buffer), "%s/%s", mmdfldir[0] ? mmdfldir : home, mmdflfil[0] ? mmdflfil : user);
311 if (datesw) {
312 st.st_size = 0;
313 st.st_atime = st.st_mtime = 0;
314 }
315 mf = (stat (buffer, &st) == NOTOK || st.st_size == 0) ? NONEOK
316 : st.st_atime <= st.st_mtime ? MMDFNEW : MMDFOLD;
317
318 if ((mf & UUCPOK) || (mf & MMDFOK)) {
319 if (notifysw & NT_MAIL) {
320 printf (personal ? "You have " : "%s has ", user);
321 if (mf & UUCPOK)
322 printf ("%s old-style bell", mf & UUCPOLD ? "old" : "new");
323 if ((mf & UUCPOK) && (mf & MMDFOK))
324 printf (" and ");
325 if (mf & MMDFOK)
326 printf ("%s%s", mf & MMDFOLD ? "old" : "new",
327 mf & UUCPOK ? " Internet" : "");
328 printf (" mail waiting");
329 } else {
330 notifysw = 0;
331 }
332 status = 0;
333 }
334 else {
335 if (notifysw & NT_NMAI)
336 printf (personal ? "You don't %s%s" : "%s doesn't %s",
337 personal ? "" : user, "have any mail waiting");
338 else
339 notifysw = 0;
340
341 status = 1;
342 }
343
344 if (notifysw)
345 if (datesw && st.st_atime)
346 printf ("; last read on %s", dtime (&st.st_atime, 1));
347 if (notifysw)
348 printf ("\n");
349
350 return status;
351 }
352
353
354 #ifdef POP
355 extern char response[];
356
357 static int
358 remotemail (char *host, char *port, char *user, char *proxy, int notifysw,
359 int personal, int snoop, int sasl, char *saslmech)
360 {
361 int nmsgs, nbytes, status;
362 char *pass = NULL;
363
364 if (user == NULL)
365 user = getusername ();
366 if (sasl)
367 pass = getusername ();
368 else
369 ruserpass (host, &user, &pass);
370
371 /* open the POP connection */
372 if (pop_init (host, user, port, pass, proxy, snoop, sasl, saslmech) == NOTOK
373 || pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages */
374 || pop_quit () == NOTOK) { /* quit POP connection */
375 advise (NULL, "%s", response);
376 return 1;
377 }
378
379 if (nmsgs) {
380 if (notifysw & NT_MAIL) {
381 printf (personal ? "You have " : "%s has ", user);
382 printf ("%d message%s (%d bytes)",
383 nmsgs, nmsgs != 1 ? "s" : "", nbytes);
384 }
385 else
386 notifysw = 0;
387
388 status = 0;
389 } else {
390 if (notifysw & NT_NMAI)
391 printf (personal ? "You don't %s%s" : "%s doesn't %s",
392 personal ? "" : user, "have any mail waiting");
393 else
394 notifysw = 0;
395 status = 1;
396 }
397 if (notifysw)
398 printf (" on %s\n", host);
399
400 return status;
401 }
402 #endif /* POP */