the default path is /var/mail, not /var/spool/mail...
[unix-history] / usr / src / usr.bin / cal / cal.c
index 94f0244..9cdda6f 100644 (file)
@@ -1,64 +1,77 @@
 /*
 /*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kim Letkeman.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * Kim Letkeman.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993, 1994\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)cal.c      4.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)cal.c      8.4 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
-#include <sys/time.h>
-#include <stdio.h>
+
 #include <ctype.h>
 #include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
 
 #define        THURSDAY                4               /* for reformation */
 #define        SATURDAY                6               /* 1 Jan 1 was a Saturday */
 
 #define        THURSDAY                4               /* for reformation */
 #define        SATURDAY                6               /* 1 Jan 1 was a Saturday */
+
 #define        FIRST_MISSING_DAY       639787          /* 3 Sep 1752 */
 #define        NUMBER_MISSING_DAYS     11              /* 11 day correction */
 #define        FIRST_MISSING_DAY       639787          /* 3 Sep 1752 */
 #define        NUMBER_MISSING_DAYS     11              /* 11 day correction */
-#define        SPACE                   99              /* used in day array */
+
+#define        MAXDAYS                 42              /* max slots in a month array */
+#define        SPACE                   -1              /* used in day array */
 
 static int days_in_month[2][13] = {
        {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 };
 
 
 static int days_in_month[2][13] = {
        {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 };
 
-static int sep1752[42] = {
-       SPACE, SPACE,     1,     2,    14,    15,    16,
-          17,    18,    19,    20,    21,    22,    23,
-          24,    25,    26,    27,    28,    29,    30,
-       SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
-       SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
-       SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
+int sep1752[MAXDAYS] = {
+       SPACE,  SPACE,  1,      2,      14,     15,     16,
+       17,     18,     19,     20,     21,     22,     23,
+       24,     25,     26,     27,     28,     29,     30,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+}, j_sep1752[MAXDAYS] = {
+       SPACE,  SPACE,  245,    246,    258,    259,    260,
+       261,    262,    263,    264,    265,    266,    267,
+       268,    269,    270,    271,    272,    273,    274,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+}, empty[MAXDAYS] = {
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
+       SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,  SPACE,
 };
 
 };
 
-static char *month_names[12] = {
+char *month_names[12] = {
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December",
 };
 
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December",
 };
 
-static char *day_headings = " S  M Tu  W Th  F  S";
+char *day_headings = " S  M Tu  W Th  F  S";
+char *j_day_headings = "  S   M  Tu   W  Th   F   S";
 
 /* leap year -- account for gregorian reformation in 1752 */
 #define        leap_year(yr) \
 
 /* leap year -- account for gregorian reformation in 1752 */
 #define        leap_year(yr) \
@@ -77,19 +90,34 @@ static char *day_headings = " S  M Tu  W Th  F  S";
 #define        leap_years_since_year_1(yr) \
        ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
 
 #define        leap_years_since_year_1(yr) \
        ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
 
+int julian;
+
+void   ascii_day __P((char *, int));
+void   center __P((char *, int, int));
+void   day_array __P((int, int, int *));
+int    day_in_week __P((int, int, int));
+int    day_in_year __P((int, int, int));
+void   j_yearly __P((int));
+void   monthly __P((int, int));
+void   trim_trailing_spaces __P((char *));
+void   usage __P((void));
+void   yearly __P((int));
+
+int
 main(argc, argv)
        int argc;
        char **argv;
 {
 main(argc, argv)
        int argc;
        char **argv;
 {
-       extern char *optarg;
-       extern int optind;
        struct tm *local_time;
        struct tm *local_time;
-       time_t now, time();
+       time_t now;
        int ch, month, year, yflag;
 
        yflag = 0;
        int ch, month, year, yflag;
 
        yflag = 0;
-       while ((ch = getopt(argc, argv, "y")) != EOF)
+       while ((ch = getopt(argc, argv, "jy")) != EOF)
                switch(ch) {
                switch(ch) {
+               case 'j':
+                       julian = 1;
+                       break;
                case 'y':
                        yflag = 1;
                        break;
                case 'y':
                        yflag = 1;
                        break;
@@ -100,18 +128,15 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
+       month = 0;
        switch(argc) {
        case 2:
        switch(argc) {
        case 2:
-               if ((month = atoi(*argv++)) <= 0 || month > 12) {
-                       (void)fprintf(stderr, "cal: illegal month value.\n");
-                       exit(1);
-               }
+               if ((month = atoi(*argv++)) < 1 || month > 12)
+                       errx(1, "illegal month value: use 1-12");
                /* FALLTHROUGH */
        case 1:
                /* FALLTHROUGH */
        case 1:
-               if ((year = atoi(*argv)) <= 0 || year > 9999) {
-                       (void)fprintf(stderr, "cal: illegal year value.\n");
-                       exit(1);
-               }
+               if ((year = atoi(*argv)) < 1 || year > 9999)
+                       errx(1, "illegal year value: use 1-9999");
                break;
        case 0:
                (void)time(&now);
                break;
        case 0:
                (void)time(&now);
@@ -123,108 +148,157 @@ main(argc, argv)
        default:
                usage();
        }
        default:
                usage();
        }
+
        if (month)
        if (month)
-               print_monthly_calendar(month, year);
+               monthly(month, year);
+       else if (julian)
+               j_yearly(year);
        else
        else
-               print_yearly_calendar(year);
+               yearly(year);
        exit(0);
 }
 
        exit(0);
 }
 
-print_monthly_calendar(month, year)
+#define        DAY_LEN         3               /* 3 spaces per day */
+#define        J_DAY_LEN       4               /* 4 spaces per day */
+#define        WEEK_LEN        20              /* 7 * 3 - one space at the end */
+#define        J_WEEK_LEN      27              /* 7 * 4 - one space at the end */
+#define        HEAD_SEP        2               /* spaces between day headings */
+#define        J_HEAD_SEP      2
+
+void
+monthly(month, year)
        int month, year;
 {
        int month, year;
 {
-       register int col, row;
-       register char *p;
-       int days[42];
-       char lineout[30];
-
-       generate_day_array(month, year, days);
-       (void)printf("   %s %d\n%s\n",
-           month_names[month - 1], year, day_headings);
+       int col, row, len, days[MAXDAYS];
+       char *p, lineout[30];
+
+       day_array(month, year, days);
+       len = sprintf(lineout, "%s %d", month_names[month - 1], year);
+       (void)printf("%*s%s\n%s\n",
+           ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "",
+           lineout, julian ? j_day_headings : day_headings);
        for (row = 0; row < 6; row++) {
        for (row = 0; row < 6; row++) {
-               for (col = 0, p = lineout; col < 7; col++, p += 3)
+               for (col = 0, p = lineout; col < 7; col++,
+                   p += julian ? J_DAY_LEN : DAY_LEN)
                        ascii_day(p, days[row * 7 + col]);
                        ascii_day(p, days[row * 7 + col]);
+               *p = '\0';
                trim_trailing_spaces(lineout);
                (void)printf("%s\n", lineout);
        }
 }
 
                trim_trailing_spaces(lineout);
                (void)printf("%s\n", lineout);
        }
 }
 
-print_yearly_calendar(year)
+void
+j_yearly(year)
        int year;
 {
        int year;
 {
-       register int col, *dp, i, month, row, which_cal;
-       register char *p;
-       int days[12][42];
-       char lineout[80];
+       int col, *dp, i, month, row, which_cal;
+       int days[12][MAXDAYS];
+       char *p, lineout[80];
 
 
-       (void)printf("\n\n\n\t\t\t\t%d\n\n", year);
+       (void)sprintf(lineout, "%d", year);
+       center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
+       (void)printf("\n\n");
        for (i = 0; i < 12; i++)
        for (i = 0; i < 12; i++)
-               generate_day_array(i + 1, year, &days[i][0]);
+               day_array(i + 1, year, days[i]);
        (void)memset(lineout, ' ', sizeof(lineout) - 1);
        lineout[sizeof(lineout) - 1] = '\0';
        (void)memset(lineout, ' ', sizeof(lineout) - 1);
        lineout[sizeof(lineout) - 1] = '\0';
-       for (month = 0; month < 12; month += 3) {
-               (void)printf("\t %.3s\t\t\t%.3s\t\t       %.3s\n",
-                   month_names[month], month_names[month + 1],
-                   month_names[month + 2]);
-               for (i = 0; i < 3; i++) {
-                       (void)printf("%s", day_headings);
-                       if (i < 2)
-                               (void)printf("   ");
+       for (month = 0; month < 12; month += 2) {
+               center(month_names[month], J_WEEK_LEN, J_HEAD_SEP);
+               center(month_names[month + 1], J_WEEK_LEN, 0);
+               (void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
+                   j_day_headings);
+               for (row = 0; row < 6; row++) {
+                       for (which_cal = 0; which_cal < 2; which_cal++) {
+                               p = lineout + which_cal * (J_WEEK_LEN + 2);
+                               dp = &days[month + which_cal][row * 7];
+                               for (col = 0; col < 7; col++, p += J_DAY_LEN)
+                                       ascii_day(p, *dp++);
+                       }
+                       *p = '\0';
+                       trim_trailing_spaces(lineout);
+                       (void)printf("%s\n", lineout);
                }
                }
-               (void)printf("\n");
+       }
+       (void)printf("\n");
+}
+
+void
+yearly(year)
+       int year;
+{
+       int col, *dp, i, month, row, which_cal;
+       int days[12][MAXDAYS];
+       char *p, lineout[80];
+
+       (void)sprintf(lineout, "%d", year);
+       center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0);
+       (void)printf("\n\n");
+       for (i = 0; i < 12; i++)
+               day_array(i + 1, year, days[i]);
+       (void)memset(lineout, ' ', sizeof(lineout) - 1);
+       lineout[sizeof(lineout) - 1] = '\0';
+       for (month = 0; month < 12; month += 3) {
+               center(month_names[month], WEEK_LEN, HEAD_SEP);
+               center(month_names[month + 1], WEEK_LEN, HEAD_SEP);
+               center(month_names[month + 2], WEEK_LEN, 0);
+               (void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
+                   "", day_headings, HEAD_SEP, "", day_headings);
                for (row = 0; row < 6; row++) {
                        for (which_cal = 0; which_cal < 3; which_cal++) {
                for (row = 0; row < 6; row++) {
                        for (which_cal = 0; which_cal < 3; which_cal++) {
-                               p = lineout + which_cal * 23;
+                               p = lineout + which_cal * (WEEK_LEN + 2);
                                dp = &days[month + which_cal][row * 7];
                                dp = &days[month + which_cal][row * 7];
-                               for (col = 0; col < 7; col++, p += 3)
+                               for (col = 0; col < 7; col++, p += DAY_LEN)
                                        ascii_day(p, *dp++);
                        }
                                        ascii_day(p, *dp++);
                        }
+                       *p = '\0';
                        trim_trailing_spaces(lineout);
                        (void)printf("%s\n", lineout);
                }
        }
                        trim_trailing_spaces(lineout);
                        (void)printf("%s\n", lineout);
                }
        }
-       (void)printf("\n\n\n");
+       (void)printf("\n");
 }
 
 /*
 }
 
 /*
- * generate_day_array --
+ * day_array --
  *     Fill in an array of 42 integers with a calendar.  Assume for a moment
  *     that you took the (maximum) 6 rows in a calendar and stretched them
  *     out end to end.  You would have 42 numbers or spaces.  This routine
  *     builds that array for any month from Jan. 1 through Dec. 9999.
  */
  *     Fill in an array of 42 integers with a calendar.  Assume for a moment
  *     that you took the (maximum) 6 rows in a calendar and stretched them
  *     out end to end.  You would have 42 numbers or spaces.  This routine
  *     builds that array for any month from Jan. 1 through Dec. 9999.
  */
-generate_day_array(month, year, days)
-       int month, year, *days;
+void
+day_array(month, year, days)
+       int month, year;
+       int *days;
 {
 {
-       register int i, day, dw, dm;
+       int day, dw, dm;
 
 
+       if (month == 9 && year == 1752) {
+               memmove(days,
+                       julian ? j_sep1752 : sep1752, MAXDAYS * sizeof(int));
+               return;
+       }
+       memmove(days, empty, MAXDAYS * sizeof(int));
        dm = days_in_month[leap_year(year)][month];
        dw = day_in_week(1, month, year);
        dm = days_in_month[leap_year(year)][month];
        dw = day_in_week(1, month, year);
-       if (month == 9 && year == 1752)
-               for (i = 0; i < 42; i++)
-                       days[i] = sep1752[i];
-       else {
-               for (i = 0; i < 42; i++)
-                       days[i] = SPACE;
-               for (day = 1, i = dw; day <= dm; ++day, ++i)
-                       days[i] = day;
-       }
+       day = julian ? day_in_year(1, month, year) : 1;
+       while (dm--)
+               days[dw++] = day++;
 }
 
 /*
  * day_in_year --
  *     return the 1 based day number within the year
  */
 }
 
 /*
  * day_in_year --
  *     return the 1 based day number within the year
  */
+int
 day_in_year(day, month, year)
 day_in_year(day, month, year)
-       register int day, month;
-       int year;
+       int day, month, year;
 {
 {
-       register int i, leap;
+       int i, leap;
 
        leap = leap_year(year);
        for (i = 1; i < month; i++)
                day += days_in_month[leap][i];
 
        leap = leap_year(year);
        for (i = 1; i < month; i++)
                day += days_in_month[leap][i];
-       return(day);
+       return (day);
 }
 
 /*
 }
 
 /*
@@ -234,6 +308,7 @@ day_in_year(day, month, year)
  *     3 Sep. 1752 through 13 Sep. 1752.  Returns Thursday for all
  *     missing days.
  */
  *     3 Sep. 1752 through 13 Sep. 1752.  Returns Thursday for all
  *     missing days.
  */
+int
 day_in_week(day, month, year)
        int day, month, year;
 {
 day_in_week(day, month, year)
        int day, month, year;
 {
@@ -242,44 +317,85 @@ day_in_week(day, month, year)
        temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
            + day_in_year(day, month, year);
        if (temp < FIRST_MISSING_DAY)
        temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
            + day_in_year(day, month, year);
        if (temp < FIRST_MISSING_DAY)
-               return((temp - 1 + SATURDAY) % 7);
+               return ((temp - 1 + SATURDAY) % 7);
        if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS))
        if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS))
-               return(((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
-       return(THURSDAY);
+               return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
+       return (THURSDAY);
 }
 
 }
 
+void
 ascii_day(p, day)
 ascii_day(p, day)
-       register char *p;
-       register int day;
+       char *p;
+       int day;
 {
 {
-       register int ten;
+       int display, val;
+       static char *aday[] = {
+               "",
+               " 1", " 2", " 3", " 4", " 5", " 6", " 7",
+               " 8", " 9", "10", "11", "12", "13", "14",
+               "15", "16", "17", "18", "19", "20", "21",
+               "22", "23", "24", "25", "26", "27", "28",
+               "29", "30", "31",
+       };
 
        if (day == SPACE) {
 
        if (day == SPACE) {
-               *p++ = ' ';
-               *p++ = ' ';
+               memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
+               return;
        }
        }
-       else {
-               ten = day / 10;
-               *p++ = ten ? ten + '0' : ' ';
+       if (julian) {
+               if (val = day / 100) {
+                       day %= 100;
+                       *p++ = val + '0';
+                       display = 1;
+               } else {
+                       *p++ = ' ';
+                       display = 0;
+               }
+               val = day / 10;
+               if (val || display)
+                       *p++ = val + '0';
+               else
+                       *p++ = ' ';
                *p++ = day % 10 + '0';
                *p++ = day % 10 + '0';
+       } else {
+               *p++ = aday[day][0];
+               *p++ = aday[day][1];
        }
        *p = ' ';
 }
 
        }
        *p = ' ';
 }
 
+void
 trim_trailing_spaces(s)
 trim_trailing_spaces(s)
-       register char *s;
+       char *s;
 {
 {
-       register char *p;
+       char *p;
 
 
-       for (p = s; *p; ++p);
-       while (p > s && isspace(*--p));
+       for (p = s; *p; ++p)
+               continue;
+       while (p > s && isspace(*--p))
+               continue;
        if (p > s)
                ++p;
        *p = '\0';
 }
 
        if (p > s)
                ++p;
        *p = '\0';
 }
 
+void
+center(str, len, separate)
+       char *str;
+       int len;
+       int separate;
+{
+
+       len -= strlen(str);
+       (void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
+       if (separate)
+               (void)printf("%*s", separate, "");
+}
+
+void
 usage()
 {
 usage()
 {
-       (void)fprintf(stderr, "usage: cal [-y] [[month] year]\n");
+
+       (void)fprintf(stderr, "usage: cal [-jy] [[month] year]\n");
        exit(1);
 }
        exit(1);
 }