Path: utzoo!attcan!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: Re: commands/date.c bug + fix Message-ID: <1855@ast.cs.vu.nl> Date: 3 Jan 89 20:54:24 GMT References: <321@cstw01.UUCP> Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 256 In article <321@cstw01.UUCP> meulenbr@cst.UUCP () writes: >Happy New Year with much minix! > >As probably all people dedicated to minix have noticed there is a bug in >the date program from minix (at least in the ST version, but I think >that it appears in the PC version as well). The bug was discovered and fixed after MINIX-ST went to press, but it has been fixed in 1.3. In the interest of keeping date-ST == date-PC, here is date-PC etc. Andy Tanenbaum : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting '/local/ast/minix/tape3/commands/date.c' sed 's/^X//' > '/local/ast/minix/tape3/commands/date.c' << '+ END-OF-FILE ''/local/ast/minix/tape3/commands/date.c' X/* date - print or set time and date Author: Jan Looyen */ X X#include X#include X X#define MIN 60L /* # seconds in a minute */ X#define HOUR (60 * MIN) /* # seconds in an hour */ X#define DAY (24 * HOUR) /* # seconds in a day */ X#define YEAR (365 * DAY) /* # seconds in a year */ X Xchar *ctime(); X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int qflag; X long t, time(); X char time_buf[15]; X X if (argc > 2) usage(); X if (argc == 2) { X if (*argv[1] == '-' && (argv[1][1] | 0x60) == 'q') { X freopen(stdin, "/dev/tty0", "r"); X printf("\nPlease enter date: MMDDYYhhmmss. Then hit RETURN.\n"); X gets(time_buf); X set_time(time_buf); X } X else X set_time(argv[1]); X } X time(&t); X printf("%s", ctime(&t)); X exit(0); X} X X Xset_time(t) Xchar *t; X{ X char *tp; X long ct, time(); X int len; X static int days_per_month[] = { X 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 X }; X struct tm *p, *localtime(); X X time(&ct); X p = localtime(&ct); X p->tm_year -= 1970; X p->tm_mon++; X len = strlen(t); X if (len != 12 && len != 10 && len != 6 && len != 4) usage(); X tp = t; X while (*tp) X if (!isdigit(*tp++)) X bad(); X if (len == 6 || len == 12) X p->tm_sec = conv(&tp, 59); X p->tm_min = conv(&tp, 59); X p->tm_hour = conv(&tp, 23); X if (len == 12 || len == 10) { X p->tm_year = conv(&tp, 99); X p->tm_mday = conv(&tp, 31); X p->tm_mon = conv(&tp, 12); X p->tm_year -= 70; X if (p->tm_year < 0) X p->tm_year += 100; X } X ct = p->tm_year * YEAR; X ct += ((p->tm_year + 1) / 4) * DAY; X days_per_month[1] = 28; X if (((p->tm_year + 2) % 4) == 0) X days_per_month[1]++; X len = 0; X p->tm_mon--; X while (len < p->tm_mon) X ct += days_per_month[len++] * DAY; X ct += --p->tm_mday * DAY; X ct += p->tm_hour * HOUR; X ct += p->tm_min * MIN; X ct += p->tm_sec; X if (stime(&ct)) X fprintf(stderr, "Set date not allowed\n"); X} X Xconv(ptr, max) Xchar **ptr; Xint max; X{ X int buf; X X *ptr -=2; X buf = atoi(*ptr); X **ptr = 0; X if (buf < 0 || buf > max) X bad(); X return(buf); X} X Xbad() X{ X fprintf(stderr, "Date: bad conversion\n"); X exit(1); X} X Xusage() X{ X fprintf(stderr, "Usage: date [-q] [[MMDDYY]hhmm[ss]]\n"); X exit(1); X} X Xisdigit(c) Xchar c; X{ X if (c >= '0' && c <= '9') X return(1); X else X return(0); X} + END-OF-FILE /local/ast/minix/tape3/commands/date.c chmod 'u=r,g=r,o=r' '/local/ast/minix/tape3/commands/date.c' set `wc -c '/local/ast/minix/tape3/commands/date.c'` count=$1 case $count in 2223) :;; *) echo 'Bad character count in ''/local/ast/minix/tape3/commands/date.c' >&2 echo 'Count should be 2223' >&2 esac echo Extracting '/local/ast/minix/tape3/lib/ctime.c' sed 's/^X//' > '/local/ast/minix/tape3/lib/ctime.c' << '+ END-OF-FILE ''/local/ast/minix/tape3/lib/ctime.c' X#include X Xstatic int days_per_month[] = { X 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 X}; Xstatic char *months[] = { X "Jan", "Feb", "Mar", "Apr", "May", "Jun", X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" X}; Xstatic char *days[] = { X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" X}; X X#define MIN 60L /* # seconds in a minute */ X#define HOUR (60 * MIN) /* # seconds in an hour */ X#define DAY (24 * HOUR) /* # seconds in a day */ X#define YEAR (365 * DAY) /* # seconds in a year */ X Xstatic struct tm tm; Xstatic char buf[26]; X Xchar *ctime(pt) Xlong *pt; X{ X register long t = *pt; X X long year; X X tm.tm_year = 0; X tm.tm_mon = 0; X tm.tm_mday = 1; X tm.tm_hour = 0; X tm.tm_min = 0; X tm.tm_sec = 0; X X /* t is elapsed time in seconds since Jan 1, 1970. */ X tm.tm_wday = (int) (t/DAY + 4L) % 7; /* Jan 1, 1970 is 4th wday */ X while (t >= (year=((tm.tm_year%4)==2) ? YEAR+DAY : YEAR)) { X tm.tm_year += 1; X t -= year; X } X tm.tm_year += 1970; X X /* t is now the offset into the current year, in seconds. */ X tm.tm_yday = (t/DAY); /* day # of the year, Jan 1 = 0 */ X X days_per_month[1] = 28; X if ((tm.tm_year % 4) == 0) /* check for leap year */ X days_per_month[1]++; X X /* Compute month. */ X while (t >= (days_per_month[tm.tm_mon] * DAY)) X t -= days_per_month[tm.tm_mon++] * DAY; X X /* Month established, now compute day of the month */ X while (t >= DAY) { X t -= DAY; X tm.tm_mday++; X } X X /* Day established, now do hour. */ X while (t >= HOUR) { X t -= HOUR; X tm.tm_hour++; X } X X /* Hour established, now do minute. */ X while (t >= MIN) { X t -= MIN; X tm.tm_min++; X } X X /* Residual time is # seconds. */ X tm.tm_sec = (int) t; X X /* Generate output in ASCII in buf. */ X sprintf(buf, "%s %s %2d %02d:%02d:%02d %d\n", X days[tm.tm_wday], months[tm.tm_mon], X tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year); X return buf; X} X Xstruct tm *localtime(pt) Xlong *pt; X{ X ctime(pt); X return &tm; X} X Xstruct tm *gmtime(pt) Xlong *pt; X{ X ctime(pt); X return &tm; X} + END-OF-FILE /local/ast/minix/tape3/lib/ctime.c chmod 'u=r,g=r,o=r' '/local/ast/minix/tape3/lib/ctime.c' set `wc -c '/local/ast/minix/tape3/lib/ctime.c'` count=$1 case $count in 1960) :;; *) echo 'Bad character count in ''/local/ast/minix/tape3/lib/ctime.c' >&2 echo 'Count should be 1960' >&2 esac exit 0