home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / date-0.2-MIHS / src / date.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-17  |  6.8 KB  |  282 lines

  1. /*    $NetBSD: date.c,v 1.11 1995/09/07 06:21:05 jtc Exp $    */
  2.  
  3. /*
  4.  * Copyright (c) 1985, 1987, 1988, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. All advertising materials mentioning features or use of this software
  16.  *    must display the following acknowledgement:
  17.  *    This product includes software developed by the University of
  18.  *    California, Berkeley and its contributors.
  19.  * 4. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  */
  35.  
  36. #ifndef lint
  37. static char copyright[] =
  38. "@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
  39.     The Regents of the University of California.  All rights reserved.\n";
  40. #endif /* not lint */
  41.  
  42. #ifndef lint
  43. #if 0
  44. static char sccsid[] = "@(#)date.c    8.2 (Berkeley) 4/28/95";
  45. #else
  46. static char rcsid[] = "$NetBSD: date.c,v 1.11 1995/09/07 06:21:05 jtc Exp $";
  47. #endif
  48. #endif /* not lint */
  49.  
  50. #include <sys/param.h>
  51. #include <sys/time.h>
  52.  
  53. #include <ctype.h>
  54. #include "err.h"
  55. #include <fcntl.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include <locale.h>
  60. #include <syslog.h>
  61. #include <libc.h>
  62. /* #include <unistd.h> */
  63.  
  64. #include "extern.h"
  65.  
  66. time_t tval;
  67. int retval, nflag;
  68.  
  69. static void setthetime __P((char *));
  70. static void badformat __P((int));
  71. static void usage __P((void));
  72.  
  73. int logwtmp __P((char *, char *, char *));
  74.  
  75. char *__progname;
  76.  
  77. int
  78. main(argc, argv)
  79.     int argc;
  80.     char **argv;
  81. {
  82.     extern int optind;
  83.     extern char *optarg;
  84.     struct timezone tz;
  85.     int ch, rflag;
  86.     char *format, buf[1024];
  87.     char *original_format;
  88.  
  89.     __progname = argv[0];
  90.     
  91.     setlocale(LC_ALL, "");
  92.  
  93.     tz.tz_dsttime = tz.tz_minuteswest = 0;
  94.     rflag = 0;
  95.     while ((ch = getopt(argc, argv, "d:nr:ut:")) != -1)
  96.         switch((char)ch) {
  97.         case 'd':        /* daylight savings time */
  98.             tz.tz_dsttime = atoi(optarg) ? 1 : 0;
  99.             break;
  100.         case 'n':        /* don't set network */
  101.             nflag = 1;
  102.             break;
  103.         case 'r':        /* user specified seconds */
  104.             rflag = 1;
  105.             tval = atol(optarg);
  106.             break;
  107.         case 'u':        /* do everything in GMT */
  108.             (void)setenv("TZ", "GMT0", 1);
  109.             break;
  110.         case 't':        /* minutes west of GMT */
  111.                     /* error check; don't allow "PST" */
  112.             if (isdigit(*optarg)) {
  113.                 tz.tz_minuteswest = atoi(optarg);
  114.                 break;
  115.             }
  116.             /* FALLTHROUGH */
  117.         default:
  118.             usage();
  119.         }
  120.     argc -= optind;
  121.     argv += optind;
  122.  
  123.     /*
  124.      * If -d or -t, set the timezone or daylight savings time; this
  125.      * doesn't belong here, there kernel should not know about either.
  126.      */
  127.     if ((tz.tz_minuteswest || tz.tz_dsttime) &&
  128.         settimeofday(NULL, &tz))
  129.         err(1, "settimeofday");
  130.  
  131.     if (!rflag && time(&tval) == -1)
  132.         err(1, "time");
  133.  
  134. /*
  135.     format = "%a %b %e %H:%M:%S %Z %Y";
  136. */
  137.     original_format = format = "%a %b %d %H:%M:%S %Z %Y";
  138.  
  139.     /* allow the operands in any order */
  140.     if (*argv && **argv == '+') {
  141.         format = *argv + 1;
  142.         ++argv;
  143.     }
  144.  
  145.     if (*argv) {
  146.         setthetime(*argv);
  147.         ++argv;
  148.     }
  149.  
  150.     if (*argv && **argv == '+')
  151.         format = *argv + 1;
  152.  
  153.     (void)strftime(buf, sizeof(buf), format, localtime(&tval));
  154.     
  155.     /* hack to support missing %e option */
  156.     if ((format == original_format) && (buf[8] == '0'))  buf[8] = ' ';
  157.     
  158.     (void)printf("%s\n", buf);
  159.     exit(retval);
  160. }
  161.  
  162. #define    ATOI2(ar)    ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
  163. void
  164. setthetime(p)
  165.     register char *p;
  166. {
  167.     register struct tm *lt;
  168.     struct timeval tv;
  169.     char *dot, *t;
  170.     int tmpNumYearDigit = 0;
  171.     int tmpCentury = 0;
  172.  
  173.     for (t = p, dot = NULL; *t; ++t) {
  174.         if (isdigit(*t))
  175.             continue;
  176.         if (*t == '.' && dot == NULL) {
  177.             dot = t;
  178.             continue;
  179.         }
  180.         badformat(1);
  181.     }
  182.  
  183.     lt = localtime(&tval);
  184.  
  185.     if (dot != NULL) {            /* .ss */
  186.         *dot++ = '\0';
  187.         if (strlen(dot) != 2)
  188.             badformat(2);
  189.         lt->tm_sec = ATOI2(dot);
  190.         if (lt->tm_sec > 61)
  191.             badformat(3);
  192.     } else
  193.         lt->tm_sec = 0;
  194.  
  195.     switch (strlen(p)) {
  196.     case 12:                /* cc */
  197.         tmpNumYearDigit = 4;
  198.         tmpCentury = ATOI2(p);
  199.     case 11:                /* yyy */
  200.         /* 3 digit year: skip the first character and do */
  201.         /* nothing, the next case will automagically add */
  202.         /* 100 years if the next 2 digits are < 69 */
  203.         /* This will keep things right until the year 2069 */
  204.         if (tmpNumYearDigit != 4)
  205.         {
  206.             p += 1;
  207.         }
  208.         /* FALLTHROUGH */
  209.     case 10:                /* yy */
  210.         lt->tm_year = ATOI2(p);
  211.         if (tmpNumYearDigit==4)
  212.         {
  213.             lt->tm_year += (tmpCentury - 19) * 100 ;
  214.         }
  215.         else
  216.         {
  217.         if (lt->tm_year < 69)        /* hack for 2000 ;-} */
  218.             lt->tm_year += 100;
  219.         }
  220.         /* FALLTHROUGH */
  221.     case 8:                    /* mm */
  222.         lt->tm_mon = ATOI2(p);
  223.         if (lt->tm_mon > 12)
  224.             badformat(4);
  225.         --lt->tm_mon;            /* time struct is 0 - 11 */
  226.         /* FALLTHROUGH */
  227.     case 6:                    /* dd */
  228.         lt->tm_mday = ATOI2(p);
  229.         if (lt->tm_mday > 31)
  230.             badformat(5);
  231.         /* FALLTHROUGH */
  232.     case 4:                    /* hh */
  233.         lt->tm_hour = ATOI2(p);
  234.         if (lt->tm_hour > 23)
  235.             badformat(6);
  236.         /* FALLTHROUGH */
  237.     case 2:                    /* mm */
  238.         lt->tm_min = ATOI2(p);
  239.         if (lt->tm_min > 59)
  240.             badformat(7);
  241.         break;
  242.     default:
  243.         badformat(8);
  244.     }
  245.  
  246.     /* convert broken-down time to GMT clock time */
  247.     if ((tval = mktime(lt)) == -1)
  248.         badformat(9);
  249.  
  250.     /* set the time */
  251.     if (nflag || netsettime(tval)) {
  252.         logwtmp("|", "date", "");
  253.         tv.tv_sec = tval;
  254.         tv.tv_usec = 0;
  255.         if (settimeofday(&tv, NULL)) {
  256.             perror("date: settimeofday");
  257.             exit(1);
  258.         }
  259.         logwtmp("{", "date", "");
  260.     }
  261.  
  262.     if ((p = getlogin()) == (char *)NULL)
  263.         p = "???";
  264.     syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
  265. }
  266.  
  267. static void
  268. badformat(pNum)
  269. {
  270.     warnx("illegal time format %d", pNum);
  271.     usage();
  272. }
  273.  
  274. static void
  275. usage()
  276. {
  277.     (void)fprintf(stderr,
  278.         "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n");
  279.     (void)fprintf(stderr, "         [cc[yy[mm[dd[hh]]]]]mm[.ss]]\n");
  280.     exit(1);
  281. }
  282.