[BACK]Return to io.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / calendar

Diff for /src/usr.bin/calendar/io.c between version 1.3 and 1.46

version 1.3, 1998/02/14 21:07:21 version 1.46, 2017/08/21 21:41:13
Line 12 
Line 12 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software   * 3. Neither the name of the University nor the names of its contributors
  *    must display the following acknowledgement:  
  *      This product includes software developed by the University of  
  *      California, Berkeley and its contributors.  
  * 4. Neither the name of the University nor the names of its contributors  
  *    may be used to endorse or promote products derived from this software   *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.   *    without specific prior written permission.
  *   *
Line 33 
Line 29 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
 #ifndef lint  
 static const char copyright[] =  
 "@(#) Copyright (c) 1989, 1993\n\  
         The Regents of the University of California.  All rights reserved.\n";  
 #endif /* not lint */  
   
 #ifndef lint  
 #if 0  
 static const char sccsid[] = "@(#)calendar.c  8.3 (Berkeley) 3/25/94";  
 #else  
 static char rcsid[] = "$OpenBSD$";  
 #endif  
 #endif /* not lint */  
   
 #include <sys/param.h>  
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/time.h>  #include <sys/time.h>
 #include <sys/types.h>  #include <sys/types.h>
Line 57 
Line 38 
 #include <ctype.h>  #include <ctype.h>
 #include <err.h>  #include <err.h>
 #include <errno.h>  #include <errno.h>
   #include <fcntl.h>
 #include <locale.h>  #include <locale.h>
 #include <pwd.h>  #include <pwd.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   #include <limits.h>
   
 #include "pathnames.h"  #include "pathnames.h"
 #include "calendar.h"  #include "calendar.h"
   
   
 char *calendarFile = "calendar";  /* default calendar file */  
 char *calendarHome = ".calendar"; /* HOME */  
 char *calendarNoMail = "nomail";  /* don't sent mail if this file exist */  
   
 struct fixs neaster, npaskha;  
   
 struct iovec header[] = {  struct iovec header[] = {
         {"From: ", 6},          { "From: ", 6 },
         {NULL, 0},          { NULL, 0 },
         {" (Reminder Service)\nTo: ", 24},          { " (Reminder Service)\nTo: ", 24 },
         {NULL, 0},          { NULL, 0 },
         {"\nSubject: ", 10},          { "\nSubject: ", 10 },
         {NULL, 0},          { NULL, 0 },
         {"'s Calendar\nPrecedence: bulk\n\n",  30},          { "'s Calendar\nPrecedence: bulk\n",  29 },
           { "Auto-Submitted: auto-generated\n\n", 32 },
 };  };
   
   
 void  void
 cal()  cal(void)
 {  {
         register int printing;          int ch, l, i, bodun = 0, bodun_maybe = 0, var, printing;
         register char *p;          struct event *events, *cur_evt, *ev1, *tmp;
           char buf[2048 + 1], *prefix = NULL, *p;
           struct match *m;
         FILE *fp;          FILE *fp;
         int ch, l;  
         int month;  
         int day;  
         int var;  
         char buf[2048 + 1];  
   
           events = NULL;
           cur_evt = NULL;
         if ((fp = opencal()) == NULL)          if ((fp = opencal()) == NULL)
                 return;                  return;
         for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) {          for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) {
Line 104 
Line 81 
                         *p = '\0';                          *p = '\0';
                 else                  else
                         while ((ch = getchar()) != '\n' && ch != EOF);                          while ((ch = getchar()) != '\n' && ch != EOF);
                 for (l = strlen(buf);                  for (l = strlen(buf); l > 0 && isspace(buf[l - 1]); l--)
                      l > 0 && isspace(buf[l - 1]);  
                      l--)  
                         ;                          ;
                 buf[l] = '\0';                  buf[l] = '\0';
                 if (buf[0] == '\0')                  if (buf[0] == '\0')
Line 114 
Line 89 
                 if (strncmp(buf, "LANG=", 5) == 0) {                  if (strncmp(buf, "LANG=", 5) == 0) {
                         (void) setlocale(LC_ALL, buf + 5);                          (void) setlocale(LC_ALL, buf + 5);
                         setnnames();                          setnnames();
                           if (!strcmp(buf + 5, "ru_RU.UTF-8") ||
                               !strcmp(buf + 5, "uk_UA.UTF-8") ||
                               !strcmp(buf + 5, "by_BY.UTF-8")) {
                                   bodun_maybe++;
                                   bodun = 0;
                                   free(prefix);
                                   prefix = NULL;
                           } else
                                   bodun_maybe = 0;
                         continue;                          continue;
                 }                  } else if (strncmp(buf, "CALENDAR=", 9) == 0) {
                 if (strncasecmp(buf, "Easter=", 7) == 0 && buf[7]) {                          char *ep;
                         if (neaster.name != NULL)  
                                 free(neaster.name);                          if (buf[9] == '\0')
                         if ((neaster.name = strdup(buf + 7)) == NULL)                                  calendar = 0;
                                 errx(1, "cannot allocate memory");                          else if (!strcasecmp(buf + 9, "julian")) {
                         neaster.len = strlen(buf + 7);                                  calendar = JULIAN;
                                   errno = 0;
                                   julian = strtoul(buf + 14, &ep, 10);
                                   if (buf[0] == '\0' || *ep != '\0')
                                           julian = 13;
                                   if ((errno == ERANGE && julian == ULONG_MAX) ||
                                       julian > 14)
                                           errx(1, "Julian calendar offset is too large");
                           } else if (!strcasecmp(buf + 9, "gregorian"))
                                   calendar = GREGORIAN;
                           else if (!strcasecmp(buf + 9, "lunar"))
                                   calendar = LUNAR;
                   } else if (bodun_maybe && strncmp(buf, "BODUN=", 6) == 0) {
                           bodun++;
                           free(prefix);
                           if ((prefix = strdup(buf + 6)) == NULL)
                                   err(1, NULL);
                         continue;                          continue;
                 }                  }
                 if (strncasecmp(buf, "Paskha=", 7) == 0 && buf[7]) {                  /* User defined names for special events */
                         if (npaskha.name != NULL)                  if ((p = strchr(buf, '='))) {
                                 free(npaskha.name);                          for (i = 0; i < NUMEV; i++) {
                         if ((npaskha.name = strdup(buf + 7)) == NULL)                                  if (strncasecmp(buf, spev[i].name,
                                 errx(1, "cannot allocate memory");                                      spev[i].nlen) == 0 &&
                         npaskha.len = strlen(buf + 7);                                      (p - buf == spev[i].nlen) &&
                         continue;                                      buf[spev[i].nlen + 1]) {
                                           p++;
                                           free(spev[i].uname);
                                           if ((spev[i].uname = strdup(p)) == NULL)
                                                   err(1, NULL);
                                           spev[i].ulen = strlen(p);
                                           i = NUMEV + 1;
                                   }
                           }
                           if (i > NUMEV)
                                   continue;
                 }                  }
                 if (buf[0] != '\t') {                  if (buf[0] != '\t') {
                         printing = isnow(buf, &month, &day, &var) ? 1 : 0;                          printing = (m = isnow(buf, bodun)) ? 1 : 0;
                         if ((p = strchr(buf, '\t')) == NULL)                          if ((p = strchr(buf, '\t')) == NULL) {
                                   printing = 0;
                                 continue;                                  continue;
                           }
                           /* Need the following to catch hardwired "variable"
                            * dates */
                         if (p > buf && p[-1] == '*')                          if (p > buf && p[-1] == '*')
                                 var = 1;                                  var = 1;
                           else
                                   var = 0;
                         if (printing) {                          if (printing) {
                                 struct tm tm;                                  struct match *foo;
                                 char dbuf[30];  
   
                                 tm.tm_sec = 0;  /* unused */                                  ev1 = NULL;
                                 tm.tm_min = 0;  /* unused */                                  while (m) {
                                 tm.tm_hour = 0; /* unused */                                          cur_evt = malloc(sizeof(struct event));
                                 tm.tm_wday = 0; /* unused */                                          if (cur_evt == NULL)
                                 tm.tm_mon = month - 1;                                                  err(1, NULL);
                                 tm.tm_mday = day;  
                                 tm.tm_year = tp->tm_year; /* unused */                                          cur_evt->when = m->when;
                                 tm.tm_isdst = tp->tm_isdst; /* unused */                                          snprintf(cur_evt->print_date,
                                 tm.tm_gmtoff = tp->tm_gmtoff; /* unused */                                              sizeof(cur_evt->print_date), "%s%c",
                                 tm.tm_zone = tp->tm_zone; /* unused */                                              m->print_date, (var + m->var) ? '*' : ' ');
                                 (void)strftime(dbuf, sizeof(dbuf), "%a %b %d",                                          if (ev1) {
                                     &tm);                                                  cur_evt->desc = ev1->desc;
                                 (void)fprintf(fp, "%s%c%s\n",                                                  cur_evt->ldesc = NULL;
                                     dbuf + 4/* skip weekdays */,                                          } else {
                                     var ? '*' : ' ', p);                                                  if (m->bodun && prefix) {
                                                           if (asprintf(&cur_evt->ldesc,
                                                               "\t%s %s", prefix,
                                                               p + 1) == -1)
                                                                   err(1, NULL);
                                                   } else if ((cur_evt->ldesc =
                                                       strdup(p)) == NULL)
                                                           err(1, NULL);
                                                   cur_evt->desc = &(cur_evt->ldesc);
                                                   ev1 = cur_evt;
                                           }
                                           insert(&events, cur_evt);
                                           foo = m;
                                           m = m->next;
                                           free(foo);
                                   }
                         }                          }
                   } else if (printing) {
                           if (asprintf(&p, "%s\n%s", ev1->ldesc,
                               buf) == -1)
                                   err(1, NULL);
                           free(ev1->ldesc);
                           ev1->ldesc = p;
                 }                  }
                 else if (printing)  
                         fprintf(fp, "%s\n", buf);  
         }          }
           tmp = events;
           while (tmp) {
                   (void)fprintf(fp, "%s%s\n", tmp->print_date, *(tmp->desc));
                   tmp = tmp->next;
           }
           tmp = events;
           while (tmp) {
                   events = tmp;
                   free(tmp->ldesc);
                   tmp = tmp->next;
                   free(events);
           }
         closecal(fp);          closecal(fp);
 }  }
   
 int  int
 getfield(p, endp, flags)  getfield(char *p, char **endp, int *flags)
         char *p, **endp;  
         int *flags;  
 {  {
         int val, var;          int val, var, i;
         char *start, savech;          char *start, savech;
   
         for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p)          for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p) &&
               *p != '*' && *p != '\t'; ++p)
                 ;                  ;
         if (*p == '*') {                        /* `*' is current month */          if (*p == '*') {                        /* `*' is every month */
                 *flags |= F_ISMONTH;                  *flags |= F_ISMONTH;
                 *endp = p+1;                  *endp = p+1;
                 return (tp->tm_mon + 1);                  return (-1);    /* means 'every month' */
         }          }
         if (isdigit(*p)) {          if (isdigit((unsigned char)*p)) {
                 val = strtol(p, &p, 10);        /* if 0, it's failure */                  val = strtol(p, &p, 10);        /* if 0, it's failure */
                 for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p)                  for (; !isdigit((unsigned char)*p) &&
                       !isalpha((unsigned char)*p) && *p != '*'; ++p)
                         ;                          ;
                 *endp = p;                  *endp = p;
                 return (val);                  return (val);
         }          }
         for (start = p; isalpha(*++p);)          for (start = p; isalpha((unsigned char)*++p);)
                 ;                  ;
   
         /* Sunday-1 */          /* Sunday-1 */
         if (*p == '+' || *p == '-')          if (*p == '+' || *p == '-')
             for(; isdigit(*++p);)                  for(; isdigit((unsigned char)*++p); )
                 ;                          ;
   
         savech = *p;          savech = *p;
         *p = '\0';          *p = '\0';
Line 204 
Line 250 
   
         /* Day */          /* Day */
         else if ((val = getday(start)) != 0) {          else if ((val = getday(start)) != 0) {
             *flags |= F_ISDAY;                  *flags |= F_ISDAY;
   
             /* variable weekday */                  /* variable weekday */
             if ((var = getdayvar(start)) != 0) {                  if ((var = getdayvar(start)) != 0) {
                 if (var <=5 && var >= -4)                          if (var <= 5 && var >= -4)
                     val += var * 10;                                  val += var * 10;
 #ifdef DEBUG  #ifdef DEBUG
                 printf("var: %d\n", var);                          printf("var: %d\n", var);
 #endif  #endif
             }                  }
         }          }
   
         /* Easter */          /* Try specials (Easter, Paskha, ...) */
         else if ((val = geteaster(start, tp->tm_year + 1900)) != 0)  
             *flags |= F_EASTER;  
   
         /* Paskha */  
         else if ((val = getpaskha(start, tp->tm_year + 1900)) != 0)  
             *flags |= F_EASTER;  
   
         /* undefined rest */  
         else {          else {
                 *p = savech;                  for (i = 0; i < NUMEV; i++) {
                 return (0);                          if (strncasecmp(start, spev[i].name, spev[i].nlen) == 0) {
                                   start += spev[i].nlen;
                                   val = i + 1;
                                   i = NUMEV + 1;
                           } else if (spev[i].uname != NULL &&
                               strncasecmp(start, spev[i].uname, spev[i].ulen) == 0) {
                                   start += spev[i].ulen;
                                   val = i + 1;
                                   i = NUMEV + 1;
                           }
                   }
                   if (i > NUMEV) {
                           const char *errstr;
   
                           switch (*start) {
                           case '-':
                           case '+':
                                   var = strtonum(start + 1, 0, 365, &errstr);
                                   if (errstr)
                                           return (0); /* Someone is just being silly */
                                   if (*start == '-')
                                           var = -var;
                                   val += (NUMEV + 1) * var;
                                   /* We add one to the matching event and multiply by
                                    * (NUMEV + 1) so as not to return 0 if there's a match.
                                    * val will overflow if there is an obscenely large
                                    * number of special events. */
                                   break;
                           }
                           *flags |= F_SPECIAL;
                   }
                   if (!(*flags & F_SPECIAL)) {
                           /* undefined rest */
                           *p = savech;
                           return (0);
                   }
         }          }
         for (*p = savech; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p)          for (*p = savech; !isdigit((unsigned char)*p) &&
               !isalpha((unsigned char)*p) && *p != '*' && *p != '\t'; ++p)
                 ;                  ;
         *endp = p;          *endp = p;
         return (val);          return (val);
 }  }
   
 char path[MAXPATHLEN];  
   
 FILE *  FILE *
 opencal()  opencal(void)
 {  {
         int fd, pdes[2];          int pdes[2], fdin;
         struct stat sbuf;          struct stat st;
   
         /* open up calendar file as stdin */          /* open up calendar file as stdin */
         if (!freopen(calendarFile, "r", stdin)) {          if ((fdin = open(calendarFile, O_RDONLY)) == -1 ||
                 if (doall) {              fstat(fdin, &st) == -1 || !S_ISREG(st.st_mode)) {
                     if (chdir(calendarHome) != 0)                  if (!doall) {
                         return (NULL);                          char *home = getenv("HOME");
                     if (stat(calendarNoMail, &sbuf) == 0)                          if (home == NULL || *home == '\0')
                         return (NULL);                                  errx(1, "cannot get home directory");
                     if (!freopen(calendarFile, "r", stdin))                          if (!(chdir(home) == 0 &&
                         return (NULL);                              chdir(calendarHome) == 0 &&
                 } else {                              (fdin = open(calendarFile, O_RDONLY)) != -1))
                         chdir(getenv("HOME"));                                  errx(1, "no calendar file: ``%s'' or ``~/%s/%s''",
                         if (!(chdir(calendarHome) == 0 &&  
                               freopen(calendarFile, "r", stdin)))  
                                 errx(1, "no calendar file: ``%s'' or ``~/%s/%s",  
                                     calendarFile, calendarHome, calendarFile);                                      calendarFile, calendarHome, calendarFile);
                 }                  }
         }          }
         if (pipe(pdes) < 0)  
           if (pipe(pdes) < 0) {
                   close(fdin);
                 return (NULL);                  return (NULL);
           }
         switch (vfork()) {          switch (vfork()) {
         case -1:                        /* error */          case -1:                        /* error */
                 (void)close(pdes[0]);                  (void)close(pdes[0]);
                 (void)close(pdes[1]);                  (void)close(pdes[1]);
                   close(fdin);
                 return (NULL);                  return (NULL);
         case 0:          case 0:
                 /* child -- stdin already setup, set stdout to pipe input */                  dup2(fdin, STDIN_FILENO);
                   /* child -- set stdout to pipe input */
                 if (pdes[1] != STDOUT_FILENO) {                  if (pdes[1] != STDOUT_FILENO) {
                         (void)dup2(pdes[1], STDOUT_FILENO);                          (void)dup2(pdes[1], STDOUT_FILENO);
                         (void)close(pdes[1]);                          (void)close(pdes[1]);
                 }                  }
                 (void)close(pdes[0]);                  (void)close(pdes[0]);
                 (void)setuid(geteuid());                  /*
                 (void)setgid(getegid());                   * Set stderr to /dev/null.  Necessary so that cron does not
                 execl(_PATH_CPP, "cpp", "-P", "-I.", _PATH_INCLUDE, NULL);                   * wait for cpp to finish if it's running calendar -a.
                    */
                   if (doall) {
                           int fderr;
                           fderr = open(_PATH_DEVNULL, O_WRONLY, 0);
                           if (fderr == -1)
                                   _exit(0);
                           (void)dup2(fderr, STDERR_FILENO);
                           (void)close(fderr);
                   }
                   execl(_PATH_CPP, "cpp", "-traditional", "-undef", "-U__GNUC__",
                       "-P", "-I.", _PATH_INCLUDE, (char *)NULL);
                 warn(_PATH_CPP);                  warn(_PATH_CPP);
                 _exit(1);                  _exit(1);
         }          }
Line 290 
Line 376 
                 return (stdout);                  return (stdout);
   
         /* set output to a temporary file, so if no output don't send mail */          /* set output to a temporary file, so if no output don't send mail */
         (void)snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP);          return(tmpfile());
         if ((fd = mkstemp(path)) < 0)  
                 return (NULL);  
         return (fdopen(fd, "w+"));  
 }  }
   
 void  void
 closecal(fp)  closecal(FILE *fp)
         FILE *fp;  
 {  {
         struct stat sbuf;          struct stat sbuf;
         int nread, pdes[2], status;          int nread, pdes[2], status;
         char buf[1024];          char buf[1024];
           pid_t pid;
   
         if (!doall)          if (!doall)
                 return;                  return;
Line 312 
Line 395 
                 goto done;                  goto done;
         if (pipe(pdes) < 0)          if (pipe(pdes) < 0)
                 goto done;                  goto done;
         switch (vfork()) {          switch ((pid = vfork())) {
         case -1:                        /* error */          case -1:                        /* error */
                 (void)close(pdes[0]);                  (void)close(pdes[0]);
                 (void)close(pdes[1]);                  (void)close(pdes[1]);
Line 324 
Line 407 
                         (void)close(pdes[0]);                          (void)close(pdes[0]);
                 }                  }
                 (void)close(pdes[1]);                  (void)close(pdes[1]);
                 (void)setuid(geteuid());  
                 (void)setgid(getegid());  
                 execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",                  execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
                     "\"Reminder Service\"", "-f", "root", NULL);                      "\"Reminder Service\"", (char *)NULL);
                 warn(_PATH_SENDMAIL);                  warn(_PATH_SENDMAIL);
                 _exit(1);                  _exit(1);
         }          }
Line 336 
Line 417 
   
         header[1].iov_base = header[3].iov_base = pw->pw_name;          header[1].iov_base = header[3].iov_base = pw->pw_name;
         header[1].iov_len = header[3].iov_len = strlen(pw->pw_name);          header[1].iov_len = header[3].iov_len = strlen(pw->pw_name);
         writev(pdes[1], header, 7);          writev(pdes[1], header, 8);
         while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)          while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
                 (void)write(pdes[1], buf, nread);                  (void)write(pdes[1], buf, nread);
         (void)close(pdes[1]);          (void)close(pdes[1]);
 done:   (void)fclose(fp);  done:   (void)fclose(fp);
         (void)unlink(path);          while (waitpid(pid, &status, 0) == -1) {
         while (wait(&status) >= 0);                  if (errno != EINTR)
                           break;
           }
   }
   
   
   void
   insert(struct event **head, struct event *cur_evt)
   {
           struct event *tmp, *tmp2;
   
           if (*head) {
                   /* Insert this one in order */
                   tmp = *head;
                   tmp2 = NULL;
                   while (tmp->next &&
                       tmp->when <= cur_evt->when) {
                           tmp2 = tmp;
                           tmp = tmp->next;
                   }
                   if (tmp->when > cur_evt->when) {
                           cur_evt->next = tmp;
                           if (tmp2)
                                   tmp2->next = cur_evt;
                           else
                                   *head = cur_evt;
                   } else {
                           cur_evt->next = tmp->next;
                           tmp->next = cur_evt;
                   }
           } else {
                   *head = cur_evt;
                   cur_evt->next = NULL;
           }
 }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.46