ffde2b49ea07c29a9bf72838a403ed2463efd04f
[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  4
24         { "version", 0 },
25 #define HELPSW  5
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 ...]", invo_name);
94                                         print_help(buf, switches, 1);
95                                         done(1);
96                                 case VERSIONSW:
97                                         print_version(invo_name);
98                                         done(1);
99
100                                 case DATESW:
101                                         datesw++;
102                                         continue;
103                                 case NDATESW:
104                                         datesw = 0;
105                                         continue;
106
107                                 case NOTESW:
108                                         if (!(cp = *argp++) || *cp == '-')
109                                                 adios(NULL, "missing argument to %s", argp[-2]);
110                                         notifysw |= donote(cp, 1);
111                                         continue;
112                                 case NNOTESW:
113                                         if (!(cp = *argp++) || *cp == '-')
114                                                 adios(NULL, "missing argument to %s", argp[-2]);
115                                         notifysw &= ~donote(cp, 0);
116                                         continue;
117                         }
118                 }
119                 if (vecp >= MAXVEC-1)
120                         adios(NULL, "you can only check %d users at a time",
121                                         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,
144                                                 datesw, notifysw, 0);
145                         else
146                                 advise(NULL, "no such user as %s", vec[vecp]);
147                 }
148         }
149
150         done(status);
151         return 1;
152 }
153
154
155 static struct swit ntswitches[] = {
156 #define NALLSW  0
157         { "all", 0 },
158 #define NMAISW  1
159         { "mail", 0 },
160 #define NNMAISW  2
161         { "nomail", 0 },
162         { NULL, 0 }
163 };
164
165
166 static int
167 donote(char *cp, int ntflag)
168 {
169         switch (smatch(cp, ntswitches)) {
170                 case AMBIGSW:
171                         ambigsw(cp, ntswitches);
172                         done(1);
173                 case UNKWNSW:
174                         adios(NULL, "-%snotify %s unknown",
175                                         ntflag ? "" : "no", cp);
176
177                 case NALLSW:
178                         return NT_ALL;
179                 case NMAISW:
180                         return NT_MAIL;
181                 case NNMAISW:
182                         return NT_NMAI;
183         }
184
185         /* Before 1999-07-15, garbage was returned if control got here. */
186         return 0;
187 }
188
189
190 static int
191 checkmail(char *user, char *home, int datesw, int notifysw, int personal)
192 {
193         int mf, status;
194         char buffer[BUFSIZ];
195         struct stat st;
196
197         snprintf(buffer, sizeof(buffer), "%s/%s",
198                         mmdfldir[0] ? mmdfldir : home,
199                         mmdflfil[0] ? mmdflfil : user);
200         if (datesw) {
201                 st.st_size = 0;
202                 st.st_atime = st.st_mtime = 0;
203         }
204         mf = (stat(buffer, &st) == NOTOK || st.st_size == 0) ? NONEOK
205                 : st.st_atime <= st.st_mtime ? MMDFNEW : MMDFOLD;
206
207         if ((mf & UUCPOK) || (mf & MMDFOK)) {
208                 if (notifysw & NT_MAIL) {
209                         printf(personal ? "You have " : "%s has ", user);
210                         if (mf & UUCPOK)
211                                 printf("%s old-style bell",
212                                                 mf & UUCPOLD ? "old" : "new");
213                         if ((mf & UUCPOK) && (mf & MMDFOK))
214                                 printf(" and ");
215                         if (mf & MMDFOK)
216                                 printf("%s%s", mf & MMDFOLD ? "old" : "new",
217                                                 mf & UUCPOK ? " Internet" : "");
218                         printf(" mail waiting");
219                 } else {
220                         notifysw = 0;
221                 }
222                 status = 0;
223         }
224         else {
225                 if (notifysw & NT_NMAI)
226                         printf(personal ? "You don't %s%s" : "%s doesn't %s",
227                                         personal ? "" : user,
228                                         "have any mail waiting");
229                 else
230                         notifysw = 0;
231
232                 status = 1;
233         }
234
235         if (notifysw)
236                 if (datesw && st.st_atime)
237                         printf("; last read on %s", dtime(&st.st_atime, 1));
238         if (notifysw)
239                 printf("\n");
240
241         return status;
242 }