Subject: bin/3935: calendar(1) enchancements
To: None <gnats-bugs@gnats.netbsd.org>
From: None <tsarna@endicor.com>
List: netbsd-bugs
Date: 08/03/1997 22:10:35
>Number:         3935
>Category:       bin
>Synopsis:       calendar(1) enchancements
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Aug  3 20:20:01 1997
>Last-Modified:
>Originator:     Ty Sarna
>Organization:
	Endicor Technologies, Inc., San Antonio, Texas
>Release:        NetBSD-current
>Environment:
System: NetBSD lotharon.endicor.com 1.2B NetBSD 1.2B (LOTHARON) #1: Thu Dec 12 12:09:19 CST 1996 tsarna@lotharon.endicor.com:/usr/src/sys/arch/sun3/compile/LOTHARON sun3


>Description:
	I wanted to be able to do several things with calendar(1)
	that I couldn't, including:

	- get entries from a file other than "calendar".
	- get entries for a different date than today
	- get entries for a whole week in advance, or only one day.

	So I added flags that allow these things. See the manpage diffs
	for details.

	Still to do: allow holidays that move around to be specified
	correctly.
>How-To-Repeat:
	See above.
>Fix:
	Apply this:

*** calendar.c.orig	Mon Mar 17 01:18:11 1997
--- calendar.c	Sun Apr  6 19:13:33 1997
***************
*** 65,77 ****
--- 65,88 ----
  
  #include "pathnames.h"
  
+ #ifndef TRUE
+ #define TRUE 1
+ #endif
+ #ifndef FALSE
+ #define FALSE 0
+ #endif
+ 
+ unsigned short lookahead = 1, weekend = 2;
+ char *fname = "calendar", *datestr = NULL;
  struct passwd *pw;
  int doall;
  
+ void	 atodays __P((char, char *, unsigned short *));
  void	 cal __P((void));
  void	 closecal __P((FILE *));
  int	 getday __P((char *));
  int	 getfield __P((char *, char **, int *));
+ void	 getmmdd(struct tm *tp, char *ds);
  int	 getmonth __P((char *));
  int	 isnow __P((char *));
  FILE	*opencal __P((void));
***************
*** 87,93 ****
  	int ch;
  	char *caldir;
  
! 	while ((ch = getopt(argc, argv, "-a")) != EOF)
  		switch (ch) {
  		case '-':		/* backward contemptible */
  		case 'a':
--- 98,104 ----
  	int ch;
  	char *caldir;
  
! 	while ((ch = getopt(argc, argv, "-ad:f:l:w:")) != EOF)
  		switch (ch) {
  		case '-':		/* backward contemptible */
  		case 'a':
***************
*** 97,102 ****
--- 108,125 ----
  			}
  			doall = 1;
  			break;
+ 		case 'd':
+ 			datestr = optarg;
+ 			break;
+ 		case 'f':
+ 			fname = optarg;
+ 			break;
+ 		case 'l':
+ 			atodays(ch, optarg, &lookahead);
+ 			break;
+ 		case 'w':
+ 			atodays(ch, optarg, &weekend);
+ 			break;
  		case '?':
  		default:
  			usage();
***************
*** 176,181 ****
--- 199,207 ----
  
  	(void)time(&now);
  	tp = localtime(&now);
+ 	if (datestr) {
+ 		getmmdd(tp, datestr);
+ 	}
  	if (isleap(tp->tm_year + 1900)) {
  		yrdays = DAYSPERLYEAR;
  		cumdays = daytab[1];
***************
*** 184,190 ****
  		cumdays = daytab[0];
  	}
  	/* Friday displays Monday's events */
! 	offset = tp->tm_wday == 5 ? 3 : 1;
  	header[5].iov_base = dayname;
  	header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
  }
--- 210,216 ----
  		cumdays = daytab[0];
  	}
  	/* Friday displays Monday's events */
! 	offset = tp->tm_wday == 5 ? lookahead + weekend : lookahead;
  	header[5].iov_base = dayname;
  	header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
  }
***************
*** 289,300 ****
  	int fd, pdes[2];
  
  	/* open up calendar file as stdin */
! 	if (!freopen("calendar", "r", stdin)) {
  		if (doall)
  			return (NULL);
  		errx(1, "no calendar file.");
  	}
! 	if (pipe(pdes) < 0) 
  		return (NULL);
  	switch (vfork()) {
  	case -1:			/* error */
--- 315,326 ----
  	int fd, pdes[2];
  
  	/* open up calendar file as stdin */
! 	if (!freopen(fname, "r", stdin)) {
  		if (doall)
  			return (NULL);
  		errx(1, "no calendar file.");
  	}
! 	if (pipe(pdes) < 0)
  		return (NULL);
  	switch (vfork()) {
  	case -1:			/* error */
***************
*** 342,355 ****
  	(void)rewind(fp);
  	if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
  		goto done;
! 	if (pipe(pdes) < 0) 
  		goto done;
  	switch (vfork()) {
  	case -1:			/* error */
  		(void)close(pdes[0]);
  		(void)close(pdes[1]);
  		goto done;
! 	case 0:		
  		/* child -- set stdin to pipe output */
  		if (pdes[0] != STDIN_FILENO) {
  			(void)dup2(pdes[0], STDIN_FILENO);
--- 368,381 ----
  	(void)rewind(fp);
  	if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
  		goto done;
! 	if (pipe(pdes) < 0)
  		goto done;
  	switch (vfork()) {
  	case -1:			/* error */
  		(void)close(pdes[0]);
  		(void)close(pdes[1]);
  		goto done;
! 	case 0:
  		/* child -- set stdin to pipe output */
  		if (pdes[0] != STDIN_FILENO) {
  			(void)dup2(pdes[0], STDIN_FILENO);
***************
*** 409,416 ****
  }
  
  void
  usage()
  {
! 	(void)fprintf(stderr, "usage: calendar [-a]\n");
  	exit(1);
  }
--- 435,510 ----
  }
  
  void
+ atodays(char ch, char *optarg, unsigned short *days)
+ {
+ 	extern char *__progname;
+ 	int u;
+ 
+ 	u = atoi(optarg);
+ 	if ((u < 0) || (u > 366)) {
+ 		fprintf(stderr,
+ 			"%s: warning: -%c %d out of range 0-366, ignored.\n",
+ 			__progname, ch, u);
+ 	} else {
+ 		*days = u;
+ 	}
+ }
+ 
+ #define todigit(x) ((x) - '0')
+ #define ATOI2(x) (todigit((x)[0]) * 10 + todigit((x)[1]))
+ #define ISDIG2(x) (isdigit((x)[0]) && isdigit((x)[1]))
+ 
+ void
+ getmmdd(struct tm *tp, char *ds)
+ {
+ 	extern char *__progname;
+ 	int ok = FALSE;
+ 	struct tm ttm;
+ 	char *t;
+ 
+ 	ttm = *tp;
+ 	ttm.tm_isdst = -1;
+ 
+ 	if (ISDIG2(ds)) {
+ 		ttm.tm_mon = ATOI2(ds) - 1;
+ 		ds += 2;
+ 	}
+ 
+ 	if (ISDIG2(ds)) {
+ 		ttm.tm_mday = ATOI2(ds);
+ 		ds += 2;
+ 
+ 		ok = TRUE;
+ 	}
+ 
+ 	if (ok) {
+ 		if (ISDIG2(ds) && ISDIG2(ds + 2)) {
+ 			ttm.tm_year = ATOI2(ds) * 100 - 1900;
+ 			ds += 2;
+ 			ttm.tm_year += ATOI2(ds);
+ 		} else if (ISDIG2(ds)) {
+ 			ttm.tm_year = ATOI2(ds);
+ 		}
+ 	}
+ 	
+ 	if (ok && (mktime(&ttm) < 0)) {
+ 		ok = FALSE;
+ 	}
+ 	
+ 	if (ok) {
+ 		*tp = ttm;
+ 	} else {
+ 		fprintf(stderr,
+ 			"%s: warning: can't convert %s to date, ignored.\n",
+ 			__progname, ds);
+ 		usage();
+ 	}
+ }
+ 
+ void
  usage()
  {
! 	(void)fprintf(stderr, "usage: calendar [-a] [-d MMDD[[YY]YY]" \
! 		" [-f fname] [-l days] [-w days]\n");
  	exit(1);
  }
*** calendar.1.orig	Thu Jul 31 11:31:23 1997
--- calendar.1	Sun Aug  3 21:46:05 1997
***************
*** 42,57 ****
  .Sh SYNOPSIS
  .Nm calendar
  .Op Fl a
  .Sh DESCRIPTION
  The 
  .Nm calendar
! utility checks the current directory or the directory specified by the
! .Dq Ev CALENDAR_DIR
! environment variable for a file named
! .Pa calendar
! and displays lines that begin with either today's date
! or tomorrow's.
! On Fridays, events on Friday through Monday are displayed.
  .Pp
  The following options are available:
  .Bl -tag -width Ds
--- 42,55 ----
  .Sh SYNOPSIS
  .Nm calendar
  .Op Fl a
+ .Op Fl f Ar file
+ .Op Fl l Ar days
+ .Op Fl w Ar days
+ .Op Fl d Ar MMDD[[YY]YY]
  .Sh DESCRIPTION
  The 
  .Nm calendar
! utility processes text files and displays lines that match certain dates.
  .Pp
  The following options are available:
  .Bl -tag -width Ds
***************
*** 59,64 ****
--- 57,87 ----
  Process the ``calendar'' files of all users and mail the results
  to them.
  This requires super-user privileges.
+ .It Fl d Ar MMDD[[YY]YY]
+ Display lines for the given date. By default, the current date is used.
+ The year, which may be given in either two or four digit format, is used
+ only for purposes of determining wether the given date falls on a Friday
+ in that year (see below). If the year is not specified, the current
+ year is assumed.
+ .It Fl f Ar file
+ Display matching calendar files from the given filename, by default
+ .Pa calendar .
+ The filename may be absolute. If not absolute, it is taken
+ relative to the current directory or the directory specified by the
+ .Dq Ev CALENDAR_DIR
+ environment variable. Or, if the
+ .Fl a
+ flag is given, a non-absolute filename is taken relative to each user's
+ home directory in turn.
+ .It Fl l Ar days
+ Causes the program to ``look ahead'' a given number of days (default
+ one) from the specified date and display their entries as well.
+ .It Fl w Ar days
+ Causes the program to add the specified number of days to the ``look
+ ahead'' number if and only if the day specified is a Friday. The default
+ value is two, which causes
+ .Nm calendar
+ to print entries through the weekend on Fridays.
  .El
  .Pp
  Lines should begin with a month and day.

>Audit-Trail:
>Unformatted: