10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*236Schin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate
300Sstevel@tonic-gate
310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
320Sstevel@tonic-gate
330Sstevel@tonic-gate /*
340Sstevel@tonic-gate * /usr/lib/calprog produces an egrep -f file
350Sstevel@tonic-gate * that will select today's and tomorrow's
360Sstevel@tonic-gate * calendar entries, with special weekend provisions
370Sstevel@tonic-gate * used by calendar command
380Sstevel@tonic-gate */
390Sstevel@tonic-gate
400Sstevel@tonic-gate
410Sstevel@tonic-gate #include <fcntl.h>
420Sstevel@tonic-gate #include <stdarg.h>
430Sstevel@tonic-gate #include <stdio.h>
440Sstevel@tonic-gate #include <ctype.h>
450Sstevel@tonic-gate #include <sys/types.h>
460Sstevel@tonic-gate #include <time.h>
470Sstevel@tonic-gate #include <sys/stat.h>
480Sstevel@tonic-gate #include <locale.h>
490Sstevel@tonic-gate #include <errno.h>
500Sstevel@tonic-gate
510Sstevel@tonic-gate
520Sstevel@tonic-gate #define DAY (3600*24L)
530Sstevel@tonic-gate
540Sstevel@tonic-gate extern char *getenv(), *malloc();
550Sstevel@tonic-gate
560Sstevel@tonic-gate static char *file;
570Sstevel@tonic-gate static int old_behavior;
580Sstevel@tonic-gate static int linenum = 1;
590Sstevel@tonic-gate static time_t t;
600Sstevel@tonic-gate static char errmsg[128];
610Sstevel@tonic-gate static char *errlst[] = {
620Sstevel@tonic-gate /* 0 */ "error on open of \"%s\", errno = %d",
630Sstevel@tonic-gate /* 1 */ "could not malloc enough memory",
640Sstevel@tonic-gate /* 2 */ "error on stat of \"%s\", errno = %d",
650Sstevel@tonic-gate /* 3 */ "file \"%s\" is not a regular file",
660Sstevel@tonic-gate /* 4 */ "error in reading the file \"%s\"",
670Sstevel@tonic-gate /* 5 */ "\"%s\" file: error on line %d",
680Sstevel@tonic-gate /* 6 */ "\"%s\" file: format descriptions are missing"
690Sstevel@tonic-gate };
700Sstevel@tonic-gate
710Sstevel@tonic-gate static
720Sstevel@tonic-gate char *month[] = {
730Sstevel@tonic-gate "[Jj]an",
740Sstevel@tonic-gate "[Ff]eb",
750Sstevel@tonic-gate "[Mm]ar",
760Sstevel@tonic-gate "[Aa]pr",
770Sstevel@tonic-gate "[Mm]ay",
780Sstevel@tonic-gate "[Jj]un",
790Sstevel@tonic-gate "[Jj]ul",
800Sstevel@tonic-gate "[Aa]ug",
810Sstevel@tonic-gate "[Ss]ep",
820Sstevel@tonic-gate "[Oo]ct",
830Sstevel@tonic-gate "[Nn]ov",
840Sstevel@tonic-gate "[Dd]ec"
850Sstevel@tonic-gate };
860Sstevel@tonic-gate
87*236Schin static void read_tmpl(void);
880Sstevel@tonic-gate static void error(const char *fmt, ...);
89*236Schin static void generate(char *);
900Sstevel@tonic-gate
91*236Schin static void
tprint(time_t t)92*236Schin tprint(time_t t)
930Sstevel@tonic-gate {
940Sstevel@tonic-gate struct tm *tm;
950Sstevel@tonic-gate tm = localtime(&t);
960Sstevel@tonic-gate (void) printf
970Sstevel@tonic-gate ("(^|[ \t(,;])((%s[^ ]* *|0*%d/|\\*/)0*%d)([^0123456789]|$)\n",
980Sstevel@tonic-gate month[tm->tm_mon], tm->tm_mon + 1, tm->tm_mday);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate
101*236Schin int
main(int argc,char * argv[])102*236Schin main(int argc, char *argv[])
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1060Sstevel@tonic-gate (void) time(&t);
1070Sstevel@tonic-gate if (((file = getenv("DATEMSK")) == 0) || file[0] == '\0')
1080Sstevel@tonic-gate old_behavior = 1;
1090Sstevel@tonic-gate if (old_behavior)
1100Sstevel@tonic-gate tprint(t);
1110Sstevel@tonic-gate else
1120Sstevel@tonic-gate read_tmpl();
1130Sstevel@tonic-gate switch (localtime(&t)->tm_wday) {
1140Sstevel@tonic-gate case 5:
1150Sstevel@tonic-gate t += DAY;
1160Sstevel@tonic-gate if (old_behavior)
1170Sstevel@tonic-gate tprint(t);
1180Sstevel@tonic-gate else
1190Sstevel@tonic-gate read_tmpl();
1200Sstevel@tonic-gate case 6:
1210Sstevel@tonic-gate t += DAY;
1220Sstevel@tonic-gate if (old_behavior)
1230Sstevel@tonic-gate tprint(t);
1240Sstevel@tonic-gate else
1250Sstevel@tonic-gate read_tmpl();
1260Sstevel@tonic-gate default:
1270Sstevel@tonic-gate t += DAY;
1280Sstevel@tonic-gate if (old_behavior)
1290Sstevel@tonic-gate tprint(t);
1300Sstevel@tonic-gate else
1310Sstevel@tonic-gate read_tmpl();
1320Sstevel@tonic-gate }
133*236Schin return (0);
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate
137*236Schin static void
read_tmpl(void)138*236Schin read_tmpl(void)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate char *clean_line();
1410Sstevel@tonic-gate FILE *fp;
1420Sstevel@tonic-gate char *bp, *start;
1430Sstevel@tonic-gate struct stat sb;
1440Sstevel@tonic-gate int no_empty = 0;
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate if ((start = (char *)malloc(512)) == NULL)
1470Sstevel@tonic-gate error(errlst[1]);
1480Sstevel@tonic-gate if ((fp = fopen(file, "r")) == NULL)
1490Sstevel@tonic-gate error(errlst[0], file, errno);
1500Sstevel@tonic-gate if (fstat(fileno(fp), &sb) < 0)
1510Sstevel@tonic-gate error(errlst[2], file, errno);
1520Sstevel@tonic-gate if ((sb.st_mode & S_IFMT) != S_IFREG)
1530Sstevel@tonic-gate error(errlst[3], file);
1540Sstevel@tonic-gate for (;;) {
1550Sstevel@tonic-gate bp = start;
1560Sstevel@tonic-gate if (!fgets(bp, 512, fp)) {
1570Sstevel@tonic-gate if (!feof(fp)) {
1580Sstevel@tonic-gate free(start);
1590Sstevel@tonic-gate fclose(fp);
1600Sstevel@tonic-gate error(errlst[4], file);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate break;
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate if (*(bp+strlen(bp)-1) != '\n') /* terminating newline? */
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate free(start);
1670Sstevel@tonic-gate fclose(fp);
1680Sstevel@tonic-gate error(errlst[5], file, linenum);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate bp = clean_line(bp);
1710Sstevel@tonic-gate if (strlen(bp)) /* anything left? */
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate no_empty++;
1740Sstevel@tonic-gate generate(bp);
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate linenum++;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate free(start);
1790Sstevel@tonic-gate fclose(fp);
1800Sstevel@tonic-gate if (!no_empty)
1810Sstevel@tonic-gate error(errlst[6], file);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate char *
clean_line(char * s)186*236Schin clean_line(char *s)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate char *ns;
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate *(s + strlen(s) -1) = (char)0; /* delete newline */
1910Sstevel@tonic-gate if (!strlen(s))
1920Sstevel@tonic-gate return (s);
1930Sstevel@tonic-gate ns = s + strlen(s) - 1; /* s->start; ns->end */
1940Sstevel@tonic-gate while ((ns != s) && (isspace(*ns))) {
1950Sstevel@tonic-gate *ns = (char)0; /* delete terminating spaces */
1960Sstevel@tonic-gate --ns;
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate while (*s) /* delete beginning white spaces */
1990Sstevel@tonic-gate if (isspace(*s))
2000Sstevel@tonic-gate ++s;
2010Sstevel@tonic-gate else
2020Sstevel@tonic-gate break;
2030Sstevel@tonic-gate return (s);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate static void
error(const char * fmt,...)2070Sstevel@tonic-gate error(const char *fmt, ...)
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate va_list args;
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate va_start(args, fmt);
2120Sstevel@tonic-gate (void) vsnprintf(errmsg, sizeof (errmsg), fmt, args);
2130Sstevel@tonic-gate fprintf(stderr, "%s\n", errmsg);
2140Sstevel@tonic-gate va_end(args);
2150Sstevel@tonic-gate exit(1);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
218*236Schin static void
generate(char * fmt)219*236Schin generate(char *fmt)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate char timebuf[1024];
2220Sstevel@tonic-gate char outbuf[2 * 1024];
2230Sstevel@tonic-gate char *tb, *ob;
2240Sstevel@tonic-gate int space = 0;
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate strftime(timebuf, sizeof (timebuf), fmt, localtime(&t));
2270Sstevel@tonic-gate tb = timebuf;
2280Sstevel@tonic-gate ob = outbuf;
2290Sstevel@tonic-gate while (*tb)
230*236Schin if (isspace(*tb)) {
2310Sstevel@tonic-gate ++tb;
2320Sstevel@tonic-gate space++;
233*236Schin }
2340Sstevel@tonic-gate else
2350Sstevel@tonic-gate {
236*236Schin if (space) {
2370Sstevel@tonic-gate *ob++ = '[';
2380Sstevel@tonic-gate *ob++ = ' ';
2390Sstevel@tonic-gate *ob++ = '\t';
2400Sstevel@tonic-gate *ob++ = ']';
2410Sstevel@tonic-gate *ob++ = '*';
2420Sstevel@tonic-gate space = 0;
2430Sstevel@tonic-gate continue;
244*236Schin }
245*236Schin if (isalpha(*tb)) {
2460Sstevel@tonic-gate *ob++ = '[';
2470Sstevel@tonic-gate *ob++ = toupper(*tb);
2480Sstevel@tonic-gate *ob++ = tolower(*tb++);
2490Sstevel@tonic-gate *ob++ = ']';
2500Sstevel@tonic-gate continue;
251*236Schin }
2520Sstevel@tonic-gate else
2530Sstevel@tonic-gate *ob++ = *tb++;
2540Sstevel@tonic-gate if (*(tb - 1) == '0')
2550Sstevel@tonic-gate *ob++ = '*';
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate *ob = '\0';
2580Sstevel@tonic-gate printf("%s\n", outbuf);
2590Sstevel@tonic-gate }
260