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

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