libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2009, 2012, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as 00007 * published by the Free Software Foundation; either version 3 of the 00008 * License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/assert.h> 00020 #include <libexplain/ac/ctype.h> 00021 #include <libexplain/ac/stdio.h> 00022 #include <libexplain/ac/stdlib.h> 00023 #include <libexplain/ac/string.h> 00024 00025 #include <libexplain/buffer/time_t.h> 00026 #include <libexplain/output.h> 00027 #include <libexplain/sizeof.h> 00028 00029 00030 #define YEAR_BIT (1 << 0) 00031 #define MONTH_BIT (1 << 1) 00032 #define MDAY_BIT (1 << 2) 00033 #define HOUR_BIT (1 << 3) 00034 #define MIN_BIT (1 << 4) 00035 #define SEC_BIT (1 << 5) 00036 00037 00038 static int 00039 all_digits(const char *text) 00040 { 00041 if (!*text) 00042 return 0; 00043 for (;;) 00044 { 00045 unsigned char c = *text++; 00046 if (!c) 00047 return 1; 00048 if (!isdigit(c)) 00049 return 0; 00050 } 00051 } 00052 00053 00054 static unsigned 00055 pull(const char *text, size_t len) 00056 { 00057 unsigned n; 00058 00059 n = 0; 00060 while (len > 0) 00061 { 00062 unsigned char c = *text++; 00063 assert(isdigit(c)); 00064 n = n * 10 + c - '0'; 00065 --len; 00066 } 00067 return n; 00068 } 00069 00070 00071 static int 00072 correct_year(const struct tm *build, int year) 00073 { 00074 int century; 00075 00076 if (year >= 100) 00077 return (year - 1900); 00078 century = 0; 00079 for (;;) 00080 { 00081 if (abs(year + century - build->tm_year) <= 50) 00082 return (year + century); 00083 century += 100; 00084 } 00085 } 00086 00087 00088 static time_t 00089 explain_parse_time_t(const char *text) 00090 { 00091 static struct tm tzero; 00092 struct tm build; 00093 unsigned numbers[6]; 00094 unsigned char masks[SIZEOF(numbers)]; 00095 time_t now; 00096 unsigned nnum; 00097 00098 build = tzero; 00099 if (time(&now) != (time_t)(-1)) 00100 { 00101 struct tm *tmp; 00102 00103 tmp = localtime(&now); 00104 if (tmp) 00105 build = *tmp; 00106 } 00107 00108 if (all_digits(text)) 00109 { 00110 size_t len; 00111 00112 len = strlen(text); 00113 if (len == 12) 00114 { 00115 build.tm_year = correct_year(&build, pull(text, 2)); 00116 build.tm_mon = pull(text + 2, 2) - 1; 00117 if (build.tm_mon < 0 || build.tm_mon >= 12) 00118 return -1; 00119 build.tm_mday = pull(text + 4, 2); 00120 if (build.tm_mday < 1 || build.tm_mday > 31) 00121 return -1; 00122 build.tm_hour = pull(text + 6, 2); 00123 if (build.tm_hour >= 24) 00124 return -1; 00125 build.tm_min = pull(text + 8, 2); 00126 if (build.tm_min >= 60) 00127 return -1; 00128 build.tm_sec = pull(text + 10, 2); 00129 if (build.tm_sec >= 62) 00130 return -1; 00131 return mktime(&build); 00132 } 00133 00134 if (len == 14) 00135 { 00136 build.tm_year = pull(text, 4) - 1900; 00137 if (build.tm_year < 0 || build.tm_year > 200) 00138 return -1; 00139 build.tm_mon = pull(text + 4, 2) - 1; 00140 if (build.tm_mon < 0 || build.tm_mon >= 12) 00141 return -1; 00142 build.tm_mday = pull(text + 6, 2); 00143 if (build.tm_mday < 1 || build.tm_mday > 31) 00144 return -1; 00145 build.tm_hour = pull(text + 8, 2); 00146 if (build.tm_hour >= 24) 00147 return -1; 00148 build.tm_min = pull(text + 10, 2); 00149 if (build.tm_min >= 60) 00150 return -1; 00151 build.tm_sec = pull(text + 12, 2); 00152 if (build.tm_sec >= 62) 00153 return -1; 00154 return mktime(&build); 00155 } 00156 00157 return strtol(text, 0, 10); 00158 } 00159 00160 /* 00161 * Break the string into a bunch of numbers, 00162 * looking for patterns. 00163 */ 00164 nnum = 0; 00165 while (nnum < SIZEOF(numbers)) 00166 { 00167 unsigned char c = *text++; 00168 if (!c) 00169 break; 00170 switch (c) 00171 { 00172 case '0': case '1': case '2': case '3': case '4': 00173 case '5': case '6': case '7': case '8': case '9': 00174 { 00175 unsigned n; 00176 unsigned char mask; 00177 unsigned ndig; 00178 00179 n = 0; 00180 ndig = 0; 00181 for (;;) 00182 { 00183 n = n * 10 + c - '0'; 00184 ++ndig; 00185 c = *text++; 00186 switch (c) 00187 { 00188 case '0': case '1': case '2': case '3': case '4': 00189 case '5': case '6': case '7': case '8': case '9': 00190 continue; 00191 00192 default: 00193 --text; 00194 break; 00195 } 00196 break; 00197 } 00198 00199 /* 00200 * If the number is stupidly large just bail, 00201 * because it can't be any part of a valid date. 00202 */ 00203 if (n >= 2100) 00204 return -1; 00205 00206 mask = 0; 00207 if (n < 100 && ndig == 2) 00208 mask |= YEAR_BIT; 00209 if (n >= 1900 && n < 2100) 00210 mask |= YEAR_BIT; 00211 if (n >= 1 && n <= 12) 00212 mask |= MONTH_BIT; 00213 if (n >= 1 && n <= 31) 00214 mask |= MDAY_BIT; 00215 if (ndig == 2 && n < 24) 00216 mask |= HOUR_BIT; 00217 if (ndig == 2 && n < 60) 00218 mask |= MIN_BIT; 00219 if (ndig == 2 && n <= 61) 00220 mask |= SEC_BIT; 00221 00222 if (mask) 00223 { 00224 numbers[nnum] = n; 00225 masks[nnum] = mask; 00226 ++nnum; 00227 } 00228 } 00229 break; 00230 00231 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': 00232 case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': 00233 case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': 00234 case 'v': case 'w': case 'x': case 'y': case 'z': 00235 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': 00236 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': 00237 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': 00238 case 'V': case 'W': case 'X': case 'Y': case 'Z': 00239 { 00240 char name[30]; 00241 char *cp; 00242 struct tm probe; 00243 int m; 00244 00245 cp = name; 00246 for (;;) 00247 { 00248 if (cp < ENDOF(name) - 1) 00249 *cp++ = c; 00250 c = *text++; 00251 switch (c) 00252 { 00253 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 00254 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': 00255 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': 00256 case 's': case 't': case 'u': case 'v': case 'w': case 'x': 00257 case 'y': case 'z': 00258 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 00259 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': 00260 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': 00261 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': 00262 case 'Y': case 'Z': 00263 continue; 00264 00265 default: 00266 --text; 00267 break; 00268 } 00269 break; 00270 } 00271 *cp = '\0'; 00272 00273 /* 00274 * Now look at possibilities for the month name. If 00275 * name doesn't match anything, throw it away (it is 00276 * probably a weekday name or a timezone name). 00277 */ 00278 probe = tzero; 00279 probe.tm_year = 80; 00280 for (m = 1; m <= 12; ++m) 00281 { 00282 char candidate[sizeof(name)]; 00283 00284 probe.tm_mon = m - 1; 00285 strftime(candidate, sizeof(candidate), "%b", &probe); 00286 if (strcasecmp(name, candidate) == 0) 00287 { 00288 numbers[nnum] = m; 00289 masks[nnum] = MONTH_BIT; 00290 ++nnum; 00291 break; 00292 } 00293 strftime(candidate, sizeof(candidate), "%B", &probe); 00294 if (strcasecmp(name, candidate) == 0) 00295 { 00296 numbers[nnum] = m; 00297 masks[nnum] = MONTH_BIT; 00298 ++nnum; 00299 break; 00300 } 00301 } 00302 } 00303 break; 00304 00305 default: 00306 /* throw away all white space and punctuation */ 00307 break; 00308 } 00309 } 00310 00311 #if 0 00312 { 00313 unsigned n; 00314 00315 /* 00316 * This debug is too useful to just throw away. 00317 */ 00318 for (n = 0; n < nnum; ++n) 00319 { 00320 char m[10]; 00321 char *mp = m; 00322 int mask = masks[n]; 00323 if (mask & YEAR_BIT) *mp++ = 'Y'; 00324 if (mask & MONTH_BIT) *mp++ = 'm'; 00325 if (mask & MDAY_BIT) *mp++ = 'd'; 00326 if (mask & HOUR_BIT) *mp++ = 'H'; 00327 if (mask & MIN_BIT) *mp++ = 'M'; 00328 if (mask & SEC_BIT) *mp++ = 'S'; 00329 *mp = '\0'; 00330 fprintf 00331 ( 00332 stderr, 00333 "%s: %d: %4d %s\n", 00334 __FILE__, 00335 __LINE__, 00336 numbers[n], 00337 m 00338 ); 00339 } 00340 } 00341 #endif 00342 00343 if (nnum == 6) 00344 { 00345 /* %Y%m%d%H%M%S */ 00346 if 00347 ( 00348 (masks[0] & YEAR_BIT) 00349 && 00350 (masks[1] & MONTH_BIT) 00351 && 00352 (masks[2] & MDAY_BIT) 00353 && 00354 (masks[3] & HOUR_BIT) 00355 && 00356 (masks[4] & MIN_BIT) 00357 && 00358 (masks[5] & SEC_BIT) 00359 ) 00360 { 00361 build.tm_year = correct_year(&build, numbers[0]); 00362 build.tm_mon = numbers[1] - 1; 00363 build.tm_mday = numbers[2]; 00364 build.tm_hour = numbers[3]; 00365 build.tm_min = numbers[4]; 00366 build.tm_sec = numbers[5]; 00367 return mktime(&build); 00368 } 00369 00370 /* %m%d%Y%H%M%S */ 00371 if 00372 ( 00373 ((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00374 && 00375 /* avoid ambiguity */ 00376 !((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00377 && 00378 (masks[2] & YEAR_BIT) 00379 && 00380 (masks[3] & HOUR_BIT) 00381 && 00382 (masks[4] & MIN_BIT) 00383 && 00384 (masks[5] & SEC_BIT) 00385 ) 00386 { 00387 build.tm_mon = numbers[0] - 1; 00388 build.tm_mday = numbers[1]; 00389 build.tm_year = correct_year(&build, numbers[2]); 00390 build.tm_hour = numbers[3]; 00391 build.tm_min = numbers[4]; 00392 build.tm_sec = numbers[5]; 00393 return mktime(&build); 00394 } 00395 00396 /* %d%m%Y%H%M%S */ 00397 if 00398 ( 00399 ((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00400 && 00401 /* avoid ambiguity */ 00402 !((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00403 && 00404 (masks[2] & YEAR_BIT) 00405 && 00406 (masks[3] & HOUR_BIT) 00407 && 00408 (masks[4] & MIN_BIT) 00409 && 00410 (masks[5] & SEC_BIT) 00411 ) 00412 { 00413 build.tm_mday = numbers[0]; 00414 build.tm_mon = numbers[1] - 1; 00415 build.tm_year = correct_year(&build, numbers[2]); 00416 build.tm_hour = numbers[3]; 00417 build.tm_min = numbers[4]; 00418 build.tm_sec = numbers[5]; 00419 return mktime(&build); 00420 } 00421 00422 /* %d%m%H%M%S%Y */ 00423 if 00424 ( 00425 ((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00426 && 00427 /* avoid ambiguity */ 00428 !((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00429 && 00430 (masks[2] & HOUR_BIT) 00431 && 00432 (masks[3] & MIN_BIT) 00433 && 00434 (masks[4] & SEC_BIT) 00435 && 00436 (masks[5] & YEAR_BIT) 00437 ) 00438 { 00439 build.tm_mday = numbers[0]; 00440 build.tm_mon = numbers[1] - 1; 00441 build.tm_hour = numbers[2]; 00442 build.tm_min = numbers[3]; 00443 build.tm_sec = numbers[4]; 00444 build.tm_year = correct_year(&build, numbers[5]); 00445 return mktime(&build); 00446 } 00447 00448 /* %m%d%H%M%S%Y */ 00449 if 00450 ( 00451 ((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00452 && 00453 /* avoid ambiguity */ 00454 !((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00455 && 00456 (masks[2] & HOUR_BIT) 00457 && 00458 (masks[3] & MIN_BIT) 00459 && 00460 (masks[4] & SEC_BIT) 00461 && 00462 (masks[5] & YEAR_BIT) 00463 ) 00464 { 00465 build.tm_mon = numbers[0] - 1; 00466 build.tm_mday = numbers[1]; 00467 build.tm_hour = numbers[2]; 00468 build.tm_min = numbers[3]; 00469 build.tm_sec = numbers[4]; 00470 build.tm_year = correct_year(&build, numbers[5]); 00471 return mktime(&build); 00472 } 00473 00474 /* dunno */ 00475 return -1; 00476 } 00477 if (nnum == 5) 00478 { 00479 /* %Y%m%d%H%M */ 00480 if 00481 ( 00482 (masks[0] & YEAR_BIT) 00483 && 00484 (masks[1] & MONTH_BIT) 00485 && 00486 (masks[2] & MDAY_BIT) 00487 && 00488 (masks[3] & HOUR_BIT) 00489 && 00490 (masks[4] & MIN_BIT) 00491 ) 00492 { 00493 build.tm_year = correct_year(&build, numbers[0]); 00494 build.tm_mon = numbers[1] - 1; 00495 build.tm_mday = numbers[2]; 00496 build.tm_hour = numbers[3]; 00497 build.tm_min = numbers[4]; 00498 build.tm_sec = 0; 00499 return mktime(&build); 00500 } 00501 00502 /* %m%d%Y%H%M */ 00503 if 00504 ( 00505 ((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00506 && 00507 /* avoid ambiguity */ 00508 !((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00509 && 00510 (masks[2] & YEAR_BIT) 00511 && 00512 (masks[3] & HOUR_BIT) 00513 && 00514 (masks[4] & MIN_BIT) 00515 ) 00516 { 00517 build.tm_mon = numbers[0] - 1; 00518 build.tm_mday = numbers[1]; 00519 build.tm_year = correct_year(&build, numbers[2]); 00520 build.tm_hour = numbers[3]; 00521 build.tm_min = numbers[4]; 00522 build.tm_sec = 0; 00523 return mktime(&build); 00524 } 00525 00526 /* %d%m%Y%H%M */ 00527 if 00528 ( 00529 ((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00530 && 00531 /* avoid ambiguity */ 00532 !((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00533 && 00534 (masks[2] & YEAR_BIT) 00535 && 00536 (masks[3] & HOUR_BIT) 00537 && 00538 (masks[4] & MIN_BIT) 00539 ) 00540 { 00541 build.tm_mday = numbers[0]; 00542 build.tm_mon = numbers[1] - 1; 00543 build.tm_year = correct_year(&build, numbers[2]); 00544 build.tm_hour = numbers[3]; 00545 build.tm_min = numbers[4]; 00546 build.tm_sec = 0; 00547 return mktime(&build); 00548 } 00549 00550 /* %d%m%H%M%Y */ 00551 if 00552 ( 00553 ((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00554 && 00555 /* avoid ambiguity */ 00556 !((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00557 && 00558 (masks[2] & HOUR_BIT) 00559 && 00560 (masks[3] & MIN_BIT) 00561 && 00562 (masks[4] & YEAR_BIT) 00563 ) 00564 { 00565 build.tm_mday = numbers[0]; 00566 build.tm_mon = numbers[1] - 1; 00567 build.tm_hour = numbers[2]; 00568 build.tm_min = numbers[3]; 00569 build.tm_sec = 0; 00570 build.tm_year = correct_year(&build, numbers[4]); 00571 return mktime(&build); 00572 } 00573 00574 /* %m%d%H%M%Y */ 00575 if 00576 ( 00577 ((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00578 && 00579 /* avoid ambiguity */ 00580 !((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00581 && 00582 (masks[2] & HOUR_BIT) 00583 && 00584 (masks[3] & MIN_BIT) 00585 && 00586 (masks[4] & YEAR_BIT) 00587 ) 00588 { 00589 build.tm_mon = numbers[0] - 1; 00590 build.tm_mday = numbers[1]; 00591 build.tm_hour = numbers[2]; 00592 build.tm_min = numbers[3]; 00593 build.tm_sec = 0; 00594 build.tm_year = correct_year(&build, numbers[4]); 00595 return mktime(&build); 00596 } 00597 00598 /* dunno */ 00599 return -1; 00600 } 00601 if (nnum == 3) 00602 { 00603 /* %Y%m%d */ 00604 if 00605 ( 00606 (masks[0] & YEAR_BIT) 00607 && 00608 (masks[1] & MONTH_BIT) 00609 && 00610 (masks[2] & MDAY_BIT) 00611 ) 00612 { 00613 build.tm_year = correct_year(&build, numbers[0]); 00614 build.tm_mon = numbers[1] - 1; 00615 build.tm_mday = numbers[2]; 00616 return mktime(&build); 00617 } 00618 00619 /* %d%m%Y */ 00620 if 00621 ( 00622 ((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00623 && 00624 /* avoid ambiguity */ 00625 !((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00626 && 00627 (masks[2] & YEAR_BIT) 00628 ) 00629 { 00630 build.tm_mday = numbers[0]; 00631 build.tm_mon = numbers[1] - 1; 00632 build.tm_year = correct_year(&build, numbers[2]); 00633 return mktime(&build); 00634 } 00635 00636 /* %m%d%Y */ 00637 if 00638 ( 00639 ((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00640 && 00641 /* avoid ambiguity */ 00642 !((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00643 && 00644 (masks[2] & YEAR_BIT) 00645 ) 00646 { 00647 build.tm_mday = numbers[0]; 00648 build.tm_mon = numbers[1] - 1; 00649 build.tm_year = correct_year(&build, numbers[2]); 00650 return mktime(&build); 00651 } 00652 00653 /* %H%M%S */ 00654 if 00655 ( 00656 (masks[0] & HOUR_BIT) 00657 && 00658 (masks[1] & MIN_BIT) 00659 && 00660 (masks[2] & SEC_BIT) 00661 ) 00662 { 00663 build.tm_hour = numbers[0]; 00664 build.tm_min = numbers[1]; 00665 build.tm_sec = numbers[2]; 00666 return mktime(&build); 00667 } 00668 00669 /* dunno */ 00670 return -1; 00671 } 00672 00673 if (nnum == 2) 00674 { 00675 /* %H%M */ 00676 if ((masks[0] & HOUR_BIT) && (masks[1] & MIN_BIT)) 00677 { 00678 build.tm_hour = numbers[0]; 00679 build.tm_min = numbers[1]; 00680 build.tm_sec = 0; 00681 return mktime(&build); 00682 } 00683 00684 /* %m%d */ 00685 if 00686 ( 00687 ((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00688 && 00689 /* avoid ambiguity */ 00690 !((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00691 ) 00692 { 00693 build.tm_mon = numbers[0] - 1; 00694 build.tm_mday = numbers[1]; 00695 return mktime(&build); 00696 } 00697 00698 /* %d%m */ 00699 if 00700 ( 00701 ((masks[0] & MDAY_BIT) && (masks[1] & MONTH_BIT)) 00702 && 00703 /* avoid ambiguity */ 00704 !((masks[0] & MONTH_BIT) && (masks[1] & MDAY_BIT)) 00705 ) 00706 { 00707 build.tm_mday = numbers[0]; 00708 build.tm_mon = numbers[1] - 1; 00709 return mktime(&build); 00710 } 00711 00712 /* dunno */ 00713 return -1; 00714 } 00715 00716 /* dunno */ 00717 return -1; 00718 } 00719 00720 00721 static time_t 00722 explain_parse_time_t_on_error(const char *text, const char *caption) 00723 { 00724 time_t result; 00725 00726 result = explain_parse_time_t(text); 00727 if (result == (time_t)(-1)) 00728 { 00729 char qtext[900]; 00730 explain_string_buffer_t qtext_sb; 00731 char message[1000]; 00732 explain_string_buffer_t message_sb; 00733 00734 explain_string_buffer_init(&qtext_sb, qtext, sizeof(qtext)); 00735 explain_string_buffer_puts_quoted(&qtext_sb, text); 00736 explain_string_buffer_init(&message_sb, message, sizeof(message)); 00737 00738 /* FIXME: i18n */ 00739 if (caption && *caption) 00740 { 00741 explain_string_buffer_printf 00742 ( 00743 &message_sb, 00744 "%s: can't parse %s into a date and time", 00745 caption, 00746 qtext 00747 ); 00748 } 00749 else 00750 { 00751 explain_string_buffer_printf 00752 ( 00753 &message_sb, 00754 "unable to parse %s into a date and time", 00755 qtext 00756 ); 00757 } 00758 00759 explain_output_error("%s", message); 00760 } 00761 return result; 00762 } 00763 00764 00765 time_t 00766 explain_parse_time_t_or_die(const char *text, const char *caption) 00767 { 00768 time_t result; 00769 00770 result = explain_parse_time_t_on_error(text, caption); 00771 if (result == (time_t)(-1)) 00772 { 00773 explain_output_exit_failure(); 00774 } 00775 return result; 00776 } 00777 00778 00779 /* vim: set ts=8 sw=4 et : */