1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33/*
34 *	/usr/lib/calprog produces an egrep -f file
35 *	that will select today's and tomorrow's
36 *	calendar entries, with special weekend provisions
37 *	used by calendar command
38 */
39
40
41#include <fcntl.h>
42#include <stdarg.h>
43#include <stdio.h>
44#include <ctype.h>
45#include <sys/types.h>
46#include <time.h>
47#include <sys/stat.h>
48#include <locale.h>
49#include <errno.h>
50
51
52#define	DAY	(3600*24L)
53
54extern  char	*getenv(), *malloc();
55
56static char	*file;
57static int	old_behavior;
58static int	linenum = 1;
59static time_t	t;
60static char	errmsg[128];
61static char	*errlst[] = {
62/*	0	*/ "error on open of \"%s\", errno = %d",
63/*	1	*/ "could not malloc enough memory",
64/*	2	*/ "error on stat of \"%s\", errno = %d",
65/*	3	*/ "file \"%s\" is not a regular file",
66/*	4	*/ "error in reading the file \"%s\"",
67/*	5	*/ "\"%s\" file: error on line %d",
68/*	6	*/ "\"%s\" file: format descriptions are missing"
69};
70
71static
72char *month[] = {
73	"[Jj]an",
74	"[Ff]eb",
75	"[Mm]ar",
76	"[Aa]pr",
77	"[Mm]ay",
78	"[Jj]un",
79	"[Jj]ul",
80	"[Aa]ug",
81	"[Ss]ep",
82	"[Oo]ct",
83	"[Nn]ov",
84	"[Dd]ec"
85};
86
87static void read_tmpl(void);
88static void error(const char *fmt, ...);
89static void generate(char *);
90
91static void
92tprint(time_t t)
93{
94	struct tm *tm;
95	tm = localtime(&t);
96	(void) printf
97		("(^|[ \t(,;])((%s[^ ]* *|0*%d/|\\*/)0*%d)([^0123456789]|$)\n",
98		month[tm->tm_mon], tm->tm_mon + 1, tm->tm_mday);
99}
100
101int
102main(int argc, char *argv[])
103{
104
105	(void) setlocale(LC_ALL, "");
106	(void) time(&t);
107	if (((file = getenv("DATEMSK")) == 0) || file[0] == '\0')
108		old_behavior = 1;
109	if (old_behavior)
110		tprint(t);
111	else
112		read_tmpl();
113	switch (localtime(&t)->tm_wday) {
114	case 5:
115		t += DAY;
116		if (old_behavior)
117			tprint(t);
118		else
119			read_tmpl();
120	case 6:
121		t += DAY;
122		if (old_behavior)
123			tprint(t);
124		else
125			read_tmpl();
126	default:
127		t += DAY;
128		if (old_behavior)
129			tprint(t);
130		else
131			read_tmpl();
132	}
133	return (0);
134}
135
136
137static void
138read_tmpl(void)
139{
140	char	*clean_line();
141	FILE  *fp;
142	char *bp, *start;
143	struct stat sb;
144	int	no_empty = 0;
145
146	if ((start = (char *)malloc(512)) == NULL)
147		error(errlst[1]);
148	if ((fp = fopen(file, "r")) == NULL)
149		error(errlst[0], file, errno);
150	if (fstat(fileno(fp), &sb) < 0)
151		error(errlst[2], file, errno);
152	if ((sb.st_mode & S_IFMT) != S_IFREG)
153		error(errlst[3], file);
154	for (;;) {
155		bp = start;
156		if (!fgets(bp, 512, fp)) {
157			if (!feof(fp)) {
158				free(start);
159				fclose(fp);
160				error(errlst[4], file);
161				}
162			break;
163		}
164		if (*(bp+strlen(bp)-1) != '\n')   /* terminating newline? */
165			{
166			free(start);
167			fclose(fp);
168			error(errlst[5], file, linenum);
169			}
170		bp = clean_line(bp);
171		if (strlen(bp))  /*  anything left?  */
172			{
173			no_empty++;
174			generate(bp);
175			}
176	linenum++;
177	}
178	free(start);
179	fclose(fp);
180	if (!no_empty)
181		error(errlst[6], file);
182}
183
184
185char  *
186clean_line(char *s)
187{
188	char  *ns;
189
190	*(s + strlen(s) -1) = (char)0; /* delete newline */
191	if (!strlen(s))
192		return (s);
193	ns = s + strlen(s) - 1; /* s->start; ns->end */
194	while ((ns != s) && (isspace(*ns))) {
195		*ns = (char)0;	/* delete terminating spaces */
196		--ns;
197		}
198	while (*s)		/* delete beginning white spaces */
199		if (isspace(*s))
200			++s;
201		else
202			break;
203	return (s);
204}
205
206static void
207error(const char *fmt, ...)
208{
209	va_list	args;
210
211	va_start(args, fmt);
212	(void) vsnprintf(errmsg, sizeof (errmsg), fmt, args);
213	fprintf(stderr, "%s\n", errmsg);
214	va_end(args);
215	exit(1);
216}
217
218static void
219generate(char *fmt)
220{
221	char	timebuf[1024];
222	char	outbuf[2 * 1024];
223	char	*tb, *ob;
224	int	space = 0;
225
226	strftime(timebuf, sizeof (timebuf), fmt, localtime(&t));
227	tb = timebuf;
228	ob = outbuf;
229	while (*tb)
230		if (isspace(*tb)) {
231			++tb;
232			space++;
233		}
234		else
235			{
236			if (space) {
237				*ob++ = '[';
238				*ob++ = ' ';
239				*ob++ = '\t';
240				*ob++ = ']';
241				*ob++ = '*';
242				space = 0;
243				continue;
244			}
245			if (isalpha(*tb)) {
246				*ob++ = '[';
247				*ob++ = toupper(*tb);
248				*ob++ = tolower(*tb++);
249				*ob++ = ']';
250				continue;
251			}
252			else
253				*ob++ = *tb++;
254				if (*(tb - 1) == '0')
255					*ob++ = '*';
256			}
257	*ob = '\0';
258	printf("%s\n", outbuf);
259}
260