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