home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / CPM3 / DATEP2.LBR / DATE+.CZ / DATE+.C
Text File  |  2000-06-30  |  19KB  |  748 lines

  1. /*=============================================================================
  2.  
  3.                 D A T E
  4.                 -------
  5.               John Hastwell-Batten
  6.              Jonathon Richard Saxton
  7.                   January 1987
  8.  
  9.     A program which (approximately) emulates DATE.COM as distributed
  10.     with CP/M 3 by Digital Research.
  11.  
  12.     Command formats:
  13.     ---------------
  14.  
  15.     date
  16.         displays current date and time.
  17.  
  18.     date set
  19.         prompts for date and time and adjusts the system clock
  20.         accordingly.
  21.  
  22.     date cont
  23.         loops, displaying date and time, until a key is pressed.
  24.  
  25.     date read
  26.         reads hardware clock and sets system date and time.
  27.  
  28.     date dd/mm/yy hh:mm:ss     -or-    date mm/dd/yy hh:mm:ss
  29.         sets the system clock to the specified value.
  30.  
  31.     Only the first letter of the argument is significant so "date s"
  32.     is equivalent to "date set".
  33.  
  34.     The format in which this program will accept dates and times is
  35.     much less strict than that allowed by DRI's DATE program:--
  36.  
  37.     1. DRI's DATE wants date input in the format MM/DD/YY and no
  38.        other.  05/07/86 is acceptable, 5/7/86 is not.  This program
  39.        will accept either of the above and also 5-7-86, 5 7 86 or
  40.        just about anything else.  It does not care what you use as
  41.        a separator between the fields and does not insist that you
  42.        pad the numbers with leading zeros.  It will also accept
  43.        1986 as a valid year.
  44.  
  45.     2. Depending on a compile-time option, this program will accept
  46.        numeric dates in the month/day/year format used in the USA
  47.        or in the more usual day/month/year format used throughout
  48.        the rest of the world.  It will also accept dates in universal
  49.        alphanumeric format - e.g. 7 dec 86 (again, the program is not
  50.        fussy about what delimiters are used).
  51.  
  52.     3. DRI's DATE wants time input in strict HH:MM:SS format.  This
  53.        program removes the unnecessary stringencies for time input
  54.        as for date input.
  55.  
  56. ===============================================================================
  57.  
  58. Modification history:
  59.  
  60. ?? Jan 87    Jon Saxton
  61.     Original release.
  62.  
  63. 02 Mar 87    Jon Saxton
  64.     Bug fix - A spurious line of code in setClock() was causing a
  65.     one-day error when year mod 4 was 0 or 3.
  66.  
  67. =============================================================================*/
  68.  
  69. #include <stdio.h>
  70. #include <signal.h>
  71. #include <ctype.h>
  72.  
  73. /* ONE or NEITHER of the following should be defined */
  74. #undef    DS1216E
  75. #undef    DS1216
  76.  
  77. #ifdef    DS1216E
  78. #define SWaddr    0x6100       /* I had one of each installed while writing */
  79. #endif               /* this program and they were in different   */
  80. #ifdef    DS1216           /* sockets.  */
  81. #define SWaddr    0x2100
  82. #endif
  83. #define TPAbank 1
  84. #define SWbank  -4
  85. #define A2    4
  86.  
  87. unsigned char buf[8];
  88. unsigned char key[8] = {0xC5,0x3A,0xA3,0x5C,0xC5,0x3A,0xA3,0x5C};
  89. unsigned char b64[64];
  90. unsigned char b1[1];
  91.  
  92. /* BDOS functions */
  93. #define    GET_VSN        12
  94. #define GET_TIME    105
  95. #define SET_SCB        49
  96. #define DATE        0x58    /* Offset of date/time within SCB */
  97. #define WORD        0xFE    /* Signal to set a word value in SCB */
  98. #define BYTE        0xFF    /* Signal to set a byte value in SCB */
  99. /* BIOS functions */
  100. #define TIME        26
  101.  
  102. struct
  103.    {
  104.       unsigned short int    days;
  105.       unsigned char        hour, minute, second;
  106.    }
  107. time_pb;
  108.  
  109. struct
  110.    {
  111.       unsigned char        offset;
  112.       unsigned char        worb;
  113.       unsigned short int    value;
  114.    }
  115. scb_pb;
  116.  
  117. struct
  118.    {
  119.       unsigned char        year,
  120.                 month,
  121.                 day,
  122.                 hour,
  123.                 minute,
  124.                 second;
  125.    }
  126. time;
  127.  
  128. #ifndef SWaddr
  129. struct
  130.    {
  131.       unsigned char        func;
  132.       unsigned char        aVal;
  133.       unsigned short int    bcVal,
  134.                 deVal,
  135.                 hlVal;
  136.    }
  137. bios_pb;
  138. #endif
  139.  
  140. unsigned char sentinel[] = {'U','S','A','-','>'};
  141. unsigned char usa = 0;    /* Use wierd MM/DD/YY format if non-0 */
  142.  
  143. extern unsigned int bdos();
  144.  
  145. unsigned char monthName[] =
  146.     {"Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"};
  147. unsigned char dayName[] =
  148.     {"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat"};
  149.  
  150. unsigned short int atou(p)
  151. unsigned char *p;
  152. {
  153.    unsigned int g = 0;
  154.    while (isspace(*p))
  155.       ++p;
  156.    while (isdigit(*p))
  157.       g = g*10 + *p++ - '0';
  158.    return g;
  159. }
  160.  
  161. /*-----------------------------------------------------------------------------
  162.  
  163.             g e t D a t e   and   g e t T i m e
  164.             =============         =============
  165.  
  166.     Prompt for date or time and get input from keyboard.
  167.  
  168. -----------------------------------------------------------------------------*/
  169.  
  170. void getDate()
  171. {
  172.     printf("Enter today's date (%s/YY): ", (usa ? "MM/DD" : "DD/MM"));
  173.     gets(b64);
  174. }
  175.  
  176. void getTime()
  177. {
  178.    printf("Enter the time (HH:MM:SS): ");
  179.    gets(b64);
  180. }
  181.  
  182. /*-----------------------------------------------------------------------------
  183.  
  184.                   u s a g e
  185.                   =========
  186.  
  187.     This routine is entered if we couldn't make sense of the command-
  188.     line.  Displays a very terse instruction on usage.
  189.  
  190. ------------------------------------------------------------------------------*/
  191.  
  192. void usage()
  193. {
  194. #ifdef SWaddr
  195.    printf("date [read | set | continuous | %s/yy hh:mm:ss]",
  196. #else
  197.    printf("date [set | continuous | %s/yy hh:mm:ss]",
  198. #endif
  199.         (usa ? "mm/dd" : "dd/mm"));
  200. }
  201.  
  202. /*-----------------------------------------------------------------------------
  203.  
  204.                 a M o n t h
  205.                 ===========
  206.  
  207.     Checks a string to see if it is a month name.  Insensitive to
  208.     upper/lower case.  Only looks at first three characters.  Returns
  209.     month number (1-12) or 0.
  210.  
  211. -----------------------------------------------------------------------------*/
  212.  
  213. unsigned short int aMonth(c)
  214. unsigned char *c;
  215. {
  216.    unsigned short int m;
  217.    unsigned char *n, *s, looking = 1;
  218.  
  219.    for (m = 0; looking && m < 12; ++m)
  220.       {
  221.      n = &monthName[m*4];
  222.      s = c;
  223.      if (isalpha(*s) && (*s++ & 0x5F) == *n++ &&
  224.          isalpha(*s) && (*s++ | 0x20) == *n++ &&
  225.          isalpha(*s) && (*s   | 0x20) == *n)
  226.         looking = 0;
  227.       }
  228.    return looking ? 0 : m;
  229. }
  230.  
  231. /*-----------------------------------------------------------------------------
  232.  
  233.                    l e a p
  234.                    =======
  235.  
  236.     Returns 1 if the year is a leap year, 0 otherwise.  Crude and
  237.     takes advantage of the fact that 2000 will be a leap year by
  238.     ignoring the checks for non-leap end-of-century years.
  239.  
  240. -----------------------------------------------------------------------------*/
  241.  
  242. unsigned short int leap(year)
  243. unsigned short int year;
  244. {
  245.    return (year & 3) ? 0 : 1;
  246. }
  247.  
  248. /*-----------------------------------------------------------------------------
  249.  
  250.                   y e a r L e n g t h
  251.                   ===================
  252.  
  253.     Determines the number of days in a year.  Crude, and takes full
  254.     advantage of the fact that 2000 will be a leap year.
  255.  
  256. -----------------------------------------------------------------------------*/
  257.  
  258. unsigned int yearLength(year)
  259. unsigned short int year;
  260. {
  261.    return 365 + leap(year);
  262. }
  263.  
  264. /*-----------------------------------------------------------------------------
  265.  
  266.                 d a y s I n
  267.                 ===========
  268.  
  269.     Returns the number of days in a month (taking leap years into
  270.     account).
  271.  
  272. -----------------------------------------------------------------------------*/
  273.  
  274. unsigned char daysIn(month,year)
  275. unsigned short int month, year;
  276. {
  277.    static unsigned char monthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  278.    return monthLength[month] + ((month == 1) ? leap(year) : 0);
  279. }
  280.  
  281. /*-----------------------------------------------------------------------------
  282.  
  283.              e x p a n d   and   c o n t r a c t
  284.              ===========     ===============
  285.  
  286.     expand() takes an array of 64 bits and blows it out to an array
  287.     of 64 bytes with the low-order bit of each byte set according to
  288.     the corresponding bit in the bit array.
  289.  
  290.     contract() does the reverse and builds a bit array from the low-
  291.     order bits of a byte array.
  292.  
  293. -----------------------------------------------------------------------------*/
  294.  
  295. void expand(narrow,wide)
  296. unsigned char narrow[], *wide;
  297. {
  298.    int    byte, bit;
  299.  
  300.    for (byte=0; byte<8; ++byte)
  301.       for (bit=0; bit<8; ++bit)
  302.      *wide++ = (narrow[byte] >> bit) & 1;
  303. }
  304.  
  305. void contract(wide,narrow)
  306. unsigned char *wide, *narrow;
  307. {
  308.    int byte, bit;
  309.    unsigned char val;
  310.    for (byte=0; byte<8; ++byte)
  311.       {
  312.      val = 0;
  313.      for(bit=0; bit<8; ++bit)
  314.         val |= (*wide++ & 1) << bit;
  315.      narrow[byte] = val;
  316.       }
  317. }
  318.  
  319. /*-----------------------------------------------------------------------------
  320.  
  321.                   u n b c d
  322.                   =========
  323.  
  324.     Converts a BCD byte to a binary number.
  325.  
  326. -----------------------------------------------------------------------------*/
  327.  
  328. unsigned short int unbcd(v)
  329. unsigned char v;
  330. {
  331.    return (v >> 4) * 10 + (v & 15);
  332. }
  333.  
  334. /*-----------------------------------------------------------------------------
  335.  
  336.                     b c d
  337.                     =====
  338.  
  339.     Converts a binary number to a BCD byte.
  340.  
  341. -----------------------------------------------------------------------------*/
  342.  
  343. unsigned char bcd(v)
  344. unsigned short int v;
  345. {
  346.    return ((v / 10) << 4) | (v % 10);
  347. }
  348.  
  349. /*-----------------------------------------------------------------------------
  350.  
  351.                 r e a d C l o c k
  352.                 =================
  353.  
  354.     Reads the hardware clock, converts the time to DRI format and
  355.     sets the date and time fields in the SCB.  Thereafter, the CIO
  356.     interrupts keep the system clock ticking.
  357.  
  358. -----------------------------------------------------------------------------*/
  359.  
  360. void readClock()
  361. {
  362. #ifdef SWaddr
  363.    extern void ibmm();    /* Inter-bank memory move - parameters are:-
  364.                 Source address,
  365.                 Source bank number,
  366.                 Destination address,
  367.                 Destiation bank number,
  368.                 Number of bytes to transfer.
  369.             */
  370. #endif
  371.  
  372.    extern void ei(), di();
  373.    unsigned int y, m;
  374.  
  375. #ifdef DS1216
  376.    ibmm(SWaddr,SWbank,b64,TPAbank,64);
  377.    expand(key,b64);            /* Expand key to 64 bytes */
  378.    ibmm(b64,TPAbank,SWaddr,SWbank,64);    /* Write key to unlock clock */
  379.    ibmm(SWaddr,SWbank,b64,TPAbank,64);    /* Read clock */
  380.    contract(b64,buf);            /* Contract clock readout */
  381. #endif
  382. #ifdef DS1216E
  383.    for (y=64; y--;)
  384.       ibmm(SWaddr+A2,SWbank,b64,TPAbank,1);
  385.    expand(key,b64);            /* Expand key to 64 bytes */
  386.    for (y=0; y<64; ++y)
  387.       ibmm(SWaddr+b64[y],SWbank,b1,TPAbank,1);
  388.    for (y=0; y<64; ++y)
  389.       ibmm(SWaddr+A2,SWbank,&b64[y],TPAbank,1);    /* Read clock */
  390.    contract(b64,buf);            /* Contract clock readout */
  391. #endif
  392.  
  393. /* buf[] now contains the clock readout in BCD as follows ....
  394.     buf[0]        1/100 second
  395.     buf[1]        second
  396.     buf[2]        minute
  397.     buf[3]        hour
  398.     buf[4]        12/24-hr flag and day of week
  399.     buf[5]        day
  400.     buf[6]        month
  401.     buf[7]        year
  402.    We convert it to DRI format .... */
  403.  
  404.    time_pb.days = 0;
  405.    for (y=78; y < unbcd(buf[7]); ++y)
  406.       time_pb.days += yearLength(y);
  407.    for (m=0; m < unbcd(buf[6])-1; ++m)
  408.       time_pb.days += daysIn(m,y);
  409.    time_pb.days += unbcd(buf[5]);
  410.    time_pb.hour = buf[3];
  411.    time_pb.minute = buf[2];
  412.    time_pb.second = buf[1];
  413.  
  414. /* Now we update the SCB fields.  Note that we must do this with interrupts
  415.    disabled so we don't get a clock rollover.  Also, we must directly update
  416.    the SCB fields because the standard BDOS function (104) for setting the
  417.    clock clears the seconds field!!! */
  418.  
  419.    scb_pb.offset = DATE;
  420.    scb_pb.worb = WORD;
  421.    scb_pb.value = time_pb.days;
  422.    di();
  423.    bdos(SET_SCB,&scb_pb);
  424.    scb_pb.offset += 2;
  425.    scb_pb.worb = BYTE;
  426.    scb_pb.value = time_pb.hour;
  427.    bdos(SET_SCB,&scb_pb);
  428.    scb_pb.offset++;
  429.    scb_pb.value = time_pb.minute;
  430.    bdos(SET_SCB,&scb_pb);
  431.    scb_pb.offset++;
  432.    scb_pb.value = time_pb.second;
  433.    bdos(SET_SCB,&scb_pb);
  434.    ei();
  435. /* If neither SmartWatch socket is present then we want to tell the CP/M+
  436.    BIOS that it should update its clock. */
  437. #ifndef SWaddr
  438.    bios_pb.bcVal = 0xFF;        /* Tell BIOS to set h/w clock */
  439.    bios_pb.func  = TIME;
  440.    bdos(50,&bios_pb);
  441. #endif
  442. }
  443.  
  444. /*-----------------------------------------------------------------------------
  445.  
  446.                 s h o w T i m e
  447.                 ===============
  448.  
  449.     Displays the current date and time.  May loop pending a keypress.
  450.  
  451. -----------------------------------------------------------------------------*/
  452.  
  453. void showTime(looping)
  454. unsigned char looping;
  455. {
  456.    short int y, m, d, w;
  457.    unsigned char ss = 0xFF;
  458.  
  459.    do
  460.       {
  461.      while ((time_pb.second = bdos(GET_TIME, &time_pb)) == ss)
  462.         if (looping)
  463.            if (kbhit())
  464.           {
  465.              looping = 0;
  466.              getch();
  467.               }
  468.      ss = time_pb.second;
  469.  
  470.      w = ((d = time_pb.days) + 6) % 7;
  471.  
  472.      for (y = 78; d > yearLength(y); ++y)
  473.         d -= yearLength(y);
  474.  
  475.      for (m = 0; d > daysIn(m,y); ++m)
  476.         d -= daysIn(m,y);
  477.  
  478.      printf("\r%s %d %s %d; %02x:%02x:%02x ",
  479.             &dayName[w*4],
  480.             d, &monthName[m*4], y+1900,
  481.             time_pb.hour,
  482.             time_pb.minute,
  483.             time_pb.second);
  484.       }
  485.    while (looping);
  486. }
  487.  
  488. /*-----------------------------------------------------------------------------
  489.  
  490.                    p a r s e D a t e
  491.                    =================
  492.  
  493. -----------------------------------------------------------------------------*/
  494.  
  495. unsigned char parseDate(p)
  496. unsigned char *p;
  497. {
  498.    unsigned short int v;
  499.    unsigned char a1, mf;
  500.    mf = usa;
  501.    a1 = 0;
  502.    while (isspace(*p))
  503.       ++p;
  504.    if (isalpha(*p)) /* then may be (should be) a month name */
  505.       {
  506.      time.month = aMonth(p);
  507.      a1 = 1;
  508.      while (isalpha(*p))
  509.         ++p;
  510.       }
  511.    else if (isdigit(*p)) /* then should be a month or day number */
  512.       {
  513.      time.month = atou(p);    /* treat it as a month for now */
  514.      while (isdigit(*p))
  515.         ++p;
  516.       }
  517.    while (*p && !isalpha(*p) && !isdigit(*p))
  518.       ++p;
  519.  
  520.    if (isalpha(*p))    /* then should be a month name */
  521.       {
  522.      v = aMonth(p);
  523.      if (a1)    /* then we've already seen a month name */
  524.         return 1;    /* so this is wrong */
  525.      time.day = time.month;
  526.      time.month = v;
  527.      while (isalpha(*p))
  528.         ++p;
  529.       }
  530.    else if (isdigit(*p))
  531.       {
  532.      v = atou(p);
  533.      while (isdigit(*p))
  534.         ++p;
  535.      if (a1)        /* first thing was a month name */
  536.         time.day = v;    /* this must be a day number */
  537.      else            /* first thing was a number */
  538.         if (mf)        /* if MM/DD/YY format */
  539.            time.day = v;    /*    this is a day */
  540.         else        /* else first thing was a day */
  541.            {        /*  and this is a month */
  542.           time.day = time.month;
  543.           time.month = v;
  544.            }
  545.       }
  546.  
  547.    while (*p && !isdigit(*p))
  548.       ++p;
  549.  
  550.    if (isdigit(*p))
  551.       {
  552.      v = atou(p);
  553.      if (v > 1900)
  554.         v -= 1900;
  555.      if (v < 78 || v > 114)
  556.         v = 0;
  557.      time.year = v;
  558.       }
  559.  
  560.    if (time.year == 0 || time.day == 0 || time.month == 0)
  561.       return 1;
  562.    if (time.month > 12)
  563.       return 1;
  564.    if (time.day > daysIn(time.month-1,time.year))
  565.       return 1;
  566.    return 0;
  567. }
  568.    
  569. /*-----------------------------------------------------------------------------
  570.  
  571.                    p a r s e T i m e
  572.                    =================
  573.  
  574. -----------------------------------------------------------------------------*/
  575.  
  576. unsigned char parseTime(p)
  577. unsigned char *p;
  578. {
  579.    unsigned short int v;
  580.  
  581.    while (isspace(*p))
  582.       ++p;
  583.    if (!isdigit(*p))
  584.       return 1;
  585.    if ((v = atou(p)) > 23)
  586.       return 1;
  587.    time.hour = v;
  588.    while (isdigit(*p))
  589.       ++p;
  590.    while (*p && !isdigit(*p))
  591.       ++p;
  592.    if ((v = atou(p)) > 59)
  593.       return 1;
  594.    time.minute = v;
  595.    while (isdigit(*p))
  596.       ++p;
  597.    while (*p && !isdigit(*p))
  598.       ++p;
  599.    if ((v = atou(p)) > 59)
  600.       return 1;
  601.    time.second = v;
  602.    return 0;
  603. }
  604.  
  605. /*-----------------------------------------------------------------------------
  606.  
  607.                 s e t C l o c k
  608.                 ===============
  609.  
  610.     Obtains date and time specifications and sets the system clock.
  611.  
  612. -----------------------------------------------------------------------------*/
  613.  
  614. void setClock(dateStr, timeStr)
  615. unsigned char *dateStr, *timeStr;
  616. {
  617.    unsigned short int y, m, days = 0;
  618.    unsigned char prompt = 0;
  619. #ifdef SWaddr
  620.    extern void ibmm();    /* Inter-bank memory move - parameters are:-
  621.                 Source address,
  622.                 Source bank number,
  623.                 Destination address,
  624.                 Destiation bank number,
  625.                 Number of bytes to transfer.
  626.             */
  627. #endif
  628.  
  629.    if (dateStr == NULL)
  630.       {
  631.      prompt = 1;
  632.      getDate();
  633.      dateStr = b64;
  634.       }
  635.    if (parseDate(dateStr))
  636.       {
  637.      puts("Badly-formed date");
  638.      exit();
  639.       }
  640.    if (timeStr == NULL)
  641.       {
  642.      getTime();
  643.      timeStr = b64;
  644.       }
  645.    if (parseTime(timeStr))
  646.       {
  647.      puts("Badly-formed time");
  648.      exit();
  649.       }
  650.  
  651. /* If we get here then we have a valid date and time.  Now program the clock */
  652.    buf[7] = bcd(time.year);
  653.    buf[6] = bcd(time.month);
  654.    buf[5] = bcd(time.day);
  655.    buf[3] = bcd(time.hour);
  656.    buf[2] = bcd(time.minute);
  657.    buf[1] = bcd(time.second);
  658.    buf[0] = 0;
  659.    days = 0;
  660.    for (y=78; y < time.year; ++y)
  661.       days += yearLength(y);
  662.    for (m=0; m < time.month-1; ++m)
  663.       days += daysIn(m,time.year);
  664.    days += time.day;
  665.    buf[4] = (days+6) % 7 + 16;
  666.    if (prompt)
  667.       {
  668.      printf("Press any key to set time: ");
  669.      if (getch() == 3)        /* Allow ^C abort */
  670.         exit();
  671.      putchar('\n');
  672.       }
  673. #ifdef DS1216
  674.    ibmm(SWaddr,SWbank,b64,TPAbank,64);
  675.    expand(key,b64);
  676.    ibmm(b64,TPAbank,SWaddr,SWbank,64);
  677.    expand(buf,b64);
  678.    ibmm(b64,TPAbank,SWaddr,SWbank,64);
  679. #endif
  680. #ifdef DS1216E
  681.    for (y=64; y--;)
  682.       ibmm(SWaddr+A2,SWbank,b64,TPAbank,1);
  683.    expand(key,b64);
  684.    for (y=0; y<64; ++y)
  685.       ibmm(SWaddr+b64[y],SWbank,b1,TPAbank,1);
  686.    expand(buf,b64);
  687.    for (y=0; y<64; ++y)
  688.       ibmm(SWaddr+b64[y],SWbank,b1,TPAbank,1);
  689. #endif
  690. /* If neither clock is present then the properly-formatted date is still
  691.    in buf[] and in the struct time */
  692. }
  693.  
  694. /*-----------------------------------------------------------------------------
  695.  
  696.                   m a i n
  697.                   =======
  698.  
  699.     Entry point to this program.  Performs primary command-line
  700.     analysis and invokes appropriate function.
  701.  
  702. -----------------------------------------------------------------------------*/
  703.  
  704. main(argc, argv)
  705. short int argc;
  706. unsigned char *argv[];
  707. {
  708.    signal(SIGINT, SIG_IGN);
  709.  
  710.    if (bdos(GET_VSN,0) < 0x30)
  711.       {
  712.      puts("This program requires CP/M 3");
  713.      exit();
  714.       }
  715.  
  716.    switch (argc)
  717.       {
  718. case 1:
  719.      showTime(0);
  720.      break;
  721. case 2:
  722.      switch (*(argv[1]) & 0x5F)
  723.         {
  724.    case 'S':
  725.            setClock(NULL,NULL);
  726. #ifdef SWaddr
  727.    case 'R':
  728. #endif
  729.            readClock();
  730.            showTime(0);
  731.            break;
  732.    case 'C':
  733.            showTime(1);
  734.            break;
  735.    default:
  736.            usage();
  737.         }
  738.      break;
  739. case 3:
  740.      setClock(argv[1],argv[2]);
  741.      readClock();
  742.      showTime(0);
  743.      break;
  744. default:
  745.      usage();
  746.       }
  747. }
  748.