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