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