0bec6756167d5fd043724f9386696395705ae9a8
[mmh] / uip / msgchk.c
1 /*
2  * msgchk.c -- check for mail
3  *
4  * This code is Copyright (c) 2002, by the authors of nmh.  See the
5  * COPYRIGHT file in the root directory of the nmh distribution for
6  * complete copyright information.
7  */
8
9 #include <h/mh.h>
10 #include <h/mts.h>
11 #include <h/tws.h>
12 #include <pwd.h>
13
14 static struct swit switches[] = {
15 #define DATESW  0
16         { "date", 0 },
17 #define NDATESW  1
18         { "nodate", 0 },
19 #define NOTESW  2
20         { "notify type", 0 },
21 #define NNOTESW  3
22         { "nonotify type", 0 },
23 #define VERSIONSW  7
24         { "version", 0 },
25 #define HELPSW  8
26         { "help", 0 },
27 };
28
29 /*
30  * Maximum numbers of users we can check (plus
31  * one for the NULL vector at the end).
32  */
33 #define MAXVEC  51
34
35 #define NT_NONE  0x0
36 #define NT_MAIL  0x1
37 #define NT_NMAI  0x2
38 #define NT_ALL   (NT_MAIL | NT_NMAI)
39
40 #define NONEOK   0x0
41 #define UUCPOLD  0x1
42 #define UUCPNEW  0x2
43 #define UUCPOK   (UUCPOLD | UUCPNEW)
44 #define MMDFOLD  0x4
45 #define MMDFNEW  0x8
46 #define MMDFOK   (MMDFOLD | MMDFNEW)
47
48
49 /*
50  * static prototypes
51  */
52 static int donote (char *, int);
53 static int checkmail (char *, char *, int, int, int);
54
55
56 int
57 main (int argc, char **argv)
58 {
59         int datesw = 1, notifysw = NT_ALL;
60         int status = 0;
61         int vecp = 0;
62         uid_t uid;
63         char buf[BUFSIZ];
64         char *user, *cp;
65         char **argp, **arguments, *vec[MAXVEC];
66         struct passwd *pw;
67
68 #ifdef LOCALE
69         setlocale(LC_ALL, "");
70 #endif
71         invo_name = r1bindex (argv[0], '/');
72
73         /* read user profile/context */
74         context_read();
75
76         mts_init (invo_name);
77         uid = getuid ();
78         user = getusername();
79
80         arguments = getarguments (invo_name, argc, argv, 1);
81         argp = arguments;
82
83         while ((cp = *argp++)) {
84                 if (*cp == '-') {
85                         switch (smatch (++cp, switches)) {
86                                 case AMBIGSW:
87                                         ambigsw (cp, switches);
88                                         done (1);
89                                 case UNKWNSW:
90                                         adios (NULL, "-%s unknown", cp);
91
92                                 case HELPSW:
93                                         snprintf (buf, sizeof(buf), "%s [switches] [users ...]",
94                                                 invo_name);
95                                         print_help (buf, switches, 1);
96                                         done (1);
97                                 case VERSIONSW:
98                                         print_version(invo_name);
99                                         done (1);
100
101                                 case DATESW:
102                                         datesw++;
103                                         continue;
104                                 case NDATESW:
105                                         datesw = 0;
106                                         continue;
107
108                                 case NOTESW:
109                                         if (!(cp = *argp++) || *cp == '-')
110                                                 adios (NULL, "missing argument to %s", argp[-2]);
111                                         notifysw |= donote (cp, 1);
112                                         continue;
113                                 case NNOTESW:
114                                         if (!(cp = *argp++) || *cp == '-')
115                                                 adios (NULL, "missing argument to %s", argp[-2]);
116                                         notifysw &= ~donote (cp, 0);
117                                         continue;
118                         }
119                 }
120                 if (vecp >= MAXVEC-1)
121                         adios (NULL, "you can only check %d users at a time", MAXVEC-1);
122                 else
123                         vec[vecp++] = cp;
124         }
125
126         if (vecp != 0)
127                 vec[vecp] = NULL;
128
129         if (vecp == 0) {
130                 char *home;
131
132                 /* Not sure this check makes sense... */
133                 if (!geteuid() || NULL == (home = getenv("HOME"))) {
134                         pw = getpwnam (user);
135                         if (pw == NULL)
136                                 adios (NULL, "unable to get information about user");
137                         home = pw->pw_dir;
138                 }
139                 status = checkmail (user, home, datesw, notifysw, 1);
140         } else {
141                 for (vecp = 0; vec[vecp]; vecp++) {
142                         if ((pw = getpwnam (vec[vecp])))
143                                 status += checkmail (pw->pw_name, pw->pw_dir, datesw, notifysw, 0);
144                         else
145                                 advise (NULL, "no such user as %s", vec[vecp]);
146                 }
147         }
148
149         done (status);
150         return 1;
151 }
152
153
154 static struct swit ntswitches[] = {
155 #define NALLSW  0
156         { "all", 0 },
157 #define NMAISW  1
158         { "mail", 0 },
159 #define NNMAISW  2
160         { "nomail", 0 },
161         { NULL, 0 }
162 };
163
164
165 static int
166 donote (char *cp, int ntflag)
167 {
168         switch (smatch (cp, ntswitches)) {
169                 case AMBIGSW:
170                         ambigsw (cp, ntswitches);
171                         done (1);
172                 case UNKWNSW:
173                         adios (NULL, "-%snotify %s unknown", ntflag ? "" : "no", cp);
174
175                 case NALLSW:
176                         return NT_ALL;
177                 case NMAISW:
178                         return NT_MAIL;
179                 case NNMAISW:
180                         return NT_NMAI;
181         }
182
183         return 0; /* Before 1999-07-15, garbage was returned if control got here. */
184 }
185
186
187 static int
188 checkmail (char *user, char *home, int datesw, int notifysw, int personal)
189 {
190         int mf, status;
191         char buffer[BUFSIZ];
192         struct stat st;
193
194         snprintf (buffer, sizeof(buffer), "%s/%s", mmdfldir[0] ? mmdfldir : home, mmdflfil[0] ? mmdflfil : user);
195         if (datesw) {
196                 st.st_size = 0;
197                 st.st_atime = st.st_mtime = 0;
198         }
199         mf = (stat (buffer, &st) == NOTOK || st.st_size == 0) ? NONEOK
200                 : st.st_atime <= st.st_mtime ? MMDFNEW : MMDFOLD;
201
202         if ((mf & UUCPOK) || (mf & MMDFOK)) {
203                 if (notifysw & NT_MAIL) {
204                         printf (personal ? "You have " : "%s has ", user);
205                         if (mf & UUCPOK)
206                                 printf ("%s old-style bell", mf & UUCPOLD ? "old" : "new");
207                         if ((mf & UUCPOK) && (mf & MMDFOK))
208                                 printf (" and ");
209                         if (mf & MMDFOK)
210                                 printf ("%s%s", mf & MMDFOLD ? "old" : "new",
211                                                 mf & UUCPOK ? " Internet" : "");
212                         printf (" mail waiting");
213                 } else {
214                         notifysw = 0;
215                 }
216                 status = 0;
217         }
218         else {
219                 if (notifysw & NT_NMAI)
220                         printf (personal ? "You don't %s%s" : "%s doesn't %s",
221                                         personal ? "" : user, "have any mail waiting");
222                 else
223                         notifysw = 0;
224
225                 status = 1;
226         }
227
228         if (notifysw)
229                 if (datesw && st.st_atime)
230                         printf ("; last read on %s", dtime (&st.st_atime, 1));
231         if (notifysw)
232                 printf ("\n");
233
234         return status;
235 }