Module Name: src Committed By: ginsbach Date: Thu May 14 02:37:37 UTC 2009
Modified Files: src/distrib/sets/lists/base: mi src/distrib/sets/lists/comp: mi src/etc/mtree: NetBSD.dist src/include: time.h src/lib/libc/time: Makefile.inc src/share/examples: Makefile Added Files: src/lib/libc/time: getdate.3 getdate.c src/share/examples/getdate: Makefile datemsk.template posixmsk.example3 posixmsk.example4 Log Message: Add the getdate(3) function and getdate_err value, conforming to IEEE Std 1003.1 (``POSIX.1'') and the Open Group Base Specifications X/Open System Interfaces extension (``XSI''). To generate a diff of this commit: cvs rdiff -u -r1.808 -r1.809 src/distrib/sets/lists/base/mi cvs rdiff -u -r1.1259 -r1.1260 src/distrib/sets/lists/comp/mi cvs rdiff -u -r1.399 -r1.400 src/etc/mtree/NetBSD.dist cvs rdiff -u -r1.38 -r1.39 src/include/time.h cvs rdiff -u -r1.11 -r1.12 src/lib/libc/time/Makefile.inc cvs rdiff -u -r0 -r1.1 src/lib/libc/time/getdate.3 \ src/lib/libc/time/getdate.c cvs rdiff -u -r1.17 -r1.18 src/share/examples/Makefile cvs rdiff -u -r0 -r1.1 src/share/examples/getdate/Makefile \ src/share/examples/getdate/datemsk.template \ src/share/examples/getdate/posixmsk.example3 \ src/share/examples/getdate/posixmsk.example4 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/base/mi diff -u src/distrib/sets/lists/base/mi:1.808 src/distrib/sets/lists/base/mi:1.809 --- src/distrib/sets/lists/base/mi:1.808 Fri May 8 23:28:46 2009 +++ src/distrib/sets/lists/base/mi Thu May 14 02:37:35 2009 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.808 2009/05/08 23:28:46 christos Exp $ +# $NetBSD: mi,v 1.809 2009/05/14 02:37:35 ginsbach Exp $ # # Note: Don't delete entries from here - mark them as "obsolete" instead, # unless otherwise stated below. @@ -1787,6 +1787,7 @@ ./usr/share/examples/emul/ultrix/etc base-sys-examples ./usr/share/examples/fstab base-fstab-examples ./usr/share/examples/ftpd base-netutil-examples +./usr/share/examples/getdate base-sys-examples ./usr/share/examples/hostapd base-netutil-examples ./usr/share/examples/ipf base-netutil-examples ./usr/share/examples/isdn base-isdn-examples Index: src/distrib/sets/lists/comp/mi diff -u src/distrib/sets/lists/comp/mi:1.1259 src/distrib/sets/lists/comp/mi:1.1260 --- src/distrib/sets/lists/comp/mi:1.1259 Wed May 13 02:50:31 2009 +++ src/distrib/sets/lists/comp/mi Thu May 14 02:37:36 2009 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1259 2009/05/13 02:50:31 pgoyette Exp $ +# $NetBSD: mi,v 1.1260 2009/05/14 02:37:36 ginsbach Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -5535,7 +5535,8 @@ ./usr/share/man/cat3/getcurx.0 comp-c-catman .cat ./usr/share/man/cat3/getcury.0 comp-c-catman .cat ./usr/share/man/cat3/getcwd.0 comp-c-catman .cat -./usr/share/man/cat3/getdate.0 comp-obsolete obsolete +./usr/share/man/cat3/getdate.0 comp-c-catman .cat +./usr/share/man/cat3/getdate_err.0 comp-c-catman .cat ./usr/share/man/cat3/getdevmajor.0 comp-c-catman .cat ./usr/share/man/cat3/getdirentries.0 comp-c-catman .cat ./usr/share/man/cat3/getdiskbyname.0 comp-c-catman .cat @@ -16340,7 +16341,8 @@ ./usr/share/man/man3/getcurx.3 comp-c-man .man ./usr/share/man/man3/getcury.3 comp-c-man .man ./usr/share/man/man3/getcwd.3 comp-c-man .man -./usr/share/man/man3/getdate.3 comp-obsolete obsolete +./usr/share/man/man3/getdate.3 comp-c-man .man +./usr/share/man/man3/getdate_err.3 comp-c-man .man ./usr/share/man/man3/getdevmajor.3 comp-c-man .man ./usr/share/man/man3/getdirentries.3 comp-c-man .man ./usr/share/man/man3/getdiskbyname.3 comp-c-man .man Index: src/etc/mtree/NetBSD.dist diff -u src/etc/mtree/NetBSD.dist:1.399 src/etc/mtree/NetBSD.dist:1.400 --- src/etc/mtree/NetBSD.dist:1.399 Sat May 2 16:02:19 2009 +++ src/etc/mtree/NetBSD.dist Thu May 14 02:37:35 2009 @@ -1,4 +1,4 @@ -# $NetBSD: NetBSD.dist,v 1.399 2009/05/02 16:02:19 pooka Exp $ +# $NetBSD: NetBSD.dist,v 1.400 2009/05/14 02:37:35 ginsbach Exp $ # @(#)4.4BSD.dist 8.1 (Berkeley) 6/13/93 # Do not customize this file as it may be overwritten on upgrades. @@ -677,6 +677,7 @@ ./usr/share/examples/disktab ./usr/share/examples/fstab ./usr/share/examples/ftpd +./usr/share/examples/getdate ./usr/share/examples/hostapd ./usr/share/examples/ipf ./usr/share/examples/isdn Index: src/include/time.h diff -u src/include/time.h:1.38 src/include/time.h:1.39 --- src/include/time.h:1.38 Sun Jan 11 03:04:12 2009 +++ src/include/time.h Thu May 14 02:37:36 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: time.h,v 1.38 2009/01/11 03:04:12 christos Exp $ */ +/* $NetBSD: time.h,v 1.39 2009/05/14 02:37:36 ginsbach Exp $ */ /* * Copyright (c) 1989, 1993 @@ -131,6 +131,12 @@ struct tm * __restrict); #endif +#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \ + defined(_NETBSD_SOURCE) +struct tm *getdate(const char *); +extern int getdate_err; +#endif + #if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \ defined(_NETBSD_SOURCE) #include <sys/time.h> /* XXX for struct timespec */ Index: src/lib/libc/time/Makefile.inc diff -u src/lib/libc/time/Makefile.inc:1.11 src/lib/libc/time/Makefile.inc:1.12 --- src/lib/libc/time/Makefile.inc:1.11 Sat Jul 16 19:36:25 2005 +++ src/lib/libc/time/Makefile.inc Thu May 14 02:37:36 2009 @@ -1,10 +1,11 @@ -# $NetBSD: Makefile.inc,v 1.11 2005/07/16 19:36:25 christos Exp $ +# $NetBSD: Makefile.inc,v 1.12 2009/05/14 02:37:36 ginsbach Exp $ .PATH: ${.CURDIR}/time SRCS+= _daylight.c \ - asctime.c difftime.c localtime.c strftime.c strptime.c -MAN+= ctime.3 offtime.3 time2posix.3 tzfile.5 tzset.3 strftime.3 strptime.3 + asctime.c difftime.c localtime.c getdate.c strftime.c strptime.c +MAN+= ctime.3 getdate.3 offtime.3 strftime.3 strptime.3 \ + time2posix.3 tzfile.5 tzset.3 CPPFLAGS+=-DALL_STATE -DUSG_COMPAT MLINKS+=ctime.3 ctime_r.3 \ Index: src/share/examples/Makefile diff -u src/share/examples/Makefile:1.17 src/share/examples/Makefile:1.18 --- src/share/examples/Makefile:1.17 Mon Jan 19 07:08:28 2009 +++ src/share/examples/Makefile Thu May 14 02:37:36 2009 @@ -1,6 +1,6 @@ -# $NetBSD: Makefile,v 1.17 2009/01/19 07:08:28 jmmv Exp $ +# $NetBSD: Makefile,v 1.18 2009/05/14 02:37:36 ginsbach Exp $ -SUBDIR= amd apm disktab emul fstab ftpd hostapd isdn pppd racoon \ +SUBDIR= amd apm disktab emul fstab ftpd getdate hostapd isdn pppd racoon \ supfiles syslogd wsmoused .include <bsd.subdir.mk> Added files: Index: src/lib/libc/time/getdate.3 diff -u /dev/null src/lib/libc/time/getdate.3:1.1 --- /dev/null Thu May 14 02:37:37 2009 +++ src/lib/libc/time/getdate.3 Thu May 14 02:37:36 2009 @@ -0,0 +1,234 @@ +.\" $NetBSD: getdate.3,v 1.1 2009/05/14 02:37:36 ginsbach Exp $ +.\" +.\" Copyright (c) 2009, The NetBSD Foundation. +.\" All Rights Reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Brian Ginsbach. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd May 8, 2009 +.Dt GETDATE 3 +.Os +.Sh NAME +.Nm getdate , +.Nm getdate_err +.Nd convert user format date and time +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In time.h +.Ft "struct tm *" +.Fo "getdate" +.Fa "const char *str" +.Fc +.Vt extern int getdate_err ; +.Sh DESCRIPTION +The +.Fn getdate +function converts a date or time character string pointed to by +.Fa str +into a static +.Va tm +structure. +.Pp +The input string is parsed and interpreted using templates. +A text file containing templates is specified by the +environment variable +.Ev DATEMSK . +This should contain the full path to the template file. +Lines in the template file represent acceptable date and/or time +conversion specifications. +These specifications are similar to those given for +.Xr strptime 3 . +The first line in the template file that matches the input string +is used to interpret and convert to internal time format. +.Ss Internal Format Conversion +The following rules apply to converting the input into the internal format. +.Bl -bullet -offset indent +.It +If only the weekday is given, the conversion assumes today when the +weekday matches today or the first future matching weekday. +.It +If only the month and no year is given, the conversion assumes the +current month when the month matches or the first future matching month. +The first day of the month is assumed if no day is given. +.It +If only the year is given, the values of the +.Fa tm_mon , +.Fa tm_mday , +.Fa tm_wday , +.Fa tm_yday , +and +.Fa tm_isdst +members of the returned +.Va "struct tm" +are unspecified. +.It +If the century is given, but the year within the century is not given, +the conversion assumes the current year. +.It +If no hour, minute, and second are given, the conversion assumes +the current hour, minute, and second. +.It +If no date is given, the conversion assumes today when the given hour +is greater than the current hour and tomorrow when the given hour is less. +.It +If +.Cm \&%Z +is being scanned, then the broken-down time is based on the the +current time of the matched timezone and not the current runtime +environment timezone. +.El +.Sh RETURN VALUES +If successful, the +.Fn getdate +function returns a pointer to a static +.Va tm +structure containing the broken-down time. +Otherwise, a null pointer is returned and +.Va getdate_err +is set to indicate the error. +.Pp +The variable +.Va getdate_err +can have the following values: +.Bl -tag -width NNN +.It 1 +.Ev DATEMSK +environment variable is null or undefined. +.It 2 +Cannot open the template file for reading. +.It 3 +Get file status failed for template file. +.It 4 +Template file is not a regular file. +.It 5 +Encountered an error while reading the template file. +.It 6 +Cannot allocate memory. +.It 7 +Input string does not match any line in the template file. +.It 8 +Input string is invalid +.Pq for example February 31 +or could not be represented in a +.Va time_t . +.El +.Sh ENVIRONMENT +.Bl -tag -width DATEMSK +.It Ev DATEMSK +The full path to the text file containing the templates +for acceptable date and/or time conversions. +.El +.Sh FILES +.Bl -tag -width DATEMSK +.It Pa /usr/share/examples/getdate/datemsk.template +An example template file that could be specified via the +.Ev DATEMSK +environment variable. +.El +.Sh EXAMPLES +The following example shows the possible contents of a template file: +.Pp +.Bd -literal -offset indent -compact +%m +%A %B %d, %Y, %H:%M:%S +%A +%B +%m/%d/%y %I %p +%d,%m,%Y %H:%M +at %A the %dst of %B in %Y +run job at %I %p, %B %dnd +%A den %d. %B %Y %H.%M Uhr +.Ed +.Pp +The following are examples of valid input for the above template: +.Pp +.Bd -literal -offset indent -compact +10/1/87 4 PM +Friday +Firday September 18, 1987, 10:30:30 +24,9,1986 10:30 +at monday the 1st of december in 1986 +run job at 3 PM, december 2nd +.Ed +.Pp +The following examples show how local data and time specification can be +defined in the template. +.Pp +.Bl -column -offset indent ".Sy Input String" ".Sy Line in Template" +.It Sy "Input String" Ta Sy "Line in Template" +.It Li 11/27/86 Ta Li \&%m/\&%d/\&%y +.It Li 27.11.86 Ta Li \&%d.\&%m/\&%y +.It Li 86-11-27 Ta Li \&%y-\&%m-\&%d +.It Li "Friday 12:00:00" Ta "\&%A \&%H:\&%M:\&%S" +.El +.Pp +The following examples illustrate the Internal Format Conversion rules +given that the current date is +.Li "Mon Sep 22 12:19:47 EDT 1986" +and the +.Ev LC_TIME +environment variable is set to the default C locale. +.Pp +.Bl -column -offset indent ".Sy Input String" ".Sy Line in Template" ".Sy Date" +.It Sy Input String Ta Sy Line in Template Ta Sy Date +.It Li Mon Ta Li \&%a Ta Li "Mon Sep 22 12:19:47 EDT 1986" +.It Li Sun Ta Li \&%a Ta Li "Sun Sep 28 12:19:47 EDT 1986" +.It Li Fri Ta Li \&%a Ta Li "Sun Sep 26 12:19:47 EDT 1986" +.It Li September Ta Li \&%B Ta Li "Mon Sep 1 12:19:47 EDT 1986" +.It Li January Ta Li \&%B Ta Li "Thu Jan 1 12:19:47 EST 1987" +.It Li December Ta Li \&%B Ta Li "Mon Dec 1 12:19:47 EST 1987" +.It Li "Sep Mon" Ta Li "\&%b %a" Ta Li "Mon Sep 1 12:19:47 EDT 1986" +.It Li "Jan Fri" Ta Li "\&%b %a" Ta Li "Fri Jan 2 12:19:47 EDT 1987" +.It Li "Dec Mon" Ta Li "\&%b %a" Ta Li "Mon Dec 1 12:19:47 EDT 1986" +.It Li "Jan Wed 1989" Ta Li "\&%b \&%a \&%Y" Ta Li "Wed Jan 4 12:19:47 EST 1989" +.It Li "Fri 9" Ta Li "\&%a \&%H" Ta Li "Fri Sep 26 09:00:00 EDT 1986" +.It Li "Feb 10:30" Ta Li "\&%b \&%H:\&%S" Ta Li "Sun Feb 1 10:00:30 EST 1987" +.It Li 10:30 Ta Li "\&%H:\&%M" Ta Li "Tue Sep 23 10:30:00 EDT 1986" +.It Li 13:30 Ta Li "\&%H:\&%M" Ta Li "Tue Sep 22 13:30:00 EDT 1986" +.El +.Sh SEE ALSO +.Xr ctime 3 , +.Xr localtime 3 , +.Xr mktime 3 , +.Xr strftime 3 , +.Xr strptime 3 , +.Xr time 3 +.Sh STANDARDS +The +.Fn getdate +function conforms to +.St -p1003.1-2001 . +.Sh HISTORY +The +.Nm +function appeared in +.At V.4 . +.Sh BUGS +The +.Nm +interface is inherently unsafe for multi-threaded programs or libraries, +since it returns a pointer to a static variable and uses a global state +variable. Index: src/lib/libc/time/getdate.c diff -u /dev/null src/lib/libc/time/getdate.c:1.1 --- /dev/null Thu May 14 02:37:37 2009 +++ src/lib/libc/time/getdate.c Thu May 14 02:37:36 2009 @@ -0,0 +1,270 @@ +/* $NetBSD: getdate.c,v 1.1 2009/05/14 02:37:36 ginsbach Exp $ */ +/* + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Brian Ginsbach. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/stat.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <util.h> + +#define TMSENTINEL (-1) + +/* + * getdate_err is set to one of the following values on error. + * + * 1 The DATEMSK environment variable is null or undefined. + * 2 The template file cannot be opened for reading. + * 3 Failed to get file status information. + * 4 Template file is not a regular file. + * 5 Encountered an error while reading the template file. + * 6 Cannot allocate memory. + * 7 Input string does not match any line in the template. + * 8 Input string is invalid (for example, February 31) or could not + * be represented in a time_t. + */ + +int getdate_err; + +struct tm * +getdate(const char *str) +{ + char *datemsk, *line, *rp; + FILE *fp; + struct stat sb; + static struct tm rtm, tmnow; + struct tm *tmp, *rtmp = &rtm; + size_t lineno = 0; + time_t now; + + if (((datemsk = getenv("DATEMSK")) == NULL) || *datemsk == '\0') { + getdate_err = 1; + return (NULL); + } + + if (stat(datemsk, &sb) < 0) { + getdate_err = 3; + return (NULL); + } + + if ((sb.st_mode & S_IFMT) != S_IFREG) { + getdate_err = 4; + return (NULL); + } + + if ((fp = fopen(datemsk, "r")) == NULL) { + getdate_err = 2; + return (NULL); + } + + /* loop through datemsk file */ + errno = 0; + rp = NULL; + while ((line = fparseln(fp, NULL, &lineno, NULL, 0)) != NULL) { + /* initialize tmp with sentinels */ + rtm.tm_sec = rtm.tm_min = rtm.tm_hour = TMSENTINEL; + rtm.tm_mday = rtm.tm_mon = rtm.tm_year = TMSENTINEL; + rtm.tm_wday = rtm.tm_yday = rtm.tm_isdst = TMSENTINEL; + rtm.tm_gmtoff = 0; + rtm.tm_zone = NULL; + rp = strptime(str, line, rtmp); + free(line); + if (rp != NULL) + break; + errno = 0; + } + if (errno != 0 || ferror(fp)) { + if (errno == ENOMEM) + getdate_err = 6; + else + getdate_err = 5; + fclose(fp); + return (NULL); + } + if (feof(fp) || (rp != NULL && *rp != '\0')) { + getdate_err = 7; + return (NULL); + } + fclose(fp); + + time(&now); + tmp = localtime(&now); + tmnow = *tmp; + + /* + * This implementation does not accept setting the broken-down time + * to anything other than the localtime(). It is not possible to + * change the scanned timezone with %Z. + * + * Note IRIX and Solaris accept only the current zone for %Z. + * XXX Is there any implementation that matches the standard? + * XXX (Or am I reading the standard wrong?) + * + * Note: Neither XPG 6 (POSIX 2004) nor XPG 7 (POSIX 2008) + * requires strptime(3) support for %Z. + */ + + /* + * Given only a weekday find the first matching weekday starting + * with the current weekday and moving into the future. + */ + if (rtm.tm_wday != TMSENTINEL && rtm.tm_year == TMSENTINEL && + rtm.tm_mon == TMSENTINEL && rtm.tm_mday == TMSENTINEL) { + rtm.tm_year = tmnow.tm_year; + rtm.tm_mon = tmnow.tm_mon; + rtm.tm_mday = tmnow.tm_mday + + (rtm.tm_wday - tmnow.tm_wday + 7) % 7; + } + + /* + * Given only a month (and no year) find the first matching month + * starting with the current month and moving into the future. + */ + if (rtm.tm_mon != TMSENTINEL) { + if (rtm.tm_year == TMSENTINEL) { + rtm.tm_year = tmnow.tm_year + + ((rtm.tm_mon < tmnow.tm_mon)? 1 : 0); + } + if (rtm.tm_mday == TMSENTINEL) { + /* assume the first of the month */ + rtm.tm_mday = 1; + /* + * XXX This isn't documented! Just observed behavior. + * + * Given the weekday find the first matching weekday + * starting with the weekday of the first day of the + * the month and moving into the future. + */ + if (rtm.tm_wday != TMSENTINEL) { + struct tm tm; + + memset(&tm, 0, sizeof(struct tm)); + tm.tm_year = rtm.tm_year; + tm.tm_mon = rtm.tm_mon; + tm.tm_mday = 1; + mktime(&tm); + rtm.tm_mday += + (rtm.tm_wday - tm.tm_wday + 7) % 7; + } + } + } + + /* + * Given no time of day assume the current time of day. + */ + if (rtm.tm_hour == TMSENTINEL && + rtm.tm_min == TMSENTINEL && rtm.tm_sec == TMSENTINEL) { + rtm.tm_hour = tmnow.tm_hour; + rtm.tm_min = tmnow.tm_min; + rtm.tm_sec = tmnow.tm_sec; + } + /* + * Given an hour and no date, find the first matching hour starting + * with the current hour and moving into the future + */ + if (rtm.tm_hour != TMSENTINEL && + rtm.tm_year == TMSENTINEL && rtm.tm_mon == TMSENTINEL && + rtm.tm_mday == TMSENTINEL) { + rtm.tm_year = tmnow.tm_year; + rtm.tm_mon = tmnow.tm_mon; + rtm.tm_mday = tmnow.tm_mday; + if (rtm.tm_hour < tmnow.tm_hour) + rtm.tm_hour += 24; + } + + /* + * Set to 'sane' values; mktime(3) does funny things otherwise. + * No hours, no minutes, no seconds, no service. + */ + if (rtm.tm_hour == TMSENTINEL) + rtm.tm_hour = 0; + if (rtm.tm_min == TMSENTINEL) + rtm.tm_min = 0; + if (rtm.tm_sec == TMSENTINEL) + rtm.tm_sec = 0; + + /* + * Given only a year the values of month, day of month, day of year, + * week day and is daylight (summer) time are unspecified. + * (Specified on the Solaris man page not POSIX.) + */ + if (rtm.tm_year != TMSENTINEL && + rtm.tm_mon == TMSENTINEL && rtm.tm_mday == TMSENTINEL) { + rtm.tm_mon = 0; + rtm.tm_mday = 1; + /* + * XXX More undocumented functionality but observed. + * + * Given the weekday find the first matching weekday + * starting with the weekday of the first day of the the + * month and moving into the future. + */ + if (rtm.tm_wday != TMSENTINEL) { + struct tm tm; + + memset(&tm, 0, sizeof(struct tm)); + tm.tm_year = rtm.tm_year; + tm.tm_mon = rtm.tm_mon; + tm.tm_mday = 1; + mktime(&tm); + rtm.tm_mday += (rtm.tm_wday - tm.tm_wday + 7) % 7; + } + } + + /* + * Given only the century but no year within, the current year + * is assumed. (Specified on the Solaris man page not POSIX.) + * + * Warning ugly end case + * + * This is more work since strptime(3) doesn't "do the right thing". + */ + if (rtm.tm_year != TMSENTINEL && (rtm.tm_year - 1900) >= 0) { + rtm.tm_year -= 1900; + rtm.tm_year += (tmnow.tm_year % 100); + } + + /* + * mktime() will normalize all values and also check that the + * value will fit into a time_t. + * + * This is only for POSIX correctness. A date >= 1900 is + * really ok, but using a time_t limits things. + */ + if (mktime(rtmp) < 0) { + getdate_err = 8; + return (NULL); + } + + return (rtmp); +} Index: src/share/examples/getdate/Makefile diff -u /dev/null src/share/examples/getdate/Makefile:1.1 --- /dev/null Thu May 14 02:37:37 2009 +++ src/share/examples/getdate/Makefile Thu May 14 02:37:36 2009 @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2009/05/14 02:37:36 ginsbach Exp $ + +NOOBJ= # defined + +.include <bsd.own.mk> + +.if ${MKSHARE} != "no" +FILES= datemsk.template posixmsk.example3 posixmsk.example4 +FILESDIR=/usr/share/examples/getdate +.endif + +.include <bsd.prog.mk> Index: src/share/examples/getdate/datemsk.template diff -u /dev/null src/share/examples/getdate/datemsk.template:1.1 --- /dev/null Thu May 14 02:37:37 2009 +++ src/share/examples/getdate/datemsk.template Thu May 14 02:37:36 2009 @@ -0,0 +1,38 @@ +# $NetBSD: datemsk.template,v 1.1 2009/05/14 02:37:36 ginsbach Exp $ +# getdate(3) DATEMSK template file +%m/%d/%y %I:%M:%S %p +%m/%d/%Y %I:%M:%S %p +%m/%d/%y %H:%M:%S +%m/%d/%Y %H:%M:%S +%m/%d/%y %I:%M %p +%m/%d/%Y %I:%M %p +%m/%d/%y %H:%M +%m/%d/%Y %H:%M +%m/%d/%y %I %p +%m/%d/%Y %I %p +%m/%d/%y %H +%m/%d/%Y %H +%m/%d/%y +%m/%d/%Y +%m/%d +%b %d, %Y %I:%M:%S %p +%b %d, %Y %H:%M:%S +%B %d, %Y %I:%M:%S %p +%B %d, %Y %H:%M:%S +%b %d, %Y %I:%M %p +%b %d, %Y %H:%M +%B %d, %Y %I:%M %p +%B %d, %Y %H:%M +%b %d, %Y %I %p +%b %d, %Y %H +%B %d, %Y %I %p +%B %d, %Y %H +%b %d, %Y +%B %d, %Y +%b %d +%B %d +%m%d%H%M%y +%m%d%H%M%Y +%m%d%H%M +%m%d%H +%m%d Index: src/share/examples/getdate/posixmsk.example3 diff -u /dev/null src/share/examples/getdate/posixmsk.example3:1.1 --- /dev/null Thu May 14 02:37:37 2009 +++ src/share/examples/getdate/posixmsk.example3 Thu May 14 02:37:36 2009 @@ -0,0 +1,9 @@ +# $NetBSD: posixmsk.example3,v 1.1 2009/05/14 02:37:36 ginsbach Exp $ +# +# The Open Group Base Specifications Issue 7 / IEEE Std 1003.1-2008 +# Example 3 +# +%m/%d/%y +%d.%m.%y +%y-%m-%d +%A %H:%M:%S Index: src/share/examples/getdate/posixmsk.example4 diff -u /dev/null src/share/examples/getdate/posixmsk.example4:1.1 --- /dev/null Thu May 14 02:37:37 2009 +++ src/share/examples/getdate/posixmsk.example4 Thu May 14 02:37:36 2009 @@ -0,0 +1,12 @@ +# $NetBSD: posixmsk.example4,v 1.1 2009/05/14 02:37:36 ginsbach Exp $ +# +# The Open Group Base Specifications Issue 7 / IEEE Std 1003.1-2008 +# Example 4 +# +%a +%B +%b %a +%b %a %Y +%a %H +%b %H:%S +%H:%M