source: trunk/athena/bin/from/from.c @ 10462

Revision 10462, 12.5 KB checked in by ghudson, 27 years ago (diff)
Don't use regexps; strcmp will do fine. KPOP -> HAVE_KRB4 HESIOD -> HAVE_HESIOD
Line 
1/*
2 * $Id: from.c,v 1.19 1997-10-02 18:57:29 ghudson Exp $
3 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/from/from.c,v $
4 * $Author: ghudson $
5 *
6 * This is the main source file for a KPOP version of the from command.
7 * It was written by Theodore Y. Ts'o, MIT Project Athena.  And later
8 * modified by Jerry Larivee, MIT Project Athena,  to support both KPOP
9 * and the old UCB from functionality.
10 */
11
12#if !defined(lint) && !defined(SABER)
13static char *rcsid = "$Id: from.c,v 1.19 1997-10-02 18:57:29 ghudson Exp $";
14#endif /* lint || SABER */
15
16#include <stdio.h>
17#include <sys/ioctl.h>
18#include <sys/types.h>
19#include <pwd.h>
20#include <string.h>
21#include <stdlib.h>
22#include <ctype.h>
23#include <sys/stat.h>
24#include <termios.h>
25#ifdef HAVE_HESIOD
26#include <hesiod.h>
27#endif
28#define NOTOK (-1)
29#define OK 0
30#define DONE 1
31
32#define MAX_HEADER_LINES 512
33
34#ifdef OFF_SWITCH
35/*
36 * if the ok file does not exist, then print the default error and do not
37 * proceed with the request. If the ok file is missing and the message
38 * file exists, print the contents of the message file and do not proceed
39 * with the request. The message file will be ignored if the ok file exists.
40 */
41
42#define OK_FILE   "/afs/athena.mit.edu/system/config/from/ok"
43#define MSG_FILE  "/afs/athena.mit.edu/system/config/from/message"
44char    *default_err = "Cannot stat the \"ok\" file.. unable to continue with request.";
45#endif /* OFF_SWITCH */
46
47FILE    *sfi, *sfo;
48char    Errmsg[80];
49char    *getlogin(), *parse_from_field();
50extern int      optind;
51extern char     *optarg;
52struct  passwd *getpwuid();
53uid_t   getuid();
54
55int     popmail_debug, verbose, unixmail, popmail, report, totals;
56int     exuser, nonomail;
57char    *progname, *sender, *user, *host;
58
59char    *headers[MAX_HEADER_LINES];
60int     num_headers, skip_message;
61
62char *Short_List[] = {
63        "from", NULL
64        };
65
66char *Report_List[] = {
67        "from", "subject", NULL
68        };
69
70char *Verbose_List[] = {
71        "to", "from", "subject", "date", NULL
72        };
73
74       
75main(argc, argv)
76        int     argc;
77        char    **argv;
78{
79        int     locmail = -1, remmail = -1;
80
81        parse_args(argc,argv);
82        if (unixmail)
83          locmail = getmail_unix(user);
84        if (popmail)
85          remmail = getmail_pop(user, host, locmail);
86        if (!nonomail && (report || verbose || totals) &&
87            (unixmail == 0 || locmail == 0) &&
88            (popmail == 0 || remmail == 0))
89          if (exuser)
90            printf ("%s doesn't have any mail waiting.\n", user);
91          else
92            puts("You don't have any mail waiting.");
93
94        exit (unixmail && locmail < 0 || popmail && remmail < 0);
95}
96
97parse_args(argc,argv)
98        int     argc;
99        register char **argv;
100{
101        register struct passwd *pp;
102        char *cp;
103        int     c;
104        extern char     *getenv();
105#ifdef HAVE_HESIOD
106        struct hes_postoffice *p;
107#endif
108
109        cp = strrchr(argv[0], '/');
110        if (cp)
111            progname = cp + 1;
112        else
113            progname = argv[0];
114        verbose = popmail_debug = 0;
115        host = user = sender = NULL;
116        unixmail = popmail = 1;
117       
118        optind = 1;
119        while ((c = getopt(argc,argv,"rvdnputs:h:")) != EOF)
120                switch(c) {
121                case 'r':
122                        /* report on no mail */
123                        report = 1;
124                        break;
125                case 'n':
126                        nonomail = 1;
127                        break;
128                case 'v':
129                        /* verbose mode */
130                        verbose++;
131                        report = 0;
132                        break;
133                case 'd':
134                        /* debug mode */
135                        popmail_debug++;
136                        break;
137                case 'p':
138                        /* check pop only */
139                        unixmail = 0;
140                        break;
141                case 'u':
142                        /* check unix mail only */
143                        popmail = 0;
144                        break;
145                case 's':
146                        /* check for mail from sender only */
147                        sender = optarg;
148                        break;
149                case 'h':
150                        /* specify pobox host */
151                        host = optarg;
152                        break;
153                case 't':
154                        /* print total messages only */
155                        totals = 1;
156                        report = 0;
157                        verbose = 0;
158                        break;
159                case '?':
160                        lusage();
161                }
162        /* check mail for user */
163        if (optind < argc) {
164                exuser = 1;
165                user = argv[optind];
166        } else {
167                user = getenv ("USER");
168                if (user == NULL)
169                        user = strdup(getlogin());
170                if (!user || !*user) {
171                        pp = getpwuid((int) getuid());
172                        if (pp == NULL) {
173                                fprintf (stderr, "%s: user not in password file\n", progname);
174                                exit(1);
175                        }
176                        user = pp->pw_name;
177                }
178              }
179       
180        if (popmail) {
181          if (!host)
182            host = getenv("MAILHOST");
183#ifdef HAVE_HESIOD
184          if (!host) {
185            p = hes_getmailhost(user);
186            if (p && !strcmp(p->po_type, "POP"))
187              host = p->po_host;
188          }
189#endif
190          if (!host) {
191            if (exuser)
192              fprintf(stderr, "%s: can't find post office server for user %s.\n",
193                      progname, user);
194            else
195              fprintf(stderr, "%s: can't find post office server.\n", progname);
196
197            if (!unixmail) {
198              return(1);
199            }
200            fprintf(stderr, "%s: Trying unix mail drop...\n", progname);
201            popmail = 0;
202          }
203        }
204        return 0;
205}
206
207lusage()
208{
209        fprintf(stderr, "Usage: %s [-v | -r | -t] [-p | -u] [-s sender] [-h host] [user]\n", progname);
210        exit(1);
211}
212
213
214getmail_pop(user, host, printhdr)
215     char       *user,*host;
216     int        printhdr;
217{
218        int nmsgs, nbytes, linelength;
219        char response[128];
220        register int i, j;
221        struct winsize windowsize;
222        int     header_scan();
223
224#ifdef OFF_SWITCH
225        if(pop_ok() == NOTOK)
226             return (1);
227#endif /* OFF_SWITCH */
228
229        if (pop_init(host) == NOTOK) {
230                error(Errmsg);
231                return(1);
232        }
233
234        if ((getline(response, sizeof response, sfi) != OK) ||
235            (*response != '+')){
236                error(response);
237                return -1;
238        }
239
240#ifdef HAVE_KRB4
241        if (pop_command("USER %s", user) == NOTOK ||
242            pop_command("PASS %s", user) == NOTOK)
243#else
244        if (pop_command("USER %s", user) == NOTOK ||
245            pop_command("RPOP %s", user) == NOTOK)
246#endif
247        {
248                error(Errmsg);
249                (void) pop_command("QUIT");
250                return -1;
251        }
252
253        if (pop_stat(&nmsgs, &nbytes) == NOTOK) {
254                error(Errmsg);
255                (void) pop_command("QUIT");
256                return -1;
257        }
258        if (nmsgs == 0) {
259                (void) pop_command("QUIT");
260                return(0);
261        }
262        if (verbose || totals)
263                printf("You have %d %s (%d bytes) on %s%c\n",
264                       nmsgs, nmsgs > 1 ? "messages" : "message",
265                       nbytes, host, verbose ? ':' : '.');
266        if (totals) {
267                (void) pop_command("QUIT");
268                return nmsgs;
269        }
270        if (printhdr)
271                puts("POP mail:");
272
273        /* find out how long the line is for the stdout */
274        if ((ioctl(1, TIOCGWINSZ, (void *)&windowsize) < 0) ||
275            (windowsize.ws_col == 0))
276                windowsize.ws_col = 80;         /* default assume 80 */
277        /* for the console window timestamp */
278        linelength = windowsize.ws_col - 6;
279        if (linelength < 32)
280                linelength = 32;
281       
282        for (i = 1; i <= nmsgs; i++) {
283                if (verbose && !skip_message)
284                        putchar('\n');
285                num_headers = skip_message = 0;
286                if (pop_scan(i, header_scan) == NOTOK) {
287                        error(Errmsg);
288                        (void) pop_command("QUIT");
289                        return -1;
290                }
291                if (report) {
292                        if (!skip_message)
293                                print_report(headers, num_headers, linelength);
294                        else
295                                for (j=0; j<num_headers; j++)
296                                        free(headers[j]);
297                } else {
298                        for (j=0; j<num_headers; j++) {
299                                if (!skip_message)
300                                        puts(headers[j]);
301                                free(headers[j]);
302                        }
303                }
304        }
305       
306        (void) pop_command("QUIT");
307        return nmsgs;
308}
309
310header_scan(line, last_header)
311        char    *line;
312        int     *last_header;
313{
314        char    *keyword, **search_list;
315        register int    i;
316       
317        if (*last_header && isspace(*line)) {
318                headers[num_headers++] = strdup(line);
319                return;
320        }
321
322        for (i=0;line[i] && line[i]!=':';i++) ;
323        keyword=malloc((unsigned) i+1);
324        if (keyword == NULL)
325          {
326            fprintf (stderr, "%s: out of memory\n", progname);
327            exit (1);
328          }
329        (void) strncpy(keyword,line,i);
330        keyword[i]='\0';
331        MakeLowerCase(keyword);
332        if (sender && !strcmp(keyword,"from")) {
333                char *mail_from = parse_from_field(line+i+1);
334                if (strcmp(sender, mail_from))
335                        skip_message++;
336                free (mail_from);
337              }
338        if (verbose)
339          search_list = Verbose_List;
340        else if (report)
341          search_list = Report_List;
342        else
343          search_list = Short_List;
344        if (list_compare(keyword, search_list)) {
345                *last_header = 1;
346                headers[num_headers++] = strdup(line);
347        } else
348                *last_header = 0;       
349}
350
351pop_scan(msgno,action)
352        int     msgno;
353        int     (*action)();
354{       
355        char buf[4096];
356        int     headers = 1;
357        int     scratch = 0;    /* Scratch for action() */
358
359        (void) sprintf(buf, "RETR %d", msgno);
360        if (popmail_debug) fprintf(stderr, "%s\n", buf);
361        if (putline(buf, Errmsg, sfo) == NOTOK)
362                return(NOTOK);
363        if (getline(buf, sizeof buf, sfi) != OK) {
364                (void) strcpy(Errmsg, buf);
365                return(NOTOK);
366        }
367        while (headers) {
368                switch (multiline(buf, sizeof buf, sfi)) {
369                case OK:
370                        if (!*buf)
371                                headers = 0;
372                        (*action)(buf,&scratch);
373                        break;
374                case DONE:
375                        return(OK);
376                case NOTOK:
377                        return(NOTOK);
378                }
379        }
380        while (1) {
381                switch (multiline(buf, sizeof buf, sfi)) {
382                case OK:
383                        break;
384                case DONE:
385                        return(OK);
386                case NOTOK:
387                        return(NOTOK);
388                }
389        }
390}
391
392/* Print error message.  `s1' is printf control string, `s2' is arg for it. */
393
394/*VARARGS1*/
395error (s1, s2)
396     char *s1, *s2;
397{
398  fprintf (stderr, "pop: ");
399  fprintf (stderr, s1, s2);
400  putc ('\n', stderr);
401}
402
403int list_compare(s,list)
404      char *s,**list;
405{
406      char *retval;
407
408      while (*list!=NULL) {
409              if (strcmp(*list++, s) == 0)
410                      return(1);
411      }
412      return(0);
413}
414
415MakeLowerCase(s)
416      char *s;
417{
418      int i;
419      for (i=0;s[i];i++)
420              s[i]=isupper(s[i]) ? tolower(s[i]) : s[i];
421}
422
423char *parse_from_field(str)
424        char    *str;
425{
426        register char   *cp, *scr;
427        char            *stored;
428       
429        stored = scr = strdup(str);
430        while (*scr && isspace(*scr))
431                scr++;
432        if (cp = strchr(scr, '<'))
433                scr = cp+1;
434        if (cp = strchr(scr, '@'))
435                *cp = '\0';
436        if (cp = strchr(scr, '>'))
437                *cp = '\0';
438        scr = strdup(scr);
439        MakeLowerCase(scr);
440        free(stored);
441        return(scr);
442}
443
444/*
445 * Do the old unix mail lookup.
446 */
447
448getmail_unix(user)
449     char *user;
450{
451        char lbuf[BUFSIZ];
452        char lbuf2[BUFSIZ];
453        int havemail = 0, stashed = 0;
454        register char *name;
455        char *getlogin();
456
457        if (sender != NULL)
458          for (name = sender; *name; name++)
459            if (isupper(*name))
460              *name = tolower(*name);
461
462        if (chdir("/usr/spool/mail") < 0) {
463            unixmail = 0;
464            return -1;
465        }
466        if (freopen(user, "r", stdin) == NULL) {
467            if(!popmail)
468                  fprintf(stderr, "Can't open /usr/spool/mail/%s.\n", user);
469            unixmail = 0;
470            return -1;
471        }
472
473        while (fgets(lbuf, sizeof lbuf, stdin) != NULL)
474                if (lbuf[0] == '\n' && stashed) {
475                        stashed = 0;
476                        if (!havemail && !totals && popmail)
477                                puts("Local mail:");
478                        if (!totals)
479                                fputs(lbuf2, stdout);
480                        havemail++;
481                } else if (strncmp(lbuf, "From ", 5) == 0 &&
482                    (sender == NULL || match(&lbuf[4], sender))) {
483                        strcpy(lbuf2, lbuf);
484                        stashed = 1;
485                }
486        if (stashed && !totals)
487                fputs(lbuf2, stdout);
488        if (totals && havemail) {
489                struct stat st;
490                if (fstat(0, &st) != -1)
491                        printf("You have %d local message%s (%d bytes).\n",
492                               havemail, havemail > 1 ? "s" : "",
493                               st.st_size);
494                else
495                        printf("You have %d local message%s.\n",
496                               havemail, havemail > 1 ? "s" : "");
497        }
498        return havemail;
499}
500
501match (line, str)
502        register char *line, *str;
503{
504        register char ch;
505
506        while (*line == ' ' || *line == '\t')
507                ++line;
508        if (*line == '\n')
509                return (0);
510        while (*str && *line != ' ' && *line != '\t' && *line != '\n') {
511                ch = isupper(*line) ? tolower(*line) : *line;
512                if (ch != *str++)
513                        return (0);
514                line++;
515        }
516        return (*str == '\0');
517}
518
519print_report(headers, num_headers, winlength)
520     char **headers;
521     int num_headers, winlength;
522{
523  int j, len;
524  char *p, *from_field = 0, *subject_field = 0, *buf, *buf1;
525 
526  for(j = 0; j < num_headers; j++) {
527    p = strchr(headers[j], ':');
528    if (p == NULL)
529      continue;
530
531    if (strncmp("From", headers[j], 4) == 0) {
532      p++;
533      while (p[0] == ' ')
534        p++;
535      from_field = p;
536      if (subject_field)
537        break;
538    }
539    else if (strncmp("Subject", headers[j], 7) == 0) {
540      p++;
541      while (p[0] == ' ')
542        p++;
543      subject_field = p;
544      if (from_field)
545        break;
546    }
547  }
548
549  buf = malloc(winlength+1);  /* add 1 for the NULL terminator */
550  if (buf == NULL)
551    {
552      fprintf (stderr, "from: out of memory\n");
553      exit (1);
554    }   
555  buf[0] = '\0';
556  buf[winlength] = '\0';
557  if (from_field)
558    strncpy(buf, from_field, winlength);
559  else
560    strncpy(buf, "<<unknown sender>>", winlength);
561  len = strlen(buf);
562  if  (len < 30)
563    len = 30;
564
565  buf1 = malloc(winlength-len+1);  /* add 1 for the NULL terminator */
566  if (buf1 == NULL)
567    {
568      fprintf (stderr, "from: out of memory\n");
569      exit (1);
570    }   
571  buf1[0] = '\0';
572
573  if (winlength - len - 1 < 1)
574    subject_field = NULL;
575
576  if (subject_field)
577    {
578      strncpy(buf1, subject_field, winlength - len - 1);
579      buf1[winlength - len - 1] = 0;
580    }
581 
582  printf("%-30s %s\n", buf, buf1);
583
584  free(buf);
585  free(buf1);
586  for (j = 0; j < num_headers; j++)
587    free(headers[j]);
588}
589
590
591#ifdef OFF_SWITCH
592
593pop_ok()
594{
595  FILE *fp;
596  struct stat sbuf;
597  char buf[BUFSIZ];
598
599  if(stat(OK_FILE, &sbuf) == 0)
600       return(OK);
601
602  if(!(fp = fopen(MSG_FILE, "r")))  {
603       printf("%s\n", default_err);
604       return(NOTOK);
605  }
606
607  memset(buf, 0, sizeof(buf));
608  while(fgets(buf, sizeof(buf), fp))
609      printf("%s", buf);
610  fclose(fp);
611  return(NOTOK);
612}
613
614#endif /* OFF_SWITCH */
615 
Note: See TracBrowser for help on using the repository browser.