Rest of the MMDF-style mail drop support removal.
[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 MAILOLD  0x4
42 #define MAILNEW  0x8
43 #define MAILOK   (MAILOLD | MAILNEW)
44
45
46 /*
47 ** static prototypes
48 */
49 static int donote(char *, int);
50 static int checkmail(char *, int, int, int);
51
52
53 int
54 main(int argc, char **argv)
55 {
56         int datesw = 1, notifysw = NT_ALL;
57         int status = 0;
58         int vecp = 0;
59         char buf[BUFSIZ];
60         char *user, *cp;
61         char **argp, **arguments, *vec[MAXVEC];
62         struct passwd *pw;
63
64 #ifdef LOCALE
65         setlocale(LC_ALL, "");
66 #endif
67         invo_name = mhbasename(argv[0]);
68
69         /* read user profile/context */
70         context_read();
71
72         mts_init(invo_name);
73         user = getusername();
74
75         arguments = getarguments(invo_name, argc, argv, 1);
76         argp = arguments;
77
78         while ((cp = *argp++)) {
79                 if (*cp == '-') {
80                         switch (smatch(++cp, switches)) {
81                         case AMBIGSW:
82                                 ambigsw(cp, switches);
83                                 done(1);
84                         case UNKWNSW:
85                                 adios(NULL, "-%s unknown", cp);
86
87                         case HELPSW:
88                                 snprintf(buf, sizeof(buf), "%s [switches] [users ...]", invo_name);
89                                 print_help(buf, switches, 1);
90                                 done(1);
91                         case VERSIONSW:
92                                 print_version(invo_name);
93                                 done(1);
94
95                         case DATESW:
96                                 datesw++;
97                                 continue;
98                         case NDATESW:
99                                 datesw = 0;
100                                 continue;
101
102                         case NOTESW:
103                                 if (!(cp = *argp++) || *cp == '-')
104                                         adios(NULL, "missing argument to %s",
105                                                         argp[-2]);
106                                 notifysw |= donote(cp, 1);
107                                 continue;
108                         case NNOTESW:
109                                 if (!(cp = *argp++) || *cp == '-')
110                                         adios(NULL, "missing argument to %s",
111                                                         argp[-2]);
112                                 notifysw &= ~donote(cp, 0);
113                                 continue;
114                         }
115                 }
116                 if (vecp >= MAXVEC-1)
117                         adios(NULL, "you can only check %d users at a time",
118                                         MAXVEC-1);
119                 else
120                         vec[vecp++] = cp;
121         }
122
123         if (!vecp) {
124                 done(checkmail(user, datesw, notifysw, 1));
125                 return 1;
126         }
127
128         vec[vecp] = NULL;
129         for (vecp = 0; vec[vecp]; vecp++) {
130                 if ((pw = getpwnam(vec[vecp])))
131                         status += checkmail(pw->pw_name, datesw, notifysw, 0);
132                 else
133                         advise(NULL, "no such user as %s", vec[vecp]);
134         }
135         done(status);
136         return 1;
137 }
138
139
140 static struct swit ntswitches[] = {
141 #define NALLSW  0
142         { "all", 0 },
143 #define NMAISW  1
144         { "mail", 0 },
145 #define NNMAISW  2
146         { "nomail", 0 },
147         { NULL, 0 }
148 };
149
150
151 static int
152 donote(char *cp, int ntflag)
153 {
154         switch (smatch(cp, ntswitches)) {
155         case AMBIGSW:
156                 ambigsw(cp, ntswitches);
157                 done(1);
158         case UNKWNSW:
159                 adios(NULL, "-%snotify %s unknown", ntflag ? "" : "no", cp);
160
161         case NALLSW:
162                 return NT_ALL;
163         case NMAISW:
164                 return NT_MAIL;
165         case NNMAISW:
166                 return NT_NMAI;
167         }
168
169         /* Before 1999-07-15, garbage was returned if control got here. */
170         return 0;
171 }
172
173
174 static int
175 checkmail(char *user, int datesw, int notifysw, int personal)
176 {
177         int mf, status;
178         char buffer[BUFSIZ];
179         struct stat st;
180         char *maildrop;
181
182         if (personal) {
183                 /*
184                 ** Evaluate the env var and profile only if the check is
185                 ** for the calling user.
186                 */
187                 if ((maildrop = getenv("MAILDROP")) && *maildrop) {
188                         snprintf(buffer, sizeof buffer, "%s",
189                                         toabsdir(maildrop));
190                 } else if ((maildrop=context_find("maildrop")) && *maildrop) {
191                         snprintf(buffer, sizeof buffer, "%s",
192                                         toabsdir(maildrop));
193                 } else {
194                         snprintf(buffer, sizeof buffer, "%s/%s",
195                                         mailspool, user);
196                 }
197         } else {
198                 snprintf(buffer, sizeof(buffer), "%s/%s", mailspool, user);
199         }
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 ? MAILNEW : MAILOLD;
206
207         if (mf & MAILOK) {
208                 if (notifysw & NT_MAIL) {
209                         if (personal) {
210                                 printf("You have ");
211                         } else {
212                                 printf("%s has ", user);
213                         }
214                         if (mf & MAILOK)
215                                 printf(mf & MAILOLD ? "old" : "new");
216                         printf(" mail waiting");
217                 } else {
218                         notifysw = 0;
219                 }
220                 status = 0;
221         } else {
222                 if (notifysw & NT_NMAI) {
223                         if (personal) {
224                                 printf("You don't have any mail waiting");
225                         } else {
226                                 printf("%s doesn't have any mail waiting",
227                                                 user);
228                         }
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                 }
239                 printf("\n");
240         }
241
242         return status;
243 }