merge with 1.8.1d
[coreutils.git] / src / date.c
blobc31c344ec0833e006a2ca248ec608596ee4bf81e
1 /* date - print or set the system date and time
2 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Options:
19 -d DATESTR Display the date DATESTR.
20 -s DATESTR Set the date to DATESTR.
21 -u Display or set the date in universal instead of local time.
22 +FORMAT Specify custom date output format, described below.
23 MMDDhhmm[[CC]YY][.ss] Set the date in the format described below.
25 If one non-option argument is given, it is used as the date to which
26 to set the system clock, and must have the format:
27 MM month (01..12)
28 DD day in month (01..31)
29 hh hour (00..23)
30 mm minute (00..59)
31 CC first 2 digits of year (optional, defaults to current) (00..99)
32 YY last 2 digits of year (optional, defaults to current) (00..99)
33 ss second (00..61)
35 If a non-option argument that starts with a `+' is specified, it
36 is used to control the format in which the date is printed; it
37 can contain any of the `%' substitutions allowed by the strftime
38 function. A newline is always added at the end of the output.
40 David MacKenzie <djm@gnu.ai.mit.edu> */
42 #ifdef HAVE_CONFIG_H
43 #if defined (CONFIG_BROKETS)
44 /* We use <config.h> instead of "config.h" so that a compilation
45 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
46 (which it would do because it found this file in $srcdir). */
47 #include <config.h>
48 #else
49 #include "config.h"
50 #endif
51 #endif
53 #include <stdio.h>
54 #include <getopt.h>
55 #include <sys/types.h>
57 #include "version.h"
58 #include "system.h"
60 #ifdef TM_IN_SYS_TIME
61 #include <sys/time.h>
62 #else
63 #include <time.h>
64 #endif
66 #ifndef STDC_HEADERS
67 time_t mktime ();
68 size_t strftime ();
69 time_t time ();
70 #endif
72 int putenv ();
73 int stime ();
75 char *xrealloc ();
76 time_t get_date ();
77 time_t posixtime ();
78 void error ();
80 static void show_date ();
81 static void usage ();
83 /* putenv string to use Universal Coordinated Time.
84 POSIX.2 says it should be "TZ=UCT0" or "TZ=GMT0". */
85 #ifndef TZ_UCT
86 #if defined(hpux) || defined(__hpux__) || defined(ultrix) || defined(__ultrix__) || defined(USG)
87 #define TZ_UCT "TZ=GMT0"
88 #else
89 #define TZ_UCT "TZ="
90 #endif
91 #endif
93 /* The name this program was run with, for error messages. */
94 char *program_name;
96 /* If non-zero, display usage information and exit. */
97 static int show_help;
99 /* If non-zero, print the version on standard output and exit. */
100 static int show_version;
102 static struct option const long_options[] =
104 {"date", required_argument, NULL, 'd'},
105 {"help", no_argument, &show_help, 1},
106 {"set", required_argument, NULL, 's'},
107 {"uct", no_argument, NULL, 'u'},
108 {"universal", no_argument, NULL, 'u'},
109 {"version", no_argument, &show_version, 1},
110 {NULL, 0, NULL, 0}
113 void
114 main (argc, argv)
115 int argc;
116 char **argv;
118 int optc;
119 char *datestr = NULL;
120 time_t when;
121 int set_date = 0;
122 int universal_time = 0;
124 program_name = argv[0];
126 while ((optc = getopt_long (argc, argv, "d:s:u", long_options, (int *) 0))
127 != EOF)
128 switch (optc)
130 case 0:
131 break;
132 case 'd':
133 datestr = optarg;
134 break;
135 case 's':
136 datestr = optarg;
137 set_date = 1;
138 break;
139 case 'u':
140 universal_time = 1;
141 break;
142 default:
143 usage ();
146 if (show_version)
148 printf ("%s\n", version_string);
149 exit (0);
152 if (show_help)
153 usage ();
155 if (argc - optind > 1)
156 usage ();
158 if (universal_time && putenv (TZ_UCT) != 0)
159 error (1, 0, "virtual memory exhausted");
161 time (&when);
163 if (datestr)
164 when = get_date (datestr, NULL);
166 if (argc - optind == 1 && argv[optind][0] != '+')
168 when = posixtime (argv[optind]);
169 set_date = 1;
172 if (when == -1)
173 error (1, 0, "invalid date");
175 if (set_date && stime (&when) == -1)
176 error (0, errno, "cannot set date");
178 if (argc - optind == 1 && argv[optind][0] == '+')
179 show_date (argv[optind] + 1, when);
180 else
181 show_date ((char *) NULL, when);
183 exit (0);
186 /* Display the date and/or time in WHEN according to the format specified
187 in FORMAT, followed by a newline. If FORMAT is NULL, use the
188 standard output format (ctime style but with a timezone inserted). */
190 static void
191 show_date (format, when)
192 char *format;
193 time_t when;
195 struct tm *tm;
196 char *out = NULL;
197 size_t out_length = 0;
199 tm = localtime (&when);
201 if (format == NULL)
202 /* Print the date in the default format. Vanilla ANSI C strftime
203 doesn't support %e, but POSIX requires it. If you don't use
204 a GNU strftime, make sure yours supports %e. */
205 format = "%a %b %e %H:%M:%S %Z %Y";
206 else if (*format == '\0')
208 printf ("\n");
209 return;
214 out_length += 200;
215 out = (char *) xrealloc (out, out_length);
217 while (strftime (out, out_length, format, tm) == 0);
219 printf ("%s\n", out);
220 free (out);
223 static void
224 usage ()
226 fprintf (stderr, "\
227 Usage: %s [{--help,--version}] [-u] [-d datestr] [-s datestr]\n\
228 [--date datestr] [--set datestr] [--uct] [--universal]\n\
229 [+FORMAT] [MMDDhhmm[[CC]YY][.ss]]\n",
230 program_name);
231 exit (1);