xref: /onnv-gate/usr/src/lib/libcmd/common/date.c (revision 4887)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1992-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                                                                      *
20*4887Schin ***********************************************************************/
21*4887Schin #pragma prototyped
22*4887Schin /*
23*4887Schin  * Glenn Fowler
24*4887Schin  * AT&T Research
25*4887Schin  *
26*4887Schin  * date -- set/display date
27*4887Schin  */
28*4887Schin 
29*4887Schin static const char usage[] =
30*4887Schin "[-?\n@(#)$Id: date (AT&T Research) 2007-03-28 $\n]"
31*4887Schin USAGE_LICENSE
32*4887Schin "[+NAME?date - set/list/convert dates]"
33*4887Schin "[+DESCRIPTION?\bdate\b sets the current date and time (with appropriate"
34*4887Schin "	privilege), lists the current date or file dates, or converts"
35*4887Schin "	dates.]"
36*4887Schin "[+?Most common \adate\a forms are recognized, including those for"
37*4887Schin "	\bcrontab\b(1), \bls\b(1), \btouch\b(1), and the default"
38*4887Schin "	output from \bdate\b itself.]"
39*4887Schin "[+?If the \adate\a operand consists of 4, 6, 8, 10 or 12 digits followed"
40*4887Schin "	by an optional \b.\b and two digits then it is interpreted as:"
41*4887Schin "	\aHHMM.SS\a, \addHHMM.SS\a, \ammddHHMM.SS\a, \ammddHHMMyy.SS\a or"
42*4887Schin "	\ayymmddHHMM.SS\a, or \ammddHHMMccyy.SS\a or \accyymmddHHMM.SS\a."
43*4887Schin "	Conflicting standards and practice allow a leading or trailing"
44*4887Schin "	2 or 4 digit year for the 10 and 12 digit forms; the X/Open trailing"
45*4887Schin "	form is used to disambiguate (\btouch\b(1) uses the leading form.)"
46*4887Schin "	Avoid the 10 digit form to avoid confusion. The digit fields are:]{"
47*4887Schin "		[+cc?Century - 1, 19-20.]"
48*4887Schin "		[+yy?Year in century, 00-99.]"
49*4887Schin "		[+mm?Month, 01-12.]"
50*4887Schin "		[+dd?Day of month, 01-31.]"
51*4887Schin "		[+HH?Hour, 00-23.]"
52*4887Schin "		[+MM?Minute, 00-59.]"
53*4887Schin "		[+SS?Seconds, 00-60.]"
54*4887Schin "}"
55*4887Schin "[+?If more than one \adate\a operand is specified then:]{"
56*4887Schin "		[+1.?Each operand sets the reference date for the next"
57*4887Schin "			operand.]"
58*4887Schin "		[+2.?The date is listed for each operand.]"
59*4887Schin "		[+3.?The system date is not set.]"
60*4887Schin "}"
61*4887Schin 
62*4887Schin "[a:access-time|atime?List file argument access times.]"
63*4887Schin "[c:change-time|ctime?List file argument change times.]"
64*4887Schin "[d:date?Use \adate\a as the current date and do not set the system"
65*4887Schin "	clock.]:[date]"
66*4887Schin "[e:epoch?Output the date in seconds since the epoch."
67*4887Schin "	Equivalent to \b--format=%s\b.]"
68*4887Schin "[E:elapsed?Interpret pairs of arguments as start and stop dates, sum the"
69*4887Schin "	differences between all pairs, and list the result as a"
70*4887Schin "	\bfmtelapsed\b(3) elapsed time on the standard output. If there are"
71*4887Schin "	an odd number of arguments then the last time argument is differenced"
72*4887Schin "	with the current time.]"
73*4887Schin "[f:format?Output the date according to the \bstrftime\b(3) \aformat\a."
74*4887Schin "	For backwards compatibility, a first argument of the form"
75*4887Schin "	\b+\b\aformat\a is equivalent to \b-f\b format."
76*4887Schin "	\aformat\a is in \bprintf\b(3) style, where %\afield\a names"
77*4887Schin "	a fixed size field, zero padded if necessary,"
78*4887Schin "	and \\\ac\a and \\\annn\a sequences are as in C. Invalid"
79*4887Schin "	%\afield\a specifications and all other characters are copied"
80*4887Schin "	without change. \afield\a may be preceded by \b%-\b to turn off"
81*4887Schin "	padding or \b%_\b to pad with space, otherwise numeric fields"
82*4887Schin "	are padded with \b0\b and string fields are padded with space."
83*4887Schin "	\afield\a may also be preceded by \bE\b for alternate era"
84*4887Schin "	representation or \bO\b for alternate digit representation (if"
85*4887Schin "	supported by the current locale.) Finally, an integral \awidth\a"
86*4887Schin "	preceding \afield\a truncates the field to \awidth\a characters."
87*4887Schin "	The fields are:]:[format]{"
88*4887Schin "		[+%?% character]"
89*4887Schin "		[+a?abbreviated weekday name]"
90*4887Schin "		[+A?full weekday name]"
91*4887Schin "		[+b?abbreviated month name]"
92*4887Schin "		[+c?\bctime\b(3) style date without the trailing newline]"
93*4887Schin "		[+C?2-digit century]"
94*4887Schin "		[+d?day of month number]"
95*4887Schin "		[+D?date as \amm/dd/yy\a]"
96*4887Schin "		[+e?blank padded day of month number]"
97*4887Schin "		[+E?unpadded day of month number]"
98*4887Schin "		[+f?locale default override date format]"
99*4887Schin "		[+F?locale default date format]"
100*4887Schin "		[+g?\bls\b(1) \b-l\b recent date with \ahh:mm\a]"
101*4887Schin "		[+G?\bls\b(1) \b-l\b distant date with \ayyyy\a]"
102*4887Schin "		[+h?abbreviated month name]"
103*4887Schin "		[+H?24-hour clock hour]"
104*4887Schin "		[+i?international \bdate\b(1) date with time zone type name]"
105*4887Schin "		[+I?12-hour clock hour]"
106*4887Schin "		[+j?1-offset Julian date]"
107*4887Schin "		[+J?0-offset Julian date]"
108*4887Schin "		[+k?\bdate\b(1) style date]"
109*4887Schin "		[+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b]"
110*4887Schin "		[+l?\bls\b(1) \b-l\b date; equivalent to \b%Q/%g/%G/\b]"
111*4887Schin "		[+m?month number]"
112*4887Schin "		[+M?minutes]"
113*4887Schin "		[+n?newline character]"
114*4887Schin "		[+N?nanoseconds 000000000-999999999]"
115*4887Schin "		[+p?meridian (e.g., \bAM\b or \bPM\b)]"
116*4887Schin "		[+q?time zone type name (nation code)]"
117*4887Schin "		[+Q?\a<del>recent<del>distant<del>\a: \a<del>\a is a unique"
118*4887Schin "			delimter character; \arecent\a format for recent"
119*4887Schin "			dates, \adistant\a format otherwise]"
120*4887Schin "		[+r?12-hour time as \ahh:mm:ss meridian\a]"
121*4887Schin "		[+R?24-hour time as \ahh:mm\a]"
122*4887Schin "		[+s?number of seconds since the epoch; \a.prec\a preceding"
123*4887Schin "			\bs\b appends \aprec\a nanosecond digits, \b9\b if"
124*4887Schin "			\aprec\a is omitted]"
125*4887Schin "		[+S?seconds 00-60]"
126*4887Schin "		[+t?tab character]"
127*4887Schin "		[+T?24-hour time as \ahh:mm:ss\a]"
128*4887Schin "		[+u?weekday number 1(Monday)-7]"
129*4887Schin "		[+U?week number with Sunday as the first day]"
130*4887Schin "		[+V?ISO week number (i18n is \afun\a)]"
131*4887Schin "		[+w?weekday number 0(Sunday)-6]"
132*4887Schin "		[+W?week number with Monday as the first day]"
133*4887Schin "		[+x?locale date style that includes month, day and year]"
134*4887Schin "		[+X?locale time style that includes hours and minutes]"
135*4887Schin "		[+y?2-digit year (you'll be sorry)]"
136*4887Schin "		[+Y?4-digit year]"
137*4887Schin "		[+z?time zone \aSHHMM\a west of GMT offset where S is"
138*4887Schin "			\b+\b or \b-\b]"
139*4887Schin "		[+Z?time zone name]"
140*4887Schin "		[+=[=]][-+]]flag?set (default or +) or clear (-) \aflag\a"
141*4887Schin "			for the remainder of \aformat\a, or for the remainder"
142*4887Schin "			of the process if \b==\b is specified. \aflag\a may be:]{"
143*4887Schin "			[+l?enable leap second adjustments]"
144*4887Schin "			[+n?convert \b%S\b as \b%S.%N\b]"
145*4887Schin "			[+u?UTC time zone]"
146*4887Schin "		}"
147*4887Schin "		[+#?equivalent to %s]"
148*4887Schin "		[+??alternate?use \aalternate\a format if a default format"
149*4887Schin "			override has not been specified, e.g., \bls\b(1) uses"
150*4887Schin "			\"%?%l\"; export TM_OPTIONS=\"format='\aoverride\a'\""
151*4887Schin "			to override the default]"
152*4887Schin "}"
153*4887Schin "[i:incremental|adjust?Set the system time in incrementatl adjustments to"
154*4887Schin "	avoid complete time shift shock. Negative adjustments still maintain"
155*4887Schin "	monotonic increasing time. Not available on all systems.]"
156*4887Schin "[L:last?List only the last time for multiple \adate\a operands.]"
157*4887Schin "[l:leap-seconds?Include leap seconds in time calculations. Leap seconds"
158*4887Schin "	after the ast library release date are not accounted for.]"
159*4887Schin "[m:modify-time|mtime?List file argument modify times.]"
160*4887Schin "[n!:network?Set network time.]"
161*4887Schin "[p:parse?Add \aformat\a to the list of \bstrptime\b(3) parse conversion"
162*4887Schin "	formats. \aformat\a follows the same conventions as the"
163*4887Schin "	\b--format\b option, with the addition of these format"
164*4887Schin "	fields:]:[format]{"
165*4887Schin "		[+|?If the format failed before this point then restart"
166*4887Schin "			the parse with the remaining format.]"
167*4887Schin "		[+&?Call the \btmdate\b(3) heuristic parser. This is"
168*4887Schin "			is the default when \b--parse\b is omitted.]"
169*4887Schin "}"
170*4887Schin "[s:show?Show the date without setting the system time.]"
171*4887Schin "[u:utc|gmt|zulu?Output dates in \acoordinated universal time\a (UTC).]"
172*4887Schin "[U:unelapsed?Interpret each argument as \bfmtelapsed\b(3) elapsed"
173*4887Schin "	time and list the \bstrelapsed\b(3) 1/\ascale\a seconds.]#[scale]"
174*4887Schin "[z:list-zones?List the known time zone table and exit. The table columns"
175*4887Schin "	are: country code, standard zone name, savings time zone name,"
176*4887Schin "	minutes west of \bUTC\b, and savings time minutes offset. Blank"
177*4887Schin "	or empty entries are listed as \b-\b.]"
178*4887Schin 
179*4887Schin "\n"
180*4887Schin "\n[ +format | date ... | file ... ]\n"
181*4887Schin "\n"
182*4887Schin 
183*4887Schin "[+SEE ALSO?\bcrontab\b(1), \bls\b(1), \btouch\b(1), \bfmtelapsed\b(3),"
184*4887Schin "	\bstrftime\b(3), \bstrptime\b(3), \btm\b(3)]"
185*4887Schin ;
186*4887Schin 
187*4887Schin #include <cmd.h>
188*4887Schin #include <ls.h>
189*4887Schin #include <proc.h>
190*4887Schin #include <tmx.h>
191*4887Schin #include <times.h>
192*4887Schin 
193*4887Schin typedef struct Fmt
194*4887Schin {
195*4887Schin 	struct Fmt*	next;
196*4887Schin 	char*		format;
197*4887Schin } Fmt_t;
198*4887Schin 
199*4887Schin #ifndef ENOSYS
200*4887Schin #define ENOSYS		EINVAL
201*4887Schin #endif
202*4887Schin 
203*4887Schin /*
204*4887Schin  * set the system clock
205*4887Schin  * the standards wimped out here
206*4887Schin  */
207*4887Schin 
208*4887Schin static int
209*4887Schin settime(const char* cmd, Time_t now, int adjust, int network)
210*4887Schin {
211*4887Schin 	char*		s;
212*4887Schin 	char**		argv;
213*4887Schin 	char*		args[5];
214*4887Schin 	char		buf[128];
215*4887Schin 
216*4887Schin 	if (!adjust && !network)
217*4887Schin 		return tmxsettime(now);
218*4887Schin 	argv = args;
219*4887Schin 	s = "/usr/bin/date";
220*4887Schin 	if (!streq(cmd, s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
221*4887Schin 	{
222*4887Schin 		*argv++ = s;
223*4887Schin 		if (streq(astconf("UNIVERSE", NiL, NiL), "att"))
224*4887Schin 		{
225*4887Schin 			tmxfmt(buf, sizeof(buf), "%m%d%H" "%M" "%Y.%S", now);
226*4887Schin 			if (adjust)
227*4887Schin 				*argv++ = "-a";
228*4887Schin 		}
229*4887Schin 		else
230*4887Schin 		{
231*4887Schin 			tmxfmt(buf, sizeof(buf), "%Y" "%m%d%H" "%M.%S", now);
232*4887Schin 			if (network)
233*4887Schin 				*argv++ = "-n";
234*4887Schin 			if (tm_info.flags & TM_UTC)
235*4887Schin 				*argv++ = "-u";
236*4887Schin 		}
237*4887Schin 		*argv++ = buf;
238*4887Schin 		*argv = 0;
239*4887Schin 		if (!procrun(s, args))
240*4887Schin 			return 0;
241*4887Schin 	}
242*4887Schin 	return -1;
243*4887Schin }
244*4887Schin 
245*4887Schin /*
246*4887Schin  * convert s to Time_t with error checking
247*4887Schin  */
248*4887Schin 
249*4887Schin static Time_t
250*4887Schin convert(register Fmt_t* f, char* s, Time_t now)
251*4887Schin {
252*4887Schin 	char*	t;
253*4887Schin 	char*	u;
254*4887Schin 
255*4887Schin 	do
256*4887Schin 	{
257*4887Schin 		now = tmxscan(s, &t, f->format, &u, now, 0);
258*4887Schin 		if (!*t && (!f->format || !*u))
259*4887Schin 			break;
260*4887Schin 	} while (f = f->next);
261*4887Schin 	if (!f || *t)
262*4887Schin 		error(3, "%s: invalid date specification", f ? t : s);
263*4887Schin 	return now;
264*4887Schin }
265*4887Schin 
266*4887Schin int
267*4887Schin b_date(int argc, register char** argv, void* context)
268*4887Schin {
269*4887Schin 	register int	n;
270*4887Schin 	register char*	s;
271*4887Schin 	register Fmt_t*	f;
272*4887Schin 	char*		t;
273*4887Schin 	unsigned long	u;
274*4887Schin 	Time_t		now;
275*4887Schin 	Time_t		ts;
276*4887Schin 	Time_t		te;
277*4887Schin 	Time_t		e;
278*4887Schin 	char		buf[128];
279*4887Schin 	Fmt_t*		fmts;
280*4887Schin 	Fmt_t		fmt;
281*4887Schin 	struct stat	st;
282*4887Schin 
283*4887Schin 	char*		cmd = argv[0];	/* original command path	*/
284*4887Schin 	char*		format = 0;	/* tmxfmt() format		*/
285*4887Schin 	char*		string = 0;	/* date string			*/
286*4887Schin 	int		elapsed = 0;	/* args are start/stop pairs	*/
287*4887Schin 	int		filetime = 0;	/* use this st_ time field	*/
288*4887Schin 	int		increment = 0;	/* incrementally adjust time	*/
289*4887Schin 	int		last = 0;	/* display the last time arg	*/
290*4887Schin 	Tm_zone_t*	listzones = 0;	/* known time zone table	*/
291*4887Schin 	int		network = 0;	/* don't set network time	*/
292*4887Schin 	int		show = 0;	/* show date and don't set	*/
293*4887Schin 	int		unelapsed = 0;	/* fmtelapsed() => strelapsed	*/
294*4887Schin 
295*4887Schin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
296*4887Schin 	setlocale(LC_ALL, "");
297*4887Schin 	tm_info.flags = TM_DATESTYLE;
298*4887Schin 	fmts = &fmt;
299*4887Schin 	fmt.format = "";
300*4887Schin 	fmt.next = 0;
301*4887Schin 	for (;;)
302*4887Schin 	{
303*4887Schin 		switch (optget(argv, usage))
304*4887Schin 		{
305*4887Schin 		case 'a':
306*4887Schin 		case 'c':
307*4887Schin 		case 'm':
308*4887Schin 			filetime = opt_info.option[1];
309*4887Schin 			continue;
310*4887Schin 		case 'd':
311*4887Schin 			string = opt_info.arg;
312*4887Schin 			show = 1;
313*4887Schin 			continue;
314*4887Schin 		case 'e':
315*4887Schin 			format = "%#";
316*4887Schin 			continue;
317*4887Schin 		case 'E':
318*4887Schin 			elapsed = 1;
319*4887Schin 			continue;
320*4887Schin 		case 'f':
321*4887Schin 			format = opt_info.arg;
322*4887Schin 			continue;
323*4887Schin 		case 'i':
324*4887Schin 			increment = 1;
325*4887Schin 			continue;
326*4887Schin 		case 'l':
327*4887Schin 			tm_info.flags |= TM_LEAP;
328*4887Schin 			continue;
329*4887Schin 		case 'L':
330*4887Schin 			last = 1;
331*4887Schin 			continue;
332*4887Schin 		case 'n':
333*4887Schin 			network = 1;
334*4887Schin 			continue;
335*4887Schin 		case 'p':
336*4887Schin 			if (!(f = newof(0, Fmt_t, 1, 0)))
337*4887Schin 				error(ERROR_SYSTEM|3, "out of space [format]");
338*4887Schin 			f->next = fmts;
339*4887Schin 			f->format = opt_info.arg;
340*4887Schin 			fmts = f;
341*4887Schin 			continue;
342*4887Schin 		case 's':
343*4887Schin 			show = 1;
344*4887Schin 			continue;
345*4887Schin 		case 'u':
346*4887Schin 			tm_info.flags |= TM_UTC;
347*4887Schin 			continue;
348*4887Schin 		case 'U':
349*4887Schin 			unelapsed = (int)opt_info.num;
350*4887Schin 			continue;
351*4887Schin 		case 'z':
352*4887Schin 			listzones = tm_data.zone;
353*4887Schin 			continue;
354*4887Schin 		case '?':
355*4887Schin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
356*4887Schin 			continue;
357*4887Schin 		case ':':
358*4887Schin 			error(2, "%s", opt_info.arg);
359*4887Schin 			continue;
360*4887Schin 		}
361*4887Schin 		break;
362*4887Schin 	}
363*4887Schin 	argv += opt_info.index;
364*4887Schin 	if (error_info.errors)
365*4887Schin 		error(ERROR_USAGE|4, "%s", optusage(NiL));
366*4887Schin 	now = tmxgettime();
367*4887Schin 	if (listzones)
368*4887Schin 	{
369*4887Schin 		s = "-";
370*4887Schin 		while (listzones->standard)
371*4887Schin 		{
372*4887Schin 			if (listzones->type)
373*4887Schin 				s = listzones->type;
374*4887Schin 			sfprintf(sfstdout, "%3s %4s %4s %4d %4d\n", s, *listzones->standard ? listzones->standard : "-", listzones->daylight ? listzones->daylight : "-", listzones->west, listzones->dst);
375*4887Schin 			listzones++;
376*4887Schin 			show = 1;
377*4887Schin 		}
378*4887Schin 	}
379*4887Schin 	else if (elapsed)
380*4887Schin 	{
381*4887Schin 		e = 0;
382*4887Schin 		while (s = *argv++)
383*4887Schin 		{
384*4887Schin 			if (!(t = *argv++))
385*4887Schin 			{
386*4887Schin 				argv--;
387*4887Schin 				t = "now";
388*4887Schin 			}
389*4887Schin 			ts = convert(fmts, s, now);
390*4887Schin 			te = convert(fmts, t, now);
391*4887Schin 			if (te > ts)
392*4887Schin 				e += te - ts;
393*4887Schin 			else
394*4887Schin 				e += ts - te;
395*4887Schin 		}
396*4887Schin 		sfputr(sfstdout, fmtelapsed((unsigned long)tmxsec(e), 1), '\n');
397*4887Schin 		show = 1;
398*4887Schin 	}
399*4887Schin 	else if (unelapsed)
400*4887Schin 	{
401*4887Schin 		while (s = *argv++)
402*4887Schin 		{
403*4887Schin 			u = strelapsed(s, &t, unelapsed);
404*4887Schin 			if (*t)
405*4887Schin 				error(3, "%s: invalid elapsed time", s);
406*4887Schin 			sfprintf(sfstdout, "%lu\n", u);
407*4887Schin 		}
408*4887Schin 		show = 1;
409*4887Schin 	}
410*4887Schin 	else if (filetime)
411*4887Schin 	{
412*4887Schin 		if (!*argv)
413*4887Schin 			error(ERROR_USAGE|4, "%s", optusage(NiL));
414*4887Schin 		n = argv[1] != 0;
415*4887Schin 		while (s = *argv++)
416*4887Schin 		{
417*4887Schin 			if (stat(s, &st))
418*4887Schin 				error(2, "%s: not found", s);
419*4887Schin 			else
420*4887Schin 			{
421*4887Schin 				switch (filetime)
422*4887Schin 				{
423*4887Schin 				case 'a':
424*4887Schin 					now = tmxgetatime(&st);
425*4887Schin 					break;
426*4887Schin 				case 'c':
427*4887Schin 					now = tmxgetctime(&st);
428*4887Schin 					break;
429*4887Schin 				default:
430*4887Schin 					now = tmxgetmtime(&st);
431*4887Schin 					break;
432*4887Schin 				}
433*4887Schin 				tmxfmt(buf, sizeof(buf), format, now);
434*4887Schin 				if (n)
435*4887Schin 					sfprintf(sfstdout, "%s: %s\n", s, buf);
436*4887Schin 				else
437*4887Schin 					sfprintf(sfstdout, "%s\n", buf);
438*4887Schin 				show = 1;
439*4887Schin 			}
440*4887Schin 		}
441*4887Schin 	}
442*4887Schin 	else
443*4887Schin 	{
444*4887Schin 		if ((s = *argv) && !format && *s == '+')
445*4887Schin 		{
446*4887Schin 			format = s + 1;
447*4887Schin 			argv++;
448*4887Schin 			s = *argv;
449*4887Schin 		}
450*4887Schin 		if (s || (s = string))
451*4887Schin 		{
452*4887Schin 			if (*argv && string)
453*4887Schin 				error(ERROR_USAGE|4, "%s", optusage(NiL));
454*4887Schin 			now = convert(fmts, s, now);
455*4887Schin 			if (*argv && (s = *++argv))
456*4887Schin 			{
457*4887Schin 				show = 1;
458*4887Schin 				do
459*4887Schin 				{
460*4887Schin 					if (!last)
461*4887Schin 					{
462*4887Schin 						tmxfmt(buf, sizeof(buf), format, now);
463*4887Schin 						sfprintf(sfstdout, "%s\n", buf);
464*4887Schin 					}
465*4887Schin 					now = convert(fmts, s, now);
466*4887Schin 				} while (s = *++argv);
467*4887Schin 			}
468*4887Schin 		}
469*4887Schin 		else
470*4887Schin 			show = 1;
471*4887Schin 		if (format || show)
472*4887Schin 		{
473*4887Schin 			tmxfmt(buf, sizeof(buf), format, now);
474*4887Schin 			sfprintf(sfstdout, "%s\n", buf);
475*4887Schin 		}
476*4887Schin 		else if (settime(cmd, now, increment, network))
477*4887Schin 			error(ERROR_SYSTEM|3, "cannot set system time");
478*4887Schin 	}
479*4887Schin 	while (fmts != &fmt)
480*4887Schin 	{
481*4887Schin 		f = fmts;
482*4887Schin 		fmts = fmts->next;
483*4887Schin 		free(f);
484*4887Schin 	}
485*4887Schin 	tm_info.flags = 0;
486*4887Schin 	if (show && sfsync(sfstdout))
487*4887Schin 		error(ERROR_system(0), "write error");
488*4887Schin 	return error_info.errors != 0;
489*4887Schin }
490