rsalz@uunet.uu.net (Rich Salz) (11/10/88)
Submitted-by: Michael Morrell <hplabs!hpda!morrell> Posting-number: Volume 16, Issue 57 Archive-name: month8.7/part04 # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # This archive contains: # days_in.c event_today.c get_home.c get_month.c # get_today.c hidden.c how_many.c is_future.c # is_leap.c is_past.c jan1.c matches.c # read_sched.c write_sched.c version.c LANG=""; export LANG echo x - days_in.c cat >days_in.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: days_in.c,v 8.2 87/11/13 21:46:25 hull Exp $"; #endif days_in(month, year) short month, year; { switch(month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return(31); case 4: case 6: case 9: case 11: return(30); case 2: return(28 + is_leap_year(year)); } /* NOTREACHED */ } @EOF chmod 644 days_in.c echo x - event_today.c cat >event_today.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: event_today.,v 8.2 87/11/13 21:46:29 hull Exp $"; #endif #include "month.h" extern struct date_rec current_date; extern short my_file; extern int user_id; event_today(event) register struct event_rec *event; { /* returns 1 if event is visible on the current day, 0 if not */ /* check if this in an anti-event */ if (event->anti) return(0); /* check if the file belongs to this user, the event is private, and the user id does not match the event owner */ if (!my_file && event->private && (user_id != event->event_owner)) return(0); /* check if event matches the current date */ if (!event_matches_date(event, ¤t_date)) return(0); /* check if event hidden by anti-event */ if (event_hidden(event, ¤t_date)) return(0); return(1); } @EOF chmod 644 event_today.c echo x - get_home.c cat >get_home.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: get_home.c,v 1.1 87/12/02 18:07:19 hull Exp $"; #endif #include <pwd.h> extern char *malloc(); char * get_home_dir(uid) int uid; { struct passwd *pw; char *strcpy(); int strlen(); if ((pw = getpwuid(uid)) == (struct passwd *)0) return((char *)0); else return(strcpy(malloc((unsigned)strlen(pw->pw_dir)+1), pw->pw_dir)); } @EOF chmod 644 get_home.c echo x - get_month.c cat >get_month.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: get_month.c,v 8.2 87/11/13 21:46:38 hull Exp $"; #endif get_month_start(month, year) register month, year; { short day, i; day = jan1(year); for (i = 1; i < month; i++) { day = (day + days_in(i, year)) % 7; } return(day); } @EOF chmod 644 get_month.c echo x - get_today.c cat >get_today.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: get_today.c,v 8.3 88/04/04 09:58:17 hull Exp $"; #endif #if SYS5 #include <time.h> #else #include <sys/time.h> #endif #include "month.h" extern struct date_rec todays_date; extern short dhour, dminute, dsecond; get_todays_date() { #if SYS5 long tloc, time(); #else struct timeval tp; struct timezone tzp; #endif struct tm *tmp; #if SYS5 if (time(&tloc) == -1) return(-1); tmp = localtime(&tloc); #else if (gettimeofday(&tp, &tzp) != 0) return(-1); tmp = localtime((long *) &tp.tv_sec); #endif todays_date.month = tmp->tm_mon + 1; todays_date.day = tmp->tm_mday; todays_date.year = 1900 + tmp->tm_year; /* random values for testing */ /* todays_date.month = random(12) + 1; todays_date.day = random(29) + 1; todays_date.year = 1900 + random(100); */ dhour = tmp->tm_hour; dminute = tmp->tm_min; dsecond = tmp->tm_sec; return(0); } /* for testing */ /* random(m) int m; { long lrand48(); return ((int) (lrand48() % m)); } */ @EOF chmod 644 get_today.c echo x - hidden.c cat >hidden.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: hidden.c,v 8.2 87/11/13 21:46:43 hull Exp $"; #endif #include "month.h" extern struct event_rec events; event_hidden(event, date) register struct event_rec *event; register struct date_rec *date; { /* returns 1 if event hidden by anti-event on date, 0 if not */ register struct event_rec *ptr; extern unsigned short file_owner; extern int strcmp(); ptr = events.next_event; while (ptr) { if (ptr->anti && (ptr->start_time.hour == event->start_time.hour) && (ptr->start_time.minute == event->start_time.minute) && (ptr->duration.hour == event->duration.hour) && (ptr->duration.minute == event->duration.minute) && (ptr->warning.hour == event->warning.hour) && (ptr->warning.minute == event->warning.minute) && (strcmp(ptr->event_string, event->event_string) == 0) && ((ptr->event_owner == event->event_owner) || (ptr->event_owner == file_owner)) && event_matches_date(ptr, date)) return(1); ptr = ptr->next_event; } return(0); } @EOF chmod 644 hidden.c echo x - how_many.c cat >how_many.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: how_many.c,v 8.2 87/11/13 21:46:48 hull Exp $"; #endif #include "month.h" how_many_since(edate, cdate) struct date_rec *edate, *cdate; { register total_days_passed; short i; if (edate->year < cdate->year) { total_days_passed = 0; for (i = edate->month; i <= 12; i++) total_days_passed += days_in(i, edate->year); total_days_passed -= (edate->day - 1); for (i = (edate->year + 1); i < cdate->year; i++) total_days_passed += (365 + is_leap_year(i)); for (i = 1; i < cdate->month; i++) total_days_passed += days_in(i, cdate->year); total_days_passed += cdate->day; } else if (edate->month == cdate->month) total_days_passed = cdate->day - edate->day + 1; else { total_days_passed = 1 - edate->day; for (i = edate->month; i < cdate->month; i++) total_days_passed += days_in(i, cdate->year); total_days_passed += cdate->day; } return(((total_days_passed - 1) / 7) + 1); } @EOF chmod 644 how_many.c echo x - is_future.c cat >is_future.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: is_future.c,v 8.2 87/11/13 21:46:50 hull Exp $"; #endif #include "month.h" is_future_event(event, date) struct event_rec *event; struct date_rec *date; { if (date->year < event->start_date.year) return(1); if (date->year > event->start_date.year) return(0); if (date->month < event->start_date.month) return(1); if (date->month > event->start_date.month) return(0); if (date->day < event->start_date.day) return(1); return(0); } @EOF chmod 644 is_future.c echo x - is_leap.c cat >is_leap.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: is_leap.c,v 8.2 87/11/13 21:46:52 hull Exp $"; #endif is_leap_year(year) int year; { return((((jan1(year + 1) + 7 - jan1(year)) % 7) == 2) ? 1 : 0); } @EOF chmod 644 is_leap.c echo x - is_past.c cat >is_past.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: is_past.c,v 8.2 87/11/13 21:46:54 hull Exp $"; #endif #include "month.h" is_past_event(event, date) struct event_rec *event; struct date_rec *date; { register end_month, end_day, end_year; if (!event->until && (event->monthly || event->yearly || event->every)) return(0); if (event->until) { end_month = event->until_date.month; end_day = event->until_date.day; end_year = event->until_date.year; } else { end_month = event->start_date.month; end_day = event->start_date.day; end_year = event->start_date.year; } if (end_year > date->year) return(0); if (end_year < date->year) return(1); if (end_month > date->month) return(0); if (end_month < date->month) return(1); if (end_day < date->day) return(1); return(0); } @EOF chmod 644 is_past.c echo x - jan1.c cat >jan1.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: jan1.c,v 8.2 87/11/13 21:46:55 hull Exp $"; #endif jan1(year) register year; { register day; day = year + (year + 3) / 4; if (year > 1800) { day -= (year - 1701) / 100; day += (year - 1601) / 400; } if (year > 4000) day -= year / 4000; return(day % 7); } @EOF chmod 644 jan1.c echo x - matches.c cat >matches.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: matches.c,v 8.2 87/11/13 21:47:00 hull Exp $"; #endif #include "month.h" #define nth_smtwtfs_of_month(date) (((date->day - 1) / 7) + 1) #define last_smtwtfs_of_month(date) \ ((date->day + 7) > days_in(date->month, date->year) ? 1 : 0) event_matches_date(event, date) register struct event_rec *event; register struct date_rec *date; { /* returns 1 if event matches date, 0 if not */ short mnth_start; int n; /* check if event is a future or past event */ if (is_future_event(event, date) || is_past_event(event, date)) return(0); /* one time events must match date */ if ((event->start_date.year == date->year) && (event->start_date.month == date->month) && (event->start_date.day == date->day) && !event->every && !event->nth_is_on && !event->last && !event->until) { return(1); } /* once monthly or once yearly events */ if (!event->every && !event->nth_is_on && !event->last) { if (event->monthly) { if (event->start_date.day == date->day) return(1); } else if (event->yearly) { if ((event->start_date.month == date->month) && (event->start_date.day == date->day)) return(1); } } mnth_start = get_month_start(date->month, date->year); if (!event->smtwtfs[(date->day - 1 + mnth_start) % 7]) return(0); /* everys */ if (event->every) { /* every smtwtfs */ if (!event->nth_is_on && !event->last) { EVDAY: if (event->smtwtfs[(date->day - 1 + mnth_start) % 7]) return(1); return(0); } /* every monthly/yearly */ if (event->monthly || event->yearly) { /* every monthly not-1st2nd3rdlast */ if (!event->nth_is_on && !event->last) goto EVDAY; /* every monthly/yearly with one of 1st2nd3rd... */ if (event->nth_is_on) { if (event->monthly && (nth_smtwtfs_of_month(date) == event->nth)) return(1); if (event->yearly && (nth_smtwtfs_of_year(date) == event->nth)) return(1); } /* every monthly/yearly with last */ if (event->last) { if (event->monthly) { if (last_smtwtfs_of_month(date)) return(1); } if (event->yearly) { if (last_smtwtfs_of_year(date)) return(1); } } } else { /* every not-monthly and not-yearly */ if (!event->nth_is_on && !event->last) goto EVDAY; /* every nth/dayofweek */ if (event->nth == 1) return(1); n = how_many_since(&event->start_date, date); if ((n % event->nth) == 1) return(1); } } return(0); } nth_smtwtfs_of_year(date) struct date_rec *date; { short dys, i; for (i = 1, dys = date->day; i < date->month; i++) { dys += days_in(i, date->year); } return(((dys - 1) / 7) + 1); } last_smtwtfs_of_year(date) struct date_rec *date; { short dys, i; for (i = 1, dys = date->day; i < date->month; i++) { dys += days_in(i, date->year); } return((dys + 7) > (365 + is_leap_year(date->year)) ? 1 : 0); } @EOF chmod 644 matches.c echo x - read_sched.c cat >read_sched.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: read_sched.c,v 8.4 88/04/04 11:00:49 hull Exp $"; #endif #include <sys/types.h> #include <sys/stat.h> #if LOCKF #include <fcntl.h> #include <unistd.h> #endif LOCKF #if FLOCK #include <sys/file.h> #endif FLOCK #include "month.h" extern unsigned short file_owner; extern int fd; extern struct event_rec events; read_schedule(m_dir, read_mode) char *m_dir; short read_mode; { char *schedule_file_name; unsigned rec_size; struct stat stat_buf; short file_version; struct event_rec event_buf, *event_ptr, *chain_ptr; extern float get_version(); extern char *strcat(), *strcpy(); schedule_file_name = malloc((unsigned) strlen(m_dir)+8); strcpy(schedule_file_name, m_dir); strcat(schedule_file_name, "/.month"); rec_size = sizeof(struct event_rec); umask(0); chain_ptr = events.next_event; /* free old events */ while (chain_ptr) { event_ptr = chain_ptr; chain_ptr = chain_ptr->next_event; free((char *)event_ptr); } events.next_event = 0; #if MULTIUSER if (read_mode == READ_ONLY) fd = open(schedule_file_name, O_RDONLY); else { if ((fd = open(schedule_file_name, O_RDWR|O_CREAT, 0660)) != -1) #if LOCKF if (lockf(fd, F_TLOCK, 0L) == -1) { close(fd); fd = -2; return(-2); } #else #if FLOCK if (flock(fd, LOCK_EX | LOCK_NB) == -1) { close(fd); fd = -2; return(-2); } #endif FLOCK #endif LOCKF } #else fd = open(schedule_file_name, O_RDWR|O_CREAT, 0660); #endif MULTIUSER free(schedule_file_name); if (fd != -1) { if (read(fd, (char *) &file_version, sizeof(file_version)) == sizeof(file_version)) { if (file_version != (int) get_version()) { close(fd); fd = -1; return(file_version); } } else { /* no version field so assume empty file */ if (read_mode == READ_ONLY) { close(fd); fd = -1; } return(0); } chain_ptr = &events; while (read(fd, &event_buf, rec_size) == rec_size) { if (event_ptr = (struct event_rec *)malloc(rec_size)) { chain_ptr->next_event = event_ptr; chain_ptr = event_ptr; *chain_ptr = event_buf; chain_ptr->next_event = (struct event_rec *)0; } else break; } fstat(fd, &stat_buf); file_owner = stat_buf.st_uid; if (read_mode == READ_ONLY) { close(fd); fd = -1; } return(0); } /* if here, open failed */ return(-1); } @EOF chmod 644 read_sched.c echo x - write_sched.c cat >write_sched.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: write_sched.,v 8.3 87/12/01 23:40:05 hull Exp $"; #endif #include "month.h" extern short updating, update_schedule, keep_old; extern int fd; extern off_type lseek(); extern struct date_rec todays_date; extern struct event_rec events; write_schedule() { short file_version; struct event_rec *chain_ptr; float get_version(); if (fd < 0) /* file not really open */ return(fd); if (!update_schedule) { close(fd); return(0); } updating = 1; file_version = (int) get_version(); if (lseek(fd, (off_type) 0, 0) == -1) { close(fd); return(-1); } #if !SYS5 if (ftruncate(fd, (off_type) 0) == -1) { close(fd); return(-1); } #endif write(fd, (char *) &file_version, sizeof(short)); chain_ptr = events.next_event; while (chain_ptr) { if (keep_old || !is_past_event(chain_ptr, &todays_date)) write(fd, (char *)chain_ptr, sizeof(struct event_rec)); else delete_event(chain_ptr); chain_ptr = chain_ptr->next_event; } close(fd); /* also releases lock */ update_schedule = updating = 0; return(0); } @EOF chmod 644 write_sched.c echo x - version.c cat >version.c <<'@EOF' #ifndef lint static char rcsid[] = "$Header: version.c,v 8.7 88/06/03 22:35:16 hull Exp $"; #endif /* $Log: version.c,v $ * Revision 8.7 88/06/03 22:35:16 22:35:16 hull (James Hull) * Changed year_area display to always display "whole" decades. * Changed semantics of 2-digit year entry. * Fixed screen-memory-file consistency bug. * * Revision 8.6 88/04/04 11:17:12 11:17:12 hull (James Hull) * Added alarm calls and new_day function so today's date is updated. * Fixed bug so that 'R' command updates schedule display. * Various other bug fixes and code clean-ups. * * Revision 8.5 88/01/15 10:48:52 10:48:52 hull (James Hull) * Fixed bug by only calling write_schedule if not in read-only mode. * * Revision 8.4 87/12/02 18:49:50 18:49:50 hull (James Hull) * Moved get_home_dir() out of month.c, monthd.c, and xmonthd.c to a separate file. * Deleted some unnecessary include files from month.c, monthd.c, xmonthd.c. * * Revision 8.3 87/12/01 23:50:22 23:50:22 hull (James Hull) * Fixed bug in read_schedule which caused monthd to mysteriously die. * Problem was caused by never closing the file descriptor and eventually * reaching the open file descriptor limit imposed by the operating system. * * Revision 8.2 87/11/13 21:25:07 21:25:07 hull (James Hull) * Fixed 'd', 'm', 'y' bug which allowed exit from schedule area. * Fixed user_name bug in 'U' and 'G' commands. * Added 'a' (print aliases) command. * Added ',' to list of allowed name separators. * Fixed security hole in 'a' and 'H' commands. * * Revision 8.1 87/11/13 21:24:26 21:24:26 hull (James Hull) * Added environment flag and command line option for time mode. * Added 't' (change time mode) command in schedule area. * * Revision 8.0 87/11/13 21:21:37 21:21:37 hull (James Hull) * Added ending time to event_rec structure. * Changed "monthd", print_sched, print_book to use ending time. * Changed format of schedule_area. * Changed all event_rec times to use time_rec structure. * Cleaned up do_incr and scroll_time so 'n' and 'p' consistent. * Fixed digit counting bug in enter_number. * Cleaned up code to "beep" for even more invalid keys. * Changed "monthd" to use process group to determine user logout. * Merged write_schedule into "common.a". * * Revision 7.7 87/11/13 21:21:06 21:21:06 hull (James Hull) * Added global alias file for 'G' command. * * Revision 7.6 87/11/13 21:20:16 21:20:16 hull (James Hull) * Changed get_npdeq to only show appropriate keys. * Cleaned up code to "beep" for most invalid keys. * * Revision 7.5 87/11/13 21:19:39 21:19:39 hull (James Hull) * Split daemon into separate "monthd" program. * Created "common.a" library. * * Revision 7.4 87/11/13 21:18:37 21:18:37 hull (James Hull) * Changed "goto mark" command from 'G' to '''. * Added 'G' (group post) command. * Minor fixes to push_area, pop_area, more, clear_message_line. * * Revision 7.3 87/11/13 21:16:35 21:16:35 morrell (Michael Morrell) * Added 'p' (previous) to 'E' command; now identical to 'S'. * Fixed security hole in shell escape. * Added '-O' option and changed 'O' command to track date. * Cleaned up code to make lint happy. * * Revision 7.2 87/11/13 21:15:59 21:15:59 hull (James Hull) * Added current date to print_sched. * Added special case for printing zero-length events. * * Revision 7.1 87/11/13 21:15:21 21:15:21 hull (James Hull) * Fixed cursor initialization bug. * * Revision 7.0 87/11/13 21:13:09 21:13:09 hull (James Hull) * Changed functions and event_rec to use date structure. * Added push/pop ara functions to fix cursor positioning bug. * Added cursor wraparound in months, days, and years areas. * Added '!' (shell escape) command. * Added 'e' (event editing) to 'E' command. * Added 'W' (write schedule) command. * * Revision 6.1 87/11/13 21:12:38 21:12:38 hull (James Hull) * Fixed next/previous bug in month area when changing years. * * Revision 6.0 87/11/13 21:11:55 21:11:55 hull (James Hull) * Added anti-events. * Fixed boundary conditions for dates. * Fixed get_date bug which trashed month, day, year. * * Revision 5.3 87/11/13 21:09:22 21:09:22 hull (James Hull) * '?', 'C', and 'P' commands check area. * Fixed 'In' printf bug in remind. * Cleaned up hl_month_year. * Added hl_day and day selection (this_day underlined). * Removed warn_day and added return to m, d, or y area. * Split display.c into hl.c, move.c, print.c, user2.c. * Added 'a', 'i', 'k', and 'r' command-line options. * Added border around days area. * Cleaned up code to make lint happy. * * Revision 5.2 87/11/13 21:07:34 21:07:34 hull (James Hull) * Added MONTH environment variable. * Fixed memory problem in get_home_dir & get_user_arg. * Removed many temp print buffers by using mvprintw. * Changed several numeric constants to named constants. * Added event description editing and insert-mode flag. * * Revision 5.0 87/11/13 21:06:16 21:06:16 hull (James Hull) * Added warning time to events. * Made year optional in '/' command and on command line. * Added '?' (help) command and file. * * Revision 4.0 87/11/13 21:05:43 21:05:43 hull (James Hull) * Added until date to events. * Replaced Accept/Cancel with ^A. * * Revision 3.0 87/11/13 21:04:14 21:04:14 hull (James Hull) * Added owner to events allowing multi-user access. * Added read-only flag and '-R' flag. * Added version values to .month file and month program. * Wrote chmonth to update .month files to new versions. * * Revision 2.0 87/11/13 21:03:22 21:03:22 hull (James Hull) * Added private flag to events. * Added direct entry of hours and minutes. * Added curses keypad input. * * Revision 1.0 87/11/13 21:00:40 21:00:40 hull (James Hull) * Initial revision * */ /* The integer portion of version changes when the event structure changes. The fractional portion changes for everything else. */ float get_version() { float version; (void) sscanf("$Revision: 8.7 $", "%*s%f", &version); return(version); } @EOF chmod 644 version.c exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.