xref: /onnv-gate/usr/src/lib/libcmd/common/date.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1992-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                                                                      *
204887Schin ***********************************************************************/
214887Schin #pragma prototyped
224887Schin /*
234887Schin  * Glenn Fowler
244887Schin  * AT&T Research
254887Schin  *
264887Schin  * date -- set/display date
274887Schin  */
284887Schin 
294887Schin static const char usage[] =
3010898Sroland.mainz@nrubsig.org "[-?\n@(#)$Id: date (AT&T Research) 2009-03-03 $\n]"
314887Schin USAGE_LICENSE
324887Schin "[+NAME?date - set/list/convert dates]"
334887Schin "[+DESCRIPTION?\bdate\b sets the current date and time (with appropriate"
344887Schin "	privilege), lists the current date or file dates, or converts"
354887Schin "	dates.]"
364887Schin "[+?Most common \adate\a forms are recognized, including those for"
374887Schin "	\bcrontab\b(1), \bls\b(1), \btouch\b(1), and the default"
384887Schin "	output from \bdate\b itself.]"
394887Schin "[+?If the \adate\a operand consists of 4, 6, 8, 10 or 12 digits followed"
404887Schin "	by an optional \b.\b and two digits then it is interpreted as:"
414887Schin "	\aHHMM.SS\a, \addHHMM.SS\a, \ammddHHMM.SS\a, \ammddHHMMyy.SS\a or"
424887Schin "	\ayymmddHHMM.SS\a, or \ammddHHMMccyy.SS\a or \accyymmddHHMM.SS\a."
434887Schin "	Conflicting standards and practice allow a leading or trailing"
444887Schin "	2 or 4 digit year for the 10 and 12 digit forms; the X/Open trailing"
454887Schin "	form is used to disambiguate (\btouch\b(1) uses the leading form.)"
464887Schin "	Avoid the 10 digit form to avoid confusion. The digit fields are:]{"
474887Schin "		[+cc?Century - 1, 19-20.]"
484887Schin "		[+yy?Year in century, 00-99.]"
494887Schin "		[+mm?Month, 01-12.]"
504887Schin "		[+dd?Day of month, 01-31.]"
514887Schin "		[+HH?Hour, 00-23.]"
524887Schin "		[+MM?Minute, 00-59.]"
534887Schin "		[+SS?Seconds, 00-60.]"
544887Schin "}"
554887Schin "[+?If more than one \adate\a operand is specified then:]{"
564887Schin "		[+1.?Each operand sets the reference date for the next"
574887Schin "			operand.]"
584887Schin "		[+2.?The date is listed for each operand.]"
594887Schin "		[+3.?The system date is not set.]"
604887Schin "}"
614887Schin 
624887Schin "[a:access-time|atime?List file argument access times.]"
634887Schin "[c:change-time|ctime?List file argument change times.]"
644887Schin "[d:date?Use \adate\a as the current date and do not set the system"
654887Schin "	clock.]:[date]"
664887Schin "[e:epoch?Output the date in seconds since the epoch."
674887Schin "	Equivalent to \b--format=%s\b.]"
684887Schin "[E:elapsed?Interpret pairs of arguments as start and stop dates, sum the"
694887Schin "	differences between all pairs, and list the result as a"
704887Schin "	\bfmtelapsed\b(3) elapsed time on the standard output. If there are"
714887Schin "	an odd number of arguments then the last time argument is differenced"
724887Schin "	with the current time.]"
734887Schin "[f:format?Output the date according to the \bstrftime\b(3) \aformat\a."
744887Schin "	For backwards compatibility, a first argument of the form"
754887Schin "	\b+\b\aformat\a is equivalent to \b-f\b format."
764887Schin "	\aformat\a is in \bprintf\b(3) style, where %\afield\a names"
774887Schin "	a fixed size field, zero padded if necessary,"
784887Schin "	and \\\ac\a and \\\annn\a sequences are as in C. Invalid"
794887Schin "	%\afield\a specifications and all other characters are copied"
804887Schin "	without change. \afield\a may be preceded by \b%-\b to turn off"
814887Schin "	padding or \b%_\b to pad with space, otherwise numeric fields"
824887Schin "	are padded with \b0\b and string fields are padded with space."
834887Schin "	\afield\a may also be preceded by \bE\b for alternate era"
844887Schin "	representation or \bO\b for alternate digit representation (if"
854887Schin "	supported by the current locale.) Finally, an integral \awidth\a"
864887Schin "	preceding \afield\a truncates the field to \awidth\a characters."
874887Schin "	The fields are:]:[format]{"
884887Schin "		[+%?% character]"
894887Schin "		[+a?abbreviated weekday name]"
904887Schin "		[+A?full weekday name]"
914887Schin "		[+b?abbreviated month name]"
924887Schin "		[+c?\bctime\b(3) style date without the trailing newline]"
934887Schin "		[+C?2-digit century]"
944887Schin "		[+d?day of month number]"
954887Schin "		[+D?date as \amm/dd/yy\a]"
964887Schin "		[+e?blank padded day of month number]"
974887Schin "		[+E?unpadded day of month number]"
984887Schin "		[+f?locale default override date format]"
998462SApril.Chin@Sun.COM "		[+F?%ISO 8601:2000 standard date format; equivalent to Y-%m-%d]"
1004887Schin "		[+g?\bls\b(1) \b-l\b recent date with \ahh:mm\a]"
1014887Schin "		[+G?\bls\b(1) \b-l\b distant date with \ayyyy\a]"
1024887Schin "		[+h?abbreviated month name]"
1034887Schin "		[+H?24-hour clock hour]"
1044887Schin "		[+i?international \bdate\b(1) date with time zone type name]"
1054887Schin "		[+I?12-hour clock hour]"
1064887Schin "		[+j?1-offset Julian date]"
1074887Schin "		[+J?0-offset Julian date]"
1084887Schin "		[+k?\bdate\b(1) style date]"
10910898Sroland.mainz@nrubsig.org "		[+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b; \b%_[EO]]K\b for space separator, %OK adds \b.%N\b, \b%EK\b adds \b%.N%z\b, \b%_EK\b adds \b.%N %z\b]"
1104887Schin "		[+l?\bls\b(1) \b-l\b date; equivalent to \b%Q/%g/%G/\b]"
1118462SApril.Chin@Sun.COM "		[+L?locale default date format]"
1124887Schin "		[+m?month number]"
1134887Schin "		[+M?minutes]"
1144887Schin "		[+n?newline character]"
1154887Schin "		[+N?nanoseconds 000000000-999999999]"
1164887Schin "		[+p?meridian (e.g., \bAM\b or \bPM\b)]"
1174887Schin "		[+q?time zone type name (nation code)]"
1184887Schin "		[+Q?\a<del>recent<del>distant<del>\a: \a<del>\a is a unique"
1194887Schin "			delimter character; \arecent\a format for recent"
1204887Schin "			dates, \adistant\a format otherwise]"
1214887Schin "		[+r?12-hour time as \ahh:mm:ss meridian\a]"
1224887Schin "		[+R?24-hour time as \ahh:mm\a]"
1234887Schin "		[+s?number of seconds since the epoch; \a.prec\a preceding"
1244887Schin "			\bs\b appends \aprec\a nanosecond digits, \b9\b if"
1254887Schin "			\aprec\a is omitted]"
1264887Schin "		[+S?seconds 00-60]"
1274887Schin "		[+t?tab character]"
1284887Schin "		[+T?24-hour time as \ahh:mm:ss\a]"
1294887Schin "		[+u?weekday number 1(Monday)-7]"
1304887Schin "		[+U?week number with Sunday as the first day]"
1314887Schin "		[+V?ISO week number (i18n is \afun\a)]"
1324887Schin "		[+w?weekday number 0(Sunday)-6]"
1334887Schin "		[+W?week number with Monday as the first day]"
1344887Schin "		[+x?locale date style that includes month, day and year]"
1354887Schin "		[+X?locale time style that includes hours and minutes]"
1364887Schin "		[+y?2-digit year (you'll be sorry)]"
1374887Schin "		[+Y?4-digit year]"
1384887Schin "		[+z?time zone \aSHHMM\a west of GMT offset where S is"
1394887Schin "			\b+\b or \b-\b]"
1404887Schin "		[+Z?time zone name]"
1414887Schin "		[+=[=]][-+]]flag?set (default or +) or clear (-) \aflag\a"
1424887Schin "			for the remainder of \aformat\a, or for the remainder"
1434887Schin "			of the process if \b==\b is specified. \aflag\a may be:]{"
1444887Schin "			[+l?enable leap second adjustments]"
1454887Schin "			[+n?convert \b%S\b as \b%S.%N\b]"
1464887Schin "			[+u?UTC time zone]"
1474887Schin "		}"
1484887Schin "		[+#?equivalent to %s]"
1494887Schin "		[+??alternate?use \aalternate\a format if a default format"
1504887Schin "			override has not been specified, e.g., \bls\b(1) uses"
1514887Schin "			\"%?%l\"; export TM_OPTIONS=\"format='\aoverride\a'\""
1524887Schin "			to override the default]"
1534887Schin "}"
1544887Schin "[i:incremental|adjust?Set the system time in incrementatl adjustments to"
1554887Schin "	avoid complete time shift shock. Negative adjustments still maintain"
1564887Schin "	monotonic increasing time. Not available on all systems.]"
1574887Schin "[L:last?List only the last time for multiple \adate\a operands.]"
1584887Schin "[l:leap-seconds?Include leap seconds in time calculations. Leap seconds"
1594887Schin "	after the ast library release date are not accounted for.]"
1604887Schin "[m:modify-time|mtime?List file argument modify times.]"
1614887Schin "[n!:network?Set network time.]"
1624887Schin "[p:parse?Add \aformat\a to the list of \bstrptime\b(3) parse conversion"
1634887Schin "	formats. \aformat\a follows the same conventions as the"
1644887Schin "	\b--format\b option, with the addition of these format"
1654887Schin "	fields:]:[format]{"
1664887Schin "		[+|?If the format failed before this point then restart"
1674887Schin "			the parse with the remaining format.]"
1684887Schin "		[+&?Call the \btmdate\b(3) heuristic parser. This is"
1694887Schin "			is the default when \b--parse\b is omitted.]"
1704887Schin "}"
1714887Schin "[s:show?Show the date without setting the system time.]"
1724887Schin "[u:utc|gmt|zulu?Output dates in \acoordinated universal time\a (UTC).]"
1734887Schin "[U:unelapsed?Interpret each argument as \bfmtelapsed\b(3) elapsed"
1744887Schin "	time and list the \bstrelapsed\b(3) 1/\ascale\a seconds.]#[scale]"
1754887Schin "[z:list-zones?List the known time zone table and exit. The table columns"
1764887Schin "	are: country code, standard zone name, savings time zone name,"
1774887Schin "	minutes west of \bUTC\b, and savings time minutes offset. Blank"
1784887Schin "	or empty entries are listed as \b-\b.]"
1794887Schin 
1804887Schin "\n"
1814887Schin "\n[ +format | date ... | file ... ]\n"
1824887Schin "\n"
1834887Schin 
1844887Schin "[+SEE ALSO?\bcrontab\b(1), \bls\b(1), \btouch\b(1), \bfmtelapsed\b(3),"
1854887Schin "	\bstrftime\b(3), \bstrptime\b(3), \btm\b(3)]"
1864887Schin ;
1874887Schin 
1884887Schin #include <cmd.h>
1894887Schin #include <ls.h>
1904887Schin #include <proc.h>
1914887Schin #include <tmx.h>
1924887Schin #include <times.h>
1934887Schin 
1944887Schin typedef struct Fmt
1954887Schin {
1964887Schin 	struct Fmt*	next;
1974887Schin 	char*		format;
1984887Schin } Fmt_t;
1994887Schin 
2004887Schin #ifndef ENOSYS
2014887Schin #define ENOSYS		EINVAL
2024887Schin #endif
2034887Schin 
2044887Schin /*
2054887Schin  * set the system clock
2064887Schin  * the standards wimped out here
2074887Schin  */
2084887Schin 
2094887Schin static int
settime(void * context,const char * cmd,Time_t now,int adjust,int network)2108462SApril.Chin@Sun.COM settime(void* context, const char* cmd, Time_t now, int adjust, int network)
2114887Schin {
2124887Schin 	char*		s;
2134887Schin 	char**		argv;
2144887Schin 	char*		args[5];
21510898Sroland.mainz@nrubsig.org 	char		buf[1024];
2164887Schin 
2174887Schin 	if (!adjust && !network)
2184887Schin 		return tmxsettime(now);
2194887Schin 	argv = args;
2204887Schin 	s = "/usr/bin/date";
2214887Schin 	if (!streq(cmd, s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
2224887Schin 	{
2234887Schin 		*argv++ = s;
2244887Schin 		if (streq(astconf("UNIVERSE", NiL, NiL), "att"))
2254887Schin 		{
2268462SApril.Chin@Sun.COM 			tmxfmt(buf, sizeof(buf), "%m%d%H" "%M%Y.%S", now);
2274887Schin 			if (adjust)
2284887Schin 				*argv++ = "-a";
2294887Schin 		}
2304887Schin 		else
2314887Schin 		{
2328462SApril.Chin@Sun.COM 			tmxfmt(buf, sizeof(buf), "%Y%m%d%H" "%M.%S", now);
2334887Schin 			if (network)
2344887Schin 				*argv++ = "-n";
2354887Schin 			if (tm_info.flags & TM_UTC)
2364887Schin 				*argv++ = "-u";
2374887Schin 		}
2384887Schin 		*argv++ = buf;
2394887Schin 		*argv = 0;
2408462SApril.Chin@Sun.COM 		if (!sh_run(context, argv - args, args))
2414887Schin 			return 0;
2424887Schin 	}
2434887Schin 	return -1;
2444887Schin }
2454887Schin 
2464887Schin /*
2474887Schin  * convert s to Time_t with error checking
2484887Schin  */
2494887Schin 
2504887Schin static Time_t
convert(register Fmt_t * f,char * s,Time_t now)2514887Schin convert(register Fmt_t* f, char* s, Time_t now)
2524887Schin {
2534887Schin 	char*	t;
2544887Schin 	char*	u;
2554887Schin 
2564887Schin 	do
2574887Schin 	{
2584887Schin 		now = tmxscan(s, &t, f->format, &u, now, 0);
2594887Schin 		if (!*t && (!f->format || !*u))
2604887Schin 			break;
2614887Schin 	} while (f = f->next);
2624887Schin 	if (!f || *t)
2634887Schin 		error(3, "%s: invalid date specification", f ? t : s);
2644887Schin 	return now;
2654887Schin }
2664887Schin 
2674887Schin int
b_date(int argc,register char ** argv,void * context)2684887Schin b_date(int argc, register char** argv, void* context)
2694887Schin {
2704887Schin 	register int	n;
2714887Schin 	register char*	s;
2724887Schin 	register Fmt_t*	f;
2734887Schin 	char*		t;
2744887Schin 	unsigned long	u;
2754887Schin 	Time_t		now;
2764887Schin 	Time_t		ts;
2774887Schin 	Time_t		te;
2784887Schin 	Time_t		e;
27910898Sroland.mainz@nrubsig.org 	char		buf[1024];
2804887Schin 	Fmt_t*		fmts;
2814887Schin 	Fmt_t		fmt;
2824887Schin 	struct stat	st;
2834887Schin 
2844887Schin 	char*		cmd = argv[0];	/* original command path	*/
2854887Schin 	char*		format = 0;	/* tmxfmt() format		*/
2864887Schin 	char*		string = 0;	/* date string			*/
2874887Schin 	int		elapsed = 0;	/* args are start/stop pairs	*/
2884887Schin 	int		filetime = 0;	/* use this st_ time field	*/
2894887Schin 	int		increment = 0;	/* incrementally adjust time	*/
2904887Schin 	int		last = 0;	/* display the last time arg	*/
2914887Schin 	Tm_zone_t*	listzones = 0;	/* known time zone table	*/
2924887Schin 	int		network = 0;	/* don't set network time	*/
2934887Schin 	int		show = 0;	/* show date and don't set	*/
2944887Schin 	int		unelapsed = 0;	/* fmtelapsed() => strelapsed	*/
2954887Schin 
2964887Schin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
2974887Schin 	tm_info.flags = TM_DATESTYLE;
2984887Schin 	fmts = &fmt;
2994887Schin 	fmt.format = "";
3004887Schin 	fmt.next = 0;
3014887Schin 	for (;;)
3024887Schin 	{
3034887Schin 		switch (optget(argv, usage))
3044887Schin 		{
3054887Schin 		case 'a':
3064887Schin 		case 'c':
3074887Schin 		case 'm':
3084887Schin 			filetime = opt_info.option[1];
3094887Schin 			continue;
3104887Schin 		case 'd':
3114887Schin 			string = opt_info.arg;
3124887Schin 			show = 1;
3134887Schin 			continue;
3144887Schin 		case 'e':
3154887Schin 			format = "%#";
3164887Schin 			continue;
3174887Schin 		case 'E':
3184887Schin 			elapsed = 1;
3194887Schin 			continue;
3204887Schin 		case 'f':
3214887Schin 			format = opt_info.arg;
3224887Schin 			continue;
3234887Schin 		case 'i':
3244887Schin 			increment = 1;
3254887Schin 			continue;
3264887Schin 		case 'l':
3274887Schin 			tm_info.flags |= TM_LEAP;
3284887Schin 			continue;
3294887Schin 		case 'L':
3304887Schin 			last = 1;
3314887Schin 			continue;
3324887Schin 		case 'n':
3334887Schin 			network = 1;
3344887Schin 			continue;
3354887Schin 		case 'p':
3364887Schin 			if (!(f = newof(0, Fmt_t, 1, 0)))
3374887Schin 				error(ERROR_SYSTEM|3, "out of space [format]");
3384887Schin 			f->next = fmts;
3394887Schin 			f->format = opt_info.arg;
3404887Schin 			fmts = f;
3414887Schin 			continue;
3424887Schin 		case 's':
3434887Schin 			show = 1;
3444887Schin 			continue;
3454887Schin 		case 'u':
3464887Schin 			tm_info.flags |= TM_UTC;
3474887Schin 			continue;
3484887Schin 		case 'U':
3494887Schin 			unelapsed = (int)opt_info.num;
3504887Schin 			continue;
3514887Schin 		case 'z':
3524887Schin 			listzones = tm_data.zone;
3534887Schin 			continue;
3544887Schin 		case '?':
3554887Schin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
3564887Schin 			continue;
3574887Schin 		case ':':
3584887Schin 			error(2, "%s", opt_info.arg);
3594887Schin 			continue;
3604887Schin 		}
3614887Schin 		break;
3624887Schin 	}
3634887Schin 	argv += opt_info.index;
3644887Schin 	if (error_info.errors)
3654887Schin 		error(ERROR_USAGE|4, "%s", optusage(NiL));
3664887Schin 	now = tmxgettime();
3674887Schin 	if (listzones)
3684887Schin 	{
3694887Schin 		s = "-";
3704887Schin 		while (listzones->standard)
3714887Schin 		{
3724887Schin 			if (listzones->type)
3734887Schin 				s = listzones->type;
3744887Schin 			sfprintf(sfstdout, "%3s %4s %4s %4d %4d\n", s, *listzones->standard ? listzones->standard : "-", listzones->daylight ? listzones->daylight : "-", listzones->west, listzones->dst);
3754887Schin 			listzones++;
3764887Schin 			show = 1;
3774887Schin 		}
3784887Schin 	}
3794887Schin 	else if (elapsed)
3804887Schin 	{
3814887Schin 		e = 0;
3824887Schin 		while (s = *argv++)
3834887Schin 		{
3844887Schin 			if (!(t = *argv++))
3854887Schin 			{
3864887Schin 				argv--;
3874887Schin 				t = "now";
3884887Schin 			}
3894887Schin 			ts = convert(fmts, s, now);
3904887Schin 			te = convert(fmts, t, now);
3914887Schin 			if (te > ts)
3924887Schin 				e += te - ts;
3934887Schin 			else
3944887Schin 				e += ts - te;
3954887Schin 		}
3964887Schin 		sfputr(sfstdout, fmtelapsed((unsigned long)tmxsec(e), 1), '\n');
3974887Schin 		show = 1;
3984887Schin 	}
3994887Schin 	else if (unelapsed)
4004887Schin 	{
4014887Schin 		while (s = *argv++)
4024887Schin 		{
4034887Schin 			u = strelapsed(s, &t, unelapsed);
4044887Schin 			if (*t)
4054887Schin 				error(3, "%s: invalid elapsed time", s);
4064887Schin 			sfprintf(sfstdout, "%lu\n", u);
4074887Schin 		}
4084887Schin 		show = 1;
4094887Schin 	}
4104887Schin 	else if (filetime)
4114887Schin 	{
4124887Schin 		if (!*argv)
4134887Schin 			error(ERROR_USAGE|4, "%s", optusage(NiL));
4144887Schin 		n = argv[1] != 0;
4154887Schin 		while (s = *argv++)
4164887Schin 		{
4174887Schin 			if (stat(s, &st))
4184887Schin 				error(2, "%s: not found", s);
4194887Schin 			else
4204887Schin 			{
4214887Schin 				switch (filetime)
4224887Schin 				{
4234887Schin 				case 'a':
4244887Schin 					now = tmxgetatime(&st);
4254887Schin 					break;
4264887Schin 				case 'c':
4274887Schin 					now = tmxgetctime(&st);
4284887Schin 					break;
4294887Schin 				default:
4304887Schin 					now = tmxgetmtime(&st);
4314887Schin 					break;
4324887Schin 				}
4334887Schin 				tmxfmt(buf, sizeof(buf), format, now);
4344887Schin 				if (n)
4354887Schin 					sfprintf(sfstdout, "%s: %s\n", s, buf);
4364887Schin 				else
4374887Schin 					sfprintf(sfstdout, "%s\n", buf);
4384887Schin 				show = 1;
4394887Schin 			}
4404887Schin 		}
4414887Schin 	}
4424887Schin 	else
4434887Schin 	{
4444887Schin 		if ((s = *argv) && !format && *s == '+')
4454887Schin 		{
4464887Schin 			format = s + 1;
4474887Schin 			argv++;
4484887Schin 			s = *argv;
4494887Schin 		}
4504887Schin 		if (s || (s = string))
4514887Schin 		{
4524887Schin 			if (*argv && string)
4534887Schin 				error(ERROR_USAGE|4, "%s", optusage(NiL));
4544887Schin 			now = convert(fmts, s, now);
4554887Schin 			if (*argv && (s = *++argv))
4564887Schin 			{
4574887Schin 				show = 1;
4584887Schin 				do
4594887Schin 				{
4604887Schin 					if (!last)
4614887Schin 					{
4624887Schin 						tmxfmt(buf, sizeof(buf), format, now);
4634887Schin 						sfprintf(sfstdout, "%s\n", buf);
4644887Schin 					}
4654887Schin 					now = convert(fmts, s, now);
4664887Schin 				} while (s = *++argv);
4674887Schin 			}
4684887Schin 		}
4694887Schin 		else
4704887Schin 			show = 1;
4714887Schin 		if (format || show)
4724887Schin 		{
4734887Schin 			tmxfmt(buf, sizeof(buf), format, now);
4744887Schin 			sfprintf(sfstdout, "%s\n", buf);
4754887Schin 		}
4768462SApril.Chin@Sun.COM 		else if (settime(context, cmd, now, increment, network))
4774887Schin 			error(ERROR_SYSTEM|3, "cannot set system time");
4784887Schin 	}
4794887Schin 	while (fmts != &fmt)
4804887Schin 	{
4814887Schin 		f = fmts;
4824887Schin 		fmts = fmts->next;
4834887Schin 		free(f);
4844887Schin 	}
4854887Schin 	tm_info.flags = 0;
4864887Schin 	if (show && sfsync(sfstdout))
4874887Schin 		error(ERROR_system(0), "write error");
4884887Schin 	return error_info.errors != 0;
4894887Schin }
490