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