home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / sources / unix / 280 < prev    next >
Encoding:
Text File  |  1992-12-27  |  17.8 KB  |  541 lines

  1. Path: sparky!uunet!paladin.american.edu!gatech!concert!decwrl!pa.dec.com!vixie
  2. From: rushpc!jjr@csn.org (John Rushford)
  3. Newsgroups: comp.sources.unix
  4. Subject: v26i081: nisttime - Set the system clock to the NIST master clock, Part01/01
  5. Date: 27 Dec 1992 23:22:57 GMT
  6. Organization: Digital Equipment Corporation Palo Alto, CA
  7. Lines: 527
  8. Sender: unix-sources-moderator@pa.dec.com
  9. Approved: vixie@pa.dec.com
  10. Message-ID: <1hldshINN8in@usenet.pa.dec.com>
  11. NNTP-Posting-Host: cognition.pa.dec.com
  12. Originator: vixie@cognition.pa.dec.com
  13.  
  14. Submitted-By: rushpc!jjr@csn.org (John Rushford)
  15. Posting-Number: Volume 26, Issue 81
  16. Archive-Name: nisttime/part01
  17.  
  18. Saw settime.c from John Walker in comp.unix.sources for a SPARC II.
  19. Attached is a program similar to settime.c however, it is written
  20. for System V Release 3.  This shell archive includes a manual page
  21. and a Makefile.  Just unbundle this archive using "sh".  You must
  22. be logged in as root to 'make install' this program.
  23.  
  24. John Rushford
  25. rushpc!jjr@csn.org
  26.  
  27. [ moderator's extract of the included man page...
  28.  
  29. NAME
  30.      nisttime - Set the system clock to the NIST master clock
  31.      usnotime - Set the system clock to the USNO master clock
  32.  
  33. SYNOPSIS
  34.      nisttime [ -sv ]
  35.      usnotime [ -sv ]
  36.  
  37. DESCRIPTION
  38.      This program calls a master clock reference and compares the
  39.      system clock with the reference. nisttime calls the National
  40.      Institute of Standards and Technology's master clock in
  41.      Boulder Colorado, (303) 494-4774 @ 1200 baud.  usnotime
  42.      calls the U.S. Naval Observatory master clock in Washington
  43.      DC, (202) 653-0351 @ 1200 baud.
  44.  
  45.   --vix ]
  46.  
  47. #! /bin/sh
  48. # This is a shell archive.  Remove anything before this line, then unpack
  49. # it by saving it into a file and typing "sh file".  To overwrite existing
  50. # files, type "sh file -c".  You can also feed this as standard input via
  51. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  52. # will see the following message at the end:
  53. #        "End of archive 1 (of 1)."
  54. # Contents:  MANIFEST Makefile README nisttime.1 nisttime.c
  55. # Wrapped by vixie@cognition.pa.dec.com on Sun Dec 27 15:21:47 1992
  56. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  57. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  58.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  59. else
  60. echo shar: Extracting \"'MANIFEST'\" \(269 characters\)
  61. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  62. X   File Name        Archive #    Description
  63. X-----------------------------------------------------------
  64. X MANIFEST                   1    This shipping list
  65. X Makefile                   1    
  66. X README                     1    
  67. X nisttime.1                 1    
  68. X nisttime.c                 1    
  69. END_OF_FILE
  70. if test 269 -ne `wc -c <'MANIFEST'`; then
  71.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  72. fi
  73. # end of 'MANIFEST'
  74. fi
  75. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  76.   echo shar: Will not clobber existing file \"'Makefile'\"
  77. else
  78. echo shar: Extracting \"'Makefile'\" \(603 characters\)
  79. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  80. X# Makefile for 'nisttime' and 'usnotime'
  81. X#
  82. X# Log in as 'root' and type 'make install'
  83. X#
  84. X
  85. DESTROOT = 
  86. DESTPATH = $(DESTROOT)/usr/local
  87. DESTBIN = $(DESTPATH)/bin
  88. DESTMAN = $(DESTPATH)/man
  89. X
  90. CFLAGS= -O
  91. LDFLAGS= -s
  92. X
  93. all: nisttime
  94. X
  95. install: nisttime
  96. X    cp nisttime $(DESTBIN)/nisttime
  97. X    chown uucp $(DESTBIN)/nisttime
  98. X    chgrp uucp $(DESTBIN)/nisttime
  99. X    chmod 4111 $(DESTBIN)/nisttime
  100. X    ln $(DESTBIN)/nisttime $(DESTBIN)/usnotime
  101. X
  102. install.man: nisttime.1
  103. X    cp nisttime.1 $(DESTMAN)/man1/nisttime.1
  104. X    echo .so $(DESTMAN)/man1/nisttime.1 >$(DESTMAN)/man1/usnotime.1
  105. X
  106. clean:; rm -f *.o *.CKP *.BAK *~ a.out core nisttime
  107. END_OF_FILE
  108. if test 603 -ne `wc -c <'Makefile'`; then
  109.     echo shar: \"'Makefile'\" unpacked with wrong size!
  110. fi
  111. # end of 'Makefile'
  112. fi
  113. if test -f 'README' -a "${1}" != "-c" ; then 
  114.   echo shar: Will not clobber existing file \"'README'\"
  115. else
  116. echo shar: Extracting \"'README'\" \(969 characters\)
  117. sed "s/^X//" >'README' <<'END_OF_FILE'
  118. Saw settime.c from John Walker in comp.unix.sources for a SPARC II.
  119. Attached is a program similar to settime.c however, it is written
  120. for System V Release 3.  This shell archive includes a manual page
  121. and a Makefile.  Just unbundle this archive using "sh".  You must
  122. be logged in as root to 'make install' this program.
  123. X
  124. John Rushford
  125. rushpc!jjr@csn.org
  126. X
  127. X[ moderator's extract of the included man page...
  128. X
  129. NAME
  130. X     nisttime - Set the system clock to the NIST master clock
  131. X     usnotime - Set the system clock to the USNO master clock
  132. X
  133. SYNOPSIS
  134. X     nisttime [ -sv ]
  135. X     usnotime [ -sv ]
  136. X
  137. DESCRIPTION
  138. X     This program calls a master clock reference and compares the
  139. X     system clock with the reference. nisttime calls the National
  140. X     Institute of Standards and Technology's master clock in
  141. X     Boulder Colorado, (303) 494-4774 @ 1200 baud.  usnotime
  142. X     calls the U.S. Naval Observatory master clock in Washington
  143. X     DC, (202) 653-0351 @ 1200 baud.
  144. X
  145. X  --vix ]
  146. END_OF_FILE
  147. if test 969 -ne `wc -c <'README'`; then
  148.     echo shar: \"'README'\" unpacked with wrong size!
  149. fi
  150. # end of 'README'
  151. fi
  152. if test -f 'nisttime.1' -a "${1}" != "-c" ; then 
  153.   echo shar: Will not clobber existing file \"'nisttime.1'\"
  154. else
  155. echo shar: Extracting \"'nisttime.1'\" \(1324 characters\)
  156. sed "s/^X//" >'nisttime.1' <<'END_OF_FILE'
  157. X.TH NISTTIME 1 
  158. X.UC 4
  159. X.SH NAME
  160. nisttime \- Set the system clock to the NIST master clock
  161. usnotime \- Set the system clock to the USNO master clock
  162. X.SH SYNOPSIS
  163. X.B nisttime 
  164. X[
  165. X.B \-sv
  166. X]
  167. X.br
  168. X.B usnotime 
  169. X[
  170. X.B \-sv
  171. X] 
  172. X.SH DESCRIPTION
  173. This program calls a master clock reference and compares the
  174. system clock with the reference.  
  175. X.B
  176. nisttime 
  177. calls the National Institute of Standards and Technology's 
  178. master clock in Boulder Colorado, (303) 494-4774 @ 1200 baud.
  179. X.B
  180. usnotime 
  181. calls the U.S. Naval Observatory master clock in Washington DC,
  182. X(202) 653-0351 @ 1200 baud.
  183. X.SH OPTIONS
  184. X.TP 10
  185. X.B \-s
  186. The system clock will be reset to the time of the called master clock.
  187. Only root may use this option.
  188. X.TP 10
  189. X.B \-v 
  190. The program will print to stdout all data received from the master
  191. clock time service.
  192. X.SH NOTE
  193. UNIX System V. Release 3 using BNU UUCP.  Requires entries in the
  194. UUCP Systems file for 
  195. X.B nisttime
  196. and
  197. X.B usnotime:
  198. X.PP
  199. nisttime Never ACU 1200 13034944774
  200. X.br
  201. usnotime Never ACU 1200 12026530351
  202. X.PP
  203. This program should be owned by 'uucp' and set to mode O'4111.
  204. X.B nisttime
  205. and
  206. X.B usnotime
  207. should be linked.
  208. X.SH FILES
  209. X/usr/lib/uucp/Devices
  210. X.br
  211. X/usr/lib/uucp/Dialcodes
  212. X.br
  213. X/usr/lib/uucp/Dialers
  214. X.br
  215. X/usr/lib/uucp/Systems
  216. X.SH AUTHOR
  217. X   John J. Rushford
  218. X.br
  219. X   Phone:  (303) 465-4070
  220. X.br
  221. X   Usenet: rushpc!jjr@csn.org
  222. END_OF_FILE
  223. if test 1324 -ne `wc -c <'nisttime.1'`; then
  224.     echo shar: \"'nisttime.1'\" unpacked with wrong size!
  225. fi
  226. # end of 'nisttime.1'
  227. fi
  228. if test -f 'nisttime.c' -a "${1}" != "-c" ; then 
  229.   echo shar: Will not clobber existing file \"'nisttime.c'\"
  230. else
  231. echo shar: Extracting \"'nisttime.c'\" \(10373 characters\)
  232. sed "s/^X//" >'nisttime.c' <<'END_OF_FILE'
  233. X/*
  234. X**    NAME
  235. X**        nisttime - set the system clock to the NIST master clock.
  236. X**        usnotime - set the system clock to the USNO master clock.
  237. X**
  238. X**    SYNOPSIS
  239. X**        nisttime [-sv]
  240. X**        usnotime [-sv]
  241. X**
  242. X**    DESCRIPTION
  243. X**        This  program calls a master  clock reference  and compares the
  244. X**        system clock  with the reference.  nisttime calls  the National
  245. X**        Institute of Standards and Technology's master clock in Boulder
  246. X**        Colorado, (303) 494-4774 @ 1200  baud.  usnotime calls the U.S.
  247. X**        Naval Observatory master clock in Washington DC, (202) 653-0351
  248. X**        @ 1200 baud.
  249. X**
  250. X**        If the -s option is used, the system clock is reset to the time 
  251. X**        of the called master clock.   Only root may use the  -s option. 
  252. X**        If the -v  option is used,  the program will  print to 'stdout' 
  253. X**        all data received from the master clock time service.
  254. X**
  255. X**    NOTE
  256. X**        UNIX System  V. Release 3 using BNU UUCP.  Requires  entries in
  257. X**        the UUCP Systems file for 'nisttime' and 'usnotime':
  258. X**
  259. X**             nisttime Never ACU 1200 13034944774
  260. X**             usnotime Never ACU 1200 12026530351
  261. X**
  262. X**        This program should be owned by 'uucp'  and set to mode O'4111.
  263. X**        nisttime and usnotime should be linked.
  264. X**
  265. X**    FILES
  266. X**        /usr/lib/uucp/Devices
  267. X**        /usr/lib/uucp/Dialcodes
  268. X**        /usr/lib/uucp/Dialers
  269. X**        /usr/lib/uucp/Systems
  270. X**
  271. X**    COMPILE AND INSTALLATION
  272. X**        cc -s -O nisttime.c -o /usr/bin/nisttime
  273. X**        chown uucp /usr/bin/nisttime
  274. X**        chgrp uucp /usr/bin/nisttime
  275. X**        ln /usr/bin/nisttime /usr/bin/usnotime
  276. X**        chmod 4111 /usr/bin/nisttime
  277. X**
  278. X**    PROGRAMMER
  279. X**        John J. Rushford
  280. X**        (303) 465-4070
  281. X**        rushpc!jjr@csn.org
  282. X*/
  283. X
  284. static char Sccsid[] = "@(#)rushpc!jjr@csn.org:nisttime.c 2.7, 11 Mar 1992";
  285. X
  286. X#include <dial.h>
  287. X#include <errno.h>
  288. X#include <stdio.h>
  289. X#include <string.h>
  290. X#include <sys/types.h>
  291. X#include <time.h>
  292. X
  293. X#define BAUD          1200         /* modem speed */
  294. X#define EPOCH         40587        /* MJD for Jan 1, 1970 00:00:00 GMT */
  295. X#define HOUR          (60 * 60)    /* seconds in an hour */
  296. X#define LINE          80           /* input line buffer size */
  297. X#define NIST_SYSNAME  "nisttime"   /* system name for NIST */
  298. X#define OTMA          '*'          /* nominal on-time mark for USNO & NIST */
  299. X#define OTMB          '#'          /* on-time mark after delay compensation */
  300. X#define ONEDAY        (HOUR * 24)  /* seconds in a day */
  301. X#define USNO_SYSNAME  "usnotime"   /* system name for Naval Observatory */
  302. X
  303. X/* scanf(3S) format strings: */
  304. X#define NISTFMT "%d%*s%2d%*[:]%2d%*[:]%2d"  /* for nisttime */
  305. X#define USNOFMT "%d%*d%2d%2d%2d"            /* for usnotime */
  306. X
  307. X/* output message macros: */
  308. X#define CLKERR(a)     (void)fprintf(stderr, \
  309. X                     "%s: cannot set the clock, difference > one day.\n", a)
  310. X#define CLKSET(a)     (void)fprintf(stdout,"%s: reset the system clock.\n", a)
  311. X#define DATAERR(a)    (void)fprintf(stderr,"%s: received invalid data.\n", a)
  312. X#define DELTA(a,b,c)  (void)fprintf(stdout, \
  313. X                     "%s: the system clock is %ld second(s) %s.\n", a, b, c)
  314. X#define DIALERR(a,b)  (void)fprintf(stderr, "%s: %s.\n", a, b)
  315. X#define ONTIME(a)     (void)fprintf(stdout, \
  316. X                     "%s: the system clock is on time.\n", a)
  317. X#define SETERR(a)     (void)fprintf(stderr, \
  318. X                     "%s: only root may set the system clock.\n", a)
  319. X#define USAGE(a)      (void)fprintf(stderr, "Usage: %s [-sv]\n", a)
  320. X
  321. X#ifndef __STDC__    
  322. X   typedef enum    boolean { B_FALSE, B_TRUE } boolean_t;
  323. X#endif    /* __STDC__ */
  324. X
  325. X/* dial(3C) error messages indexed by translated error return code: */
  326. static char *error_msg[13] = {
  327. X   "interrupt occured",
  328. X   "dialer hung, no return from write",
  329. X   "no answer, caller script failed",
  330. X   "illegal baud-rate",
  331. X   "acu problem, open() failure",
  332. X   "line problem, open() failure",
  333. X   "can't open Devices file",
  334. X   "requested device not available",
  335. X   "requested device not known",
  336. X   "no device available at requested baud rate",
  337. X   "no device known at requested baud rate",
  338. X   "requested speed does not match",
  339. X   "system not known and/or can't read Systems file"
  340. X};
  341. X
  342. X/* returns a pointer to the base name component of the path name: */
  343. static char *
  344. X#ifndef __STDC__
  345. basename(pathname)
  346. char *pathname;
  347. X#else
  348. basename(char *pathname)
  349. X#endif
  350. X{
  351. X   char *Basename;    /* pointer to resulting basename */
  352. X
  353. X   if ((Basename = strrchr(pathname, '/')) == NULL)
  354. X    Basename = pathname;    /* not a path name*/
  355. X   else Basename++;    /* move past last slash in the path name */
  356. X
  357. X   return Basename;
  358. X}
  359. X
  360. X/* returns the number of seconds since 00:00:00 GMT on January 1, 1970 */
  361. static time_t 
  362. X#ifndef __STDC__
  363. Since1970(Julian, Hour, Min, Sec)
  364. int Julian, Hour, Min, Sec;
  365. X#else
  366. Since1970(int Julian, int Hour, int Min, int Sec)
  367. X#endif
  368. X{
  369. X   int no_days = 0;    /* days since January 1, 1970 */
  370. X
  371. X   no_days = Julian - EPOCH;
  372. X   return ((no_days * ONEDAY) + (Hour * HOUR) + (Min * 60) + Sec);
  373. X}
  374. X
  375. X#ifndef __STDC__
  376. main(argc, argv)
  377. int argc;
  378. char **argv;
  379. X#else
  380. main(int argc, char **argv)
  381. X#endif
  382. X{
  383. X   boolean_t      clkset   = B_FALSE,  /* clock was reset flag */
  384. X           complete = B_FALSE,  /* call complete flag */
  385. X           errflag  = B_FALSE,  /* invalid option flag */
  386. X           no_data  = B_FALSE,  /* invalid time data flag */
  387. X           sflag    = B_FALSE,  /* reset the system clock flag */
  388. X           usnoflag = B_FALSE,  /* U.S Naval Observatory flag */
  389. X           vflag    = B_FALSE;  /* verbose output flag */
  390. X   CALL           call;                /* dial structure */
  391. X   char           line[LINE],          /* input line storage buffer */
  392. X           *prog;               /* base name of this program */
  393. X   FILE           *modem_rfp;          /* stream pointer to modem */
  394. X   int            c,                   /* option character */
  395. X           Hour     = 0,        /* hours (00 - 23) */
  396. X           lineno   = 0,        /* number of received input lines */
  397. X           Min      = 0,        /* minutes (00 - 59) */
  398. X           Mjd      = 0,        /* modified julian Date */
  399. X           modem_fd,            /* dial(3C) file descriptor */
  400. X           Sample   = 0,        /* number of USNO Samples */
  401. X           Sec      = 0,        /* seconds (00 - 60) */
  402. X           getopt(),            /* getopt(3C) */
  403. X           stime();             /* stime(2) */
  404. X   extern int     optind;              /* index of next argument */
  405. X   struct termio  la;                  /* termio table */
  406. X   time_t         delta    = 0,        /* diff. between sysclk & timbuf */
  407. X           sysclk,              /* seconds since the epoch */
  408. X           timbuf;              /* seconds since the epoch */
  409. X   unsigned short getuid();            /* getuid(2) */
  410. X   void           exit();              /* exit(2) */
  411. X
  412. X   /* initialize the termio structure */
  413. X   la.c_iflag = (0 | IGNBRK | IGNPAR | IXON | IXOFF);
  414. X   la.c_oflag = 0;
  415. X   la.c_cflag = (0 | B1200 | CS8 | CREAD | HUPCL);
  416. X   la.c_lflag = (0 | ICANON | ECHO | ECHONL);
  417. X
  418. X   /* initialize the call structure */
  419. X   call.attr  = &la;
  420. X   call.baud  = -1;
  421. X   call.speed = BAUD;
  422. X   call.telno = NIST_SYSNAME;    /* call the NIST, default */
  423. X
  424. X   /* get the program base name: */
  425. X   prog = basename(argv[0]);
  426. X
  427. X   /* process command-line arguments: */
  428. X   while ((c = getopt(argc, argv, "sv")) != EOF) {
  429. X    switch(c) {
  430. X        case 's': /* request to set the system clock */
  431. X              if (getuid() == 0) sflag = B_TRUE;
  432. X              else {
  433. X              SETERR(prog);
  434. X              errflag = B_TRUE;
  435. X                     }
  436. X                     break;
  437. X           case 'v': /* request for verbose output */
  438. X              vflag = B_TRUE;
  439. X              break;
  440. X           case '?': /* unknown request */
  441. X              errflag = B_TRUE;
  442. X              break;
  443. X       }  /* end of switch statement */
  444. X   }  /* end of while loop */
  445. X   
  446. X   /* exit on command line errors: */
  447. X   if (argc > optind || errflag) {
  448. X    USAGE(prog);
  449. X    exit(1);
  450. X   }
  451. X   /* check to see if this is a call to the U.S. Naval Observatory: */
  452. X   if (strcmp(prog, USNO_SYSNAME) == 0) {
  453. X    usnoflag = B_TRUE;
  454. X    call.telno = USNO_SYSNAME;  /* reset the call structure */
  455. X   }
  456. X   /* connect to the remote system: */
  457. X   if ((modem_fd = dial(call)) < 0) {
  458. X    DIALERR(prog, error_msg[((modem_fd * -1) - 1)]);
  459. X    exit(2);
  460. X   }
  461. X   if ((modem_rfp = fdopen(modem_fd, "r")) == NULL) {
  462. X    perror(prog);
  463. X    exit(3);
  464. X   }
  465. X   /* read and process input from the remote system: */
  466. X   while (!complete && fgets(line, LINE, modem_rfp) != NULL) {
  467. X    if (usnoflag) {  /* process Naval Observatory data */
  468. X        if (line[0] == OTMA) ++Sample;   /* saw an on-time mark */
  469. X           if (Sample == 5) complete = B_TRUE;  /* 5 samples is good enough */
  470. X        else  /* process input data: */
  471. X        (void)sscanf(line, USNOFMT, &Mjd, &Hour, &Min, &Sec);
  472. X       }  
  473. X    else {  /* else process NIST data */
  474. X             (void)sscanf(line, NISTFMT, &Mjd, &Hour, &Min, &Sec);
  475. X         /* check for on-time mark, prefer an OTMB mark */
  476. X         if(line[49] == OTMB || (lineno > 20 && line[49] == OTMA)) 
  477. X                 complete = B_TRUE;  
  478. X       }  
  479. X    if (complete) {           /* done sampling the remote system so */
  480. X        (void)time(&sysclk);  /* get the local system clocks time */
  481. X        /* compute the current time according to the remote system: */
  482. X           timbuf = Since1970(Mjd, Hour, Min, Sec); 
  483. X        /* calculate the difference: */
  484. X        if (timbuf > sysclk) delta = timbuf - sysclk;
  485. X        else delta = sysclk - timbuf;
  486. X        /* check to see if the difference is out of bounds: */
  487. X        if (delta > ONEDAY || delta == 0) sflag = B_FALSE;
  488. X           /* if everything is ok, reset the system clock: */
  489. X        if (sflag && stime(&timbuf) == 0) clkset = B_TRUE;
  490. X       }
  491. X    if (vflag) {  /* if verbose output was requested then print it: */
  492. X        (void)fflush(modem_rfp); 
  493. X        (void)fprintf(stdout, "%s", line);
  494. X       }
  495. X    /* if all we've got is bum data, give up: */
  496. X       if (++lineno > 30 && !complete) complete = no_data = B_TRUE;
  497. X   }  /* end of while loop */
  498. X   
  499. X   /* terminate the call and close the modem stream: */
  500. X   undial(modem_fd);  
  501. X   (void)fclose(modem_rfp);
  502. X   
  503. X   /* if there were no good samples, report and exit: */
  504. X   if (no_data) {
  505. X    DATAERR(prog);
  506. X    exit(4);
  507. X   }
  508. X   /* call succeeded so report the results: */
  509. X   if (timbuf > sysclk) DELTA(prog, delta, "slow");
  510. X   if (sysclk > timbuf) DELTA(prog, delta, "fast");
  511. X   if (sysclk == timbuf) ONTIME(prog);
  512. X   if (delta > ONEDAY) CLKERR(prog);
  513. X   if (clkset) CLKSET(prog);
  514. X
  515. X   return 0;
  516. X}
  517. X
  518. END_OF_FILE
  519. if test 10373 -ne `wc -c <'nisttime.c'`; then
  520.     echo shar: \"'nisttime.c'\" unpacked with wrong size!
  521. fi
  522. # end of 'nisttime.c'
  523. fi
  524. echo shar: End of archive 1 \(of 1\).
  525. cp /dev/null ark1isdone
  526. MISSING=""
  527. for I in 1 ; do
  528.     if test ! -f ark${I}isdone ; then
  529.     MISSING="${MISSING} ${I}"
  530.     fi
  531. done
  532. if test "${MISSING}" = "" ; then
  533.     echo You have the archive.
  534.     rm -f ark[1-9]isdone
  535. else
  536.     echo You still need to unpack the following archives:
  537.     echo "        " ${MISSING}
  538. fi
  539. ##  End of shell archive.
  540. exit 0
  541.