home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / 3b1 / volume02 / rsetclk / part01 < prev    next >
Encoding:
Internet Message Format  |  1992-06-22  |  29.9 KB

  1. Path: comp-sources-3b1
  2. From: thad@btr.com (Thaddeus P. Floryan)
  3. Subject:  v02i008:  rsetclk: set system clock from remote host on ethernet, Part01/01
  4. Newsgroups: comp.sources.3b1
  5. Approved: dave@galaxia.network23.com
  6. X-Checksum-Snefru: 978722dd b379843c 630be6d6 4f882ab4
  7.  
  8. Submitted-by: thad@btr.com (Thaddeus P. Floryan)
  9. Posting-number: Volume 2, Issue 8
  10. Archive-name: rsetclk/part01
  11.  
  12. rsetclk - sets the system's clocks referenced to a remote host
  13.  
  14. Sets the 3B1's time-of-day and realtime clocks from another system
  15. on the net per the "time" service.  Presently Ethernet is assumed.
  16. Resolution is +/- 1 second; if more accuracy is needed (and on systems
  17. which support it), the NTP facility should be used instead.
  18.  
  19. Even if you don't have Ethernet on your 3B1, some of the ancillary
  20. time and clock routines might prove useful in other applications.
  21.  
  22. rsetclk has worked fine for over 2 months, so it's time to inflict
  23. in on the net!  :-)
  24.  
  25. This distribution includes:
  26.  
  27.     total 48
  28.     -rw-r--r--  1 thad    users      1231 Apr 12 22:46 Makefile 
  29.     -rwxr-xr-x  1 thad    users      1046 Apr  6 02:33 cleanup.exam*
  30.     -rwxr-xr-x  1 thad    users       588 Apr 12 15:29 clockupd.sh*
  31.     -rw-r--r--  1 thad    users       341 Apr  6 02:16 crontab.exam 
  32.     -rw-r--r--  1 thad    users      3494 Apr 12 17:37 mksystime.c 
  33.     -rw-r--r--  1 thad    users      4772 Apr 14 21:59 rhost_time.c 
  34.     -rw-r--r--  1 thad    users      6203 Apr 13 13:29 rsetclk.c 
  35.     -rw-r--r--  1 thad    users      1784 Apr 12 23:27 rtc_stime.c 
  36.     -rw-r--r--  1 thad    users      2111 Apr 12 23:28 rtc_time.c 
  37.  
  38. Thad Floryan [ thad@btr.com (OR) {decwrl, mips, fernwood}!btr!thad ]
  39.  
  40. ---- Cut Here and feed the following to sh ----
  41. #!/bin/sh
  42. # This is a shell archive (produced by shar 3.49)
  43. # To extract the files from this archive, save it to a file, remove
  44. # everything above the "!/bin/sh" line above, and type "sh file_name".
  45. #
  46. # made 06/15/1992 11:35 UTC by thad@thadlabs
  47. # Source directory /usr/local/src/rsetclk
  48. #
  49. # existing files will NOT be overwritten unless -c is specified
  50. #
  51. # This shar contains:
  52. # length  mode       name
  53. # ------ ---------- ------------------------------------------
  54. #   1231 -rw-r--r-- Makefile
  55. #   1243 -rw-r--r-- README
  56. #   1046 -rwxr-xr-x cleanup.exam
  57. #    588 -rwxr-xr-x clockupd.sh
  58. #    341 -rw-r--r-- crontab.exam
  59. #   3494 -rw-r--r-- mksystime.c
  60. #   4772 -rw-r--r-- rhost_time.c
  61. #   6203 -rw-r--r-- rsetclk.c
  62. #   1784 -rw-r--r-- rtc_stime.c
  63. #   2111 -rw-r--r-- rtc_time.c
  64. #
  65. # ============= Makefile ==============
  66. if test -f 'Makefile' -a X"$1" != X"-c"; then
  67.     echo 'x - skipping Makefile (File already exists)'
  68. else
  69. echo 'x - extracting Makefile (Text)'
  70. sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  71. X# Makefile for rsetclk on 3B1
  72. X#
  73. X# The program must be run as root when changing system time and is intended to
  74. X# be ONLY run by root.  Must be root to install.
  75. X#
  76. XCC    =    gcc
  77. XCFLAGS    =    -O -DUNIXPC
  78. XCWINTCP    =    -DSYSTEM5 -DSHORT_IDENT
  79. XINCL    =
  80. XIWINTCP    =    -I/usr/ethernet/include
  81. XLDFLAGS    =    -s
  82. XLIBS    =    -lnet /lib/crt0.o /usr/local/lib/gcc-gnulib -lc
  83. XNAME    =    rsetclk
  84. XOBJS    =    rsetclk.o mksystime.o rhost_time.o rtc_stime.o rtc_time.o
  85. XSRCS    =    rsetclk.c mksystime.c rhost_time.c rtc_stime.c rtc_time.c
  86. XDEST    =    /usr/local/bin
  87. XFMODE    =    4500
  88. XOWNER    =    root
  89. XGROUP    =    root
  90. X
  91. X$(NAME)    :    $(OBJS)
  92. X        $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
  93. X
  94. Xrsetclk.o :    rsetclk.c
  95. X        $(CC) $(CFLAGS) $(INCL) -c $*.c
  96. X
  97. Xmksystime.o :    mksystime.c
  98. X        $(CC) $(CFLAGS) $(INCL) -c $*.c
  99. X
  100. Xrhost_time.o :    rhost_time.c
  101. X        $(CC) $(CFLAGS) $(CWINTCP) $(INCL) $(IWINTCP) -c $*.c
  102. X
  103. Xrtc_stime.o :    rtc_stime.c
  104. X        $(CC) $(CFLAGS) $(INCL) -c $*.c
  105. X
  106. Xrtc_time.o :    rtc_time.c
  107. X        $(CC) $(CFLAGS) $(INCL) -c $*.c
  108. X
  109. Xinstall :    $(NAME)
  110. X        mv    $(NAME)  $(DEST)/
  111. X        chown $(OWNER) $(DEST)/$(NAME)
  112. X        chgrp $(GROUP) $(DEST)/$(NAME)
  113. X        chmod $(FMODE) $(DEST)/$(NAME)
  114. X
  115. Xclean    :
  116. X        rm -f $(OBJS) core *~
  117. X
  118. Xlint    :
  119. X        lint $(CFLAGS) $(CWINTCP) $(INCL) $(IWINTCP) $(SRCS)
  120. X
  121. Xlintp    :
  122. X        lint $(CFLAGS) $(CWINTCP) $(INCL) $(IWINTCP) -p $(SRCS)
  123. SHAR_EOF
  124. chmod 0644 Makefile ||
  125. echo 'restore of Makefile failed'
  126. Wc_c="`wc -c < 'Makefile'`"
  127. test 1231 -eq "$Wc_c" ||
  128.     echo 'Makefile: original size 1231, current size' "$Wc_c"
  129. fi
  130. # ============= README ==============
  131. if test -f 'README' -a X"$1" != X"-c"; then
  132.     echo 'x - skipping README (File already exists)'
  133. else
  134. echo 'x - extracting README (Text)'
  135. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  136. Xrsetclk - sets the system's clocks referenced to a remote host
  137. X
  138. XSets the 3B1's time-of-day and realtime clocks from another system
  139. Xon the net per the "time" service.  Presently Ethernet is assumed.
  140. XResolution is +/- 1 second; if more accuracy is needed (and on systems
  141. Xwhich support it), the NTP facility should be used instead.
  142. X
  143. XEven if you don't have Ethernet on your 3B1, some of the ancillary
  144. Xtime and clock routines might prove useful in other applications.
  145. X
  146. Xrsetclk has worked fine for over 2 months, so it's time to inflict
  147. Xin on the net!  :-)
  148. X
  149. XThis distribution includes:
  150. X
  151. X    total 48
  152. X    -rw-r--r--  1 thad    users      1231 Apr 12 22:46 Makefile 
  153. X    -rwxr-xr-x  1 thad    users      1046 Apr  6 02:33 cleanup.exam*
  154. X    -rwxr-xr-x  1 thad    users       588 Apr 12 15:29 clockupd.sh*
  155. X    -rw-r--r--  1 thad    users       341 Apr  6 02:16 crontab.exam 
  156. X    -rw-r--r--  1 thad    users      3494 Apr 12 17:37 mksystime.c 
  157. X    -rw-r--r--  1 thad    users      4772 Apr 14 21:59 rhost_time.c 
  158. X    -rw-r--r--  1 thad    users      6203 Apr 13 13:29 rsetclk.c 
  159. X    -rw-r--r--  1 thad    users      1784 Apr 12 23:27 rtc_stime.c 
  160. X    -rw-r--r--  1 thad    users      2111 Apr 12 23:28 rtc_time.c 
  161. X
  162. XThad Floryan [ thad@btr.com (OR) {decwrl, mips, fernwood}!btr!thad ]
  163. SHAR_EOF
  164. chmod 0644 README ||
  165. echo 'restore of README failed'
  166. Wc_c="`wc -c < 'README'`"
  167. test 1243 -eq "$Wc_c" ||
  168.     echo 'README: original size 1243, current size' "$Wc_c"
  169. fi
  170. # ============= cleanup.exam ==============
  171. if test -f 'cleanup.exam' -a X"$1" != X"-c"; then
  172.     echo 'x - skipping cleanup.exam (File already exists)'
  173. else
  174. echo 'x - extracting cleanup.exam (Text)'
  175. sed 's/^X//' << 'SHAR_EOF' > 'cleanup.exam' &&
  176. X# Example of log file(s) rollover as could be used in /etc/cleanup.wk
  177. X
  178. XADMDIR=/usr/adm
  179. X
  180. X# The list of names in the NAME loop specifies the log files to be rolled.
  181. X# The monotonically decreasing list of numbers in the GEN loop controls how
  182. X# many old LOG files are retained per the example:
  183. X#
  184. X#    OLD/*log-2 goes to OLD/*log-3,
  185. X#    OLD/*log-1 goes to OLD/*log-2,
  186. X#    OLD/*log-0 goes to OLD/*log-1,
  187. X#    current    goes to OLD/*log-0
  188. X#
  189. Xfor NAME in cronlog sulog modemlog clocklog
  190. Xdo
  191. X    for GEN in  2 1 0
  192. X    do
  193. X    PLUS=`expr $GEN + 1`
  194. X    mv      $ADMDIR/OLD/$NAME-$GEN $ADMDIR/OLD/$NAME-$PLUS 2>/dev/null || \
  195. X      touch $ADMDIR/OLD/$NAME-$GEN $ADMDIR/OLD/$NAME-$PLUS
  196. X    done
  197. X
  198. X    cp $ADMDIR/$NAME $ADMDIR/OLD/$NAME-0 2>/dev/null || touch $ADMDIR/$NAME
  199. X
  200. X    if [ "$NAME" = "cronlog" ]
  201. X    then
  202. X    # tell the status manager to empty the file $ADMDIR/cronlog
  203. X    #
  204. X    ps -e | grep "smgr" | \
  205. X        while read PID TTY TIME COMMAND
  206. X        do
  207. X        if [ "$COMMAND" = "smgr" ]
  208. X        then    kill -17 $PID
  209. X        fi
  210. X        done
  211. X    else
  212. X    > $ADMDIR/$NAME
  213. X    fi
  214. X
  215. X    chmod 640 $ADMDIR/$NAME
  216. X
  217. Xdone
  218. SHAR_EOF
  219. chmod 0755 cleanup.exam ||
  220. echo 'restore of cleanup.exam failed'
  221. Wc_c="`wc -c < 'cleanup.exam'`"
  222. test 1046 -eq "$Wc_c" ||
  223.     echo 'cleanup.exam: original size 1046, current size' "$Wc_c"
  224. fi
  225. # ============= clockupd.sh ==============
  226. if test -f 'clockupd.sh' -a X"$1" != X"-c"; then
  227.     echo 'x - skipping clockupd.sh (File already exists)'
  228. else
  229. echo 'x - extracting clockupd.sh (Text)'
  230. sed 's/^X//' << 'SHAR_EOF' > 'clockupd.sh' &&
  231. X# Sample shell script (as /etc/clockupd.sh) to be invoked by cron for updating
  232. X# the 3B1's time from a remote host at some periodic interval.
  233. X#
  234. X# The "sleep 60" is to accomodate the check for excessive clock drift made by
  235. X# the rsetclk program so as not to perturb other cron activities.
  236. X#
  237. X# stdout and stderr will both appear in LOGFILE
  238. X#
  239. X# The "-l $LOGFILE" is solely for use in messages directed to /dev/error
  240. X#
  241. XLOGFILE=/usr/adm/clocklog
  242. XRHOST=cosmic
  243. XRSETCLK=/usr/local/bin/rsetclk
  244. X
  245. Xsleep 60
  246. Xecho "\nAt `date`"             1>> $LOGFILE
  247. X$RSETCLK -l $LOGFILE -s $RHOST 1>> $LOGFILE 2>&1
  248. SHAR_EOF
  249. chmod 0755 clockupd.sh ||
  250. echo 'restore of clockupd.sh failed'
  251. Wc_c="`wc -c < 'clockupd.sh'`"
  252. test 588 -eq "$Wc_c" ||
  253.     echo 'clockupd.sh: original size 588, current size' "$Wc_c"
  254. fi
  255. # ============= crontab.exam ==============
  256. if test -f 'crontab.exam' -a X"$1" != X"-c"; then
  257.     echo 'x - skipping crontab.exam (File already exists)'
  258. else
  259. echo 'x - extracting crontab.exam (Text)'
  260. sed 's/^X//' << 'SHAR_EOF' > 'crontab.exam' &&
  261. X# Example crontab entries for /etc/clockupd.sh and /etc/cleanup.wk
  262. X#
  263. X#Mn  Hr Da Mo Da (0=SUN, 1=MON, 2=TUE, 3=WED, 4=THU, 5=FRI, 6=SAT)
  264. X#of  of of of of
  265. X#Hr  Da Mo Yr Wk  Command
  266. X#
  267. X03    3  *  *  *  /bin/sh         -c "/etc/clockupd.sh              >/dev/null"
  268. X30    5  *  *  1  /bin/sh         -c "/etc/cleanup.wk               >/dev/null"
  269. SHAR_EOF
  270. chmod 0644 crontab.exam ||
  271. echo 'restore of crontab.exam failed'
  272. Wc_c="`wc -c < 'crontab.exam'`"
  273. test 341 -eq "$Wc_c" ||
  274.     echo 'crontab.exam: original size 341, current size' "$Wc_c"
  275. fi
  276. # ============= mksystime.c ==============
  277. if test -f 'mksystime.c' -a X"$1" != X"-c"; then
  278.     echo 'x - skipping mksystime.c (File already exists)'
  279. else
  280. echo 'x - extracting mksystime.c (Text)'
  281. sed 's/^X//' << 'SHAR_EOF' > 'mksystime.c' &&
  282. X/************************************************************************
  283. X *    MKSYSTIME                        MKSYSTIME
  284. X *
  285. X * NAME
  286. X *    mksystime - creates an epoch-based time value from its components
  287. X *
  288. X * SYNOPSIS
  289. X *
  290. X *    time_t mksystime(year, month, day, hour, minute, second)
  291. X *
  292. X *    int year, month, day, hour, minute, second
  293. X *
  294. X * DESCRIPTION
  295. X *
  296. X *    mksystime() will return a time_t time value in the form of time(2) for
  297. X *    the given year, month, day, hour, minute, and second arguments.
  298. X *
  299. X *    Because this is a "raw" translation to time_t without cognizance of
  300. X *    time zones or DST, the value should be treated as being GMT.
  301. X *
  302. X *    By default, the returned value will be UNIX-style based on the epoch
  303. X *    Jan. 1, 1970 0:00:00.  Other systems' epochs are easily handled.
  304. X *
  305. X *    An invalid conversion returns a value of -1.
  306. X *
  307. X * ASSERTIONS
  308. X *
  309. X *    146097 = number of days in 400 years per 400 * 365.2425 = 146097.00
  310. X *     36524 = number of days in 100 years per 100 * 365.2425 =  36524.25
  311. X *      1461 = number of days in   4 years per   4 * 365.2425 =   1460.97
  312. X *
  313. X * BUGS
  314. X *
  315. X *    Assumes the input arguments represent a valid date. A "filter" should
  316. X *    be added for the year, month and day arguments.
  317. X *
  318. X *    The returned value succumbs to 32-bit architecture problems similar
  319. X *    to those of the host system (for UNIX, this typically occurs for dates
  320. X *    beginning 2038 A.D. when the value rolls past the largest signed long
  321. X *    value in 32 bits).
  322. X *
  323. X * SEE ALSO
  324. X *
  325. X *    dayno() [ also by Thad Floryan ] which is part of a date-arithmetic
  326. X *        package in which dates and times are specially handled as
  327. X *        jdates and time fractions, respectively, and in which the time
  328. X *        rollover problem has been solved and validated in a machine-
  329. X *        independent fashion for years up to 9999 AD.
  330. X *
  331. X * AUTHOR
  332. X *
  333. X *    Thad Floryan [ thad@btr.com (OR) {decwrl, mips, fernwood} ]
  334. X *
  335. X * VERSION
  336. X *
  337. X *    1.0 12-Nov-1985 (original implementation)
  338. X *    2.0 sometime later (formatting cleanup, use of time_t instead of long)
  339. X *
  340. X * NOTES
  341. X *
  342. X *    The ADJ_* epoch adjusters represent the number of days between the
  343. X *    pseudo-date Jan. 1, 0000 and the date of the epoch.
  344. X */
  345. X
  346. X#include <sys/types.h>
  347. X
  348. X#define ADJ_UNIX    719527    /* adjuster for Jan. 1, 1970 epoch */
  349. X#define ADJ_AMIGA    722449    /* adjuster for Jan. 1, 1978 epoch */
  350. X
  351. X#ifdef AMIGA
  352. X#  define ADJ_DAY ADJ_AMIGA
  353. X#else
  354. X#  define ADJ_DAY ADJ_UNIX
  355. X#endif
  356. X
  357. Xshort mthvec[] = {-1,-1,30,58,89,119,150,180,211,242,272,303,333,364};
  358. X
  359. Xtime_t
  360. Xmksystime(year, month, day, hour, minute, second)
  361. X    int    year;
  362. X    int    month;
  363. X    int    day;
  364. X    int    hour;
  365. X    int    minute;
  366. X    int    second;
  367. X{
  368. X    int    quex;    /* Number of years excess of quad centuries */
  369. X    int    cent;    /* Number of years excess of centuries */
  370. X    int    leap;    /* Number of leap days since epoch Jan. 1, 0000 */
  371. X
  372. X    int    jdate;    /* pseudo-Julian date epoch Jan. 1, 0000 */
  373. X
  374. X/*
  375. X *    Filter out bad time values
  376. X */
  377. X    if (   ((hour   < 0) || (hour   > 23))
  378. X        || ((minute < 0) || (minute > 59))
  379. X        || ((second < 0) || (second > 59))) {
  380. X        return -1;
  381. X    }
  382. X/*
  383. X *    Perform main calculations
  384. X */
  385. X    quex = year % 400;
  386. X    cent = quex % 100;
  387. X    leap = (cent % 4) * 365;
  388. X
  389. X    jdate = day
  390. X        + (year / 400) * 146097
  391. X        + (quex / 100) *  36524
  392. X        + (cent /   4) *   1461
  393. X        + leap
  394. X        + mthvec[month];
  395. X/*
  396. X *    Adjust for months before March in non-leap years
  397. X */
  398. X    if ((month < 3) &&
  399. X            ((leap != 0 && quex == 0) ||
  400. X             (leap == 0 && (quex == 0 || cent != 0)))) {
  401. X        --jdate;
  402. X    }
  403. X/*
  404. X *    Compute return value referenced to requested epoch
  405. X */
  406. X    return ((jdate - ADJ_DAY) * 86400)
  407. X        + (hour * 3600)
  408. X        + (minute * 60)
  409. X        + second;
  410. X}
  411. SHAR_EOF
  412. chmod 0644 mksystime.c ||
  413. echo 'restore of mksystime.c failed'
  414. Wc_c="`wc -c < 'mksystime.c'`"
  415. test 3494 -eq "$Wc_c" ||
  416.     echo 'mksystime.c: original size 3494, current size' "$Wc_c"
  417. fi
  418. # ============= rhost_time.c ==============
  419. if test -f 'rhost_time.c' -a X"$1" != X"-c"; then
  420.     echo 'x - skipping rhost_time.c (File already exists)'
  421. else
  422. echo 'x - extracting rhost_time.c (Text)'
  423. sed 's/^X//' << 'SHAR_EOF' > 'rhost_time.c' &&
  424. X/****************************************************************************
  425. X *    RHOST_TIME                               RHOST_TIME
  426. X *
  427. X * NAME
  428. X *
  429. X *    rhost_time - gets current time_t value from a remote host adjusted
  430. X *             to UNIX-style time.
  431. X *
  432. X * SYNOPSIS
  433. X *
  434. X *    time_t rhost_time(hostname, errptr)
  435. X *
  436. X *    char *hostname, *errptr
  437. X *
  438. X * DESCRIPTION
  439. X *
  440. X *    Returns the UNIX-style time from a remote host's inetd server.  Note
  441. X *    the time returned by the inetd server is the number of seconds since
  442. X *    midnight, Jan 1, 1900, in a timeval structure.  Since gettimeofday()
  443. X *    returns the number of seconds since midnight, Jan 1, 1970, the value
  444. X *    2208988800 seconds was added to gettimeofday(2)'s returned value and
  445. X *    we have to make an adjustment to normal UNIX system time.  Note that
  446. X *    the tv_usec value will always be zero.  For compilers that cannot
  447. X *    handle such large numbers, 2208988800 is equivalent to 0x83AA7E80.
  448. X *
  449. X *    The returned value is compatible to that from time().  Note that since
  450. X *    we cannot assume we're running on a "real" computer whose byte order
  451. X *    is the same as network byte order, ntohl() is applied to the value
  452. X *    retrieved from the remote host to accomodate "little endian" machines
  453. X *    such as the DEC {VAX or Alpha} or Intel 80?86 platforms.
  454. X *
  455. X *    The hostname is a null-terminated string whose form may be anything
  456. X *    normally used to reach that host (i.e. "host" or "host.domain.com").
  457. X *
  458. X * RETURN VALUES
  459. X *
  460. X *    On successful completion, rhost_time() returns the time as documented
  461. X *    above.
  462. X *
  463. X *    On error, rhost_time() returns a -1, errno will be set, and a pointer
  464. X *    to the error string will be returned via *errptr.
  465. X *
  466. X * BUGS
  467. X *
  468. X *    The return value for the error message points to a static data area
  469. X *    whose content is potentially overwritten by each call to rhost_time.
  470. X *
  471. X * SEE ALSO
  472. X *
  473. X *    time(), stime()
  474. X *    
  475. X */
  476. X
  477. X#include <stdio.h>
  478. X#include <sys/types.h>
  479. X#include <sys/socket.h>
  480. X#include <sys/time.h>
  481. X#include <netinet/in.h>
  482. X#include <netdb.h>
  483. X#include <signal.h>
  484. X#include <setjmp.h>
  485. X#include <errno.h>
  486. X
  487. X#define SERVICE    "time"
  488. X#define TIMEOUT 10        /* seconds to wait for reply from rhost */
  489. X
  490. Xextern    char            *sys_errlist[];    /* system error strings */
  491. X
  492. X    jmp_buf             env;        /* used by timeout handler */
  493. X    char             errmsg[80];    /* text of error message */
  494. X
  495. Xtime_t
  496. Xrhost_time(hostname, errptr)
  497. X    char            *hostname;
  498. X    char               **errptr;
  499. X{
  500. X
  501. X    int             noanswer();
  502. X
  503. X    int             s;
  504. X    int             n;
  505. X    int             len;
  506. X    int             status;
  507. X    struct    timeval         rtimebuf;
  508. X    struct    hostent        *hp;
  509. X    struct    servent        *sp;
  510. X    struct    sockaddr_in     sin;
  511. X
  512. X/*
  513. X *    Get a datagram socket in the Internet domain
  514. X */
  515. X    s = socket(AF_INET, SOCK_DGRAM, 0);
  516. X    if (s < 0) {
  517. X        sprintf(errmsg, "socket: %s\n", sys_errlist[errno]);
  518. X        *errptr = errmsg;
  519. X        return -1;
  520. X    }
  521. X/*
  522. X *    Look up the port number of the service.
  523. X */
  524. X    sp = getservbyname(SERVICE, "udp");
  525. X    if (sp == NULL) {
  526. X        errno = EINVAL;
  527. X        sprintf(errmsg, "%s/udp: unknown service\n", SERVICE);
  528. X        *errptr = errmsg;
  529. X        close(s);
  530. X        return -1;
  531. X    }
  532. X/*
  533. X *    Look up the network number of the host on the command line
  534. X */
  535. X    hp = gethostbyname(hostname);
  536. X    if (hp == NULL) {
  537. X        errno = EINVAL;
  538. X        sprintf(errmsg, "%s: host unknown\n", hostname);
  539. X        *errptr = errmsg;
  540. X        close(s);
  541. X        return -1;
  542. X    }
  543. X/*
  544. X *    Build the address of the server on the remote machine
  545. X */
  546. X    sin.sin_family = AF_INET;
  547. X    sin.sin_port   = sp->s_port;
  548. X
  549. X    bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
  550. X/*
  551. X *    Send a datagram to the server
  552. X */
  553. X    status = sendto(s, &rtimebuf, sizeof(rtimebuf), 0, &sin, sizeof(sin));
  554. X    if (status < 0) {
  555. X        sprintf(errmsg, "sendto(%s): %s\n", hostname, sys_errlist[errno]);
  556. X        *errptr = errmsg;
  557. X        close(s);
  558. X        return -1;
  559. X    }
  560. X/*
  561. X *    Enable timeout signal in case remote host is dead
  562. X */
  563. X    signal(SIGALRM, noanswer);
  564. X    alarm(TIMEOUT);
  565. X/*
  566. X *    Test if we timed out waiting for remote host to respond; presume the
  567. X *    remote host is down if so.
  568. X */
  569. X    status = setjmp(env);
  570. X    if (status > 0) {
  571. X        errno = EHOSTDOWN;
  572. X        sprintf(errmsg, "timeout(%s): %s\n", hostname, sys_errlist[errno]);
  573. X        *errptr = errmsg;
  574. X        close(s);
  575. X        return -1;
  576. X    }
  577. X/*
  578. X *    Receive a datagram back
  579. X */
  580. X    len = sizeof(sin);
  581. X    n   = recvfrom(s, &rtimebuf, sizeof(rtimebuf), 0, &sin, &len);
  582. X/*
  583. X *    Disable timeout signal
  584. X */
  585. X    alarm(0);
  586. X/*
  587. X *    Test state of returned datagram
  588. X */
  589. X    if (n < 0) {
  590. X        sprintf(errmsg, "recvfrom(%s): %s", hostname, sys_errlist[errno]);
  591. X        *errptr = errmsg;
  592. X        close(s);
  593. X        return -1;
  594. X    }
  595. X/*
  596. X *    Accomodate "little endian" architectures.
  597. X */
  598. X    rtimebuf.tv_sec = ntohl(rtimebuf.tv_sec);
  599. X/*
  600. X *    Adjust time with respect to the UNIX epoch of Jan. 1, 1970 00:00:00 GMT
  601. X */
  602. X    rtimebuf.tv_sec -= 2208988800L;
  603. X/*
  604. X *    Release socket
  605. X */
  606. X    close(s);
  607. X
  608. X    return rtimebuf.tv_sec;
  609. X}
  610. X
  611. X/*
  612. X *    rhost_time() timeout handler
  613. X *
  614. X */
  615. Xnoanswer()
  616. X{
  617. X    longjmp(env, 1);
  618. X}
  619. SHAR_EOF
  620. chmod 0644 rhost_time.c ||
  621. echo 'restore of rhost_time.c failed'
  622. Wc_c="`wc -c < 'rhost_time.c'`"
  623. test 4772 -eq "$Wc_c" ||
  624.     echo 'rhost_time.c: original size 4772, current size' "$Wc_c"
  625. fi
  626. # ============= rsetclk.c ==============
  627. if test -f 'rsetclk.c' -a X"$1" != X"-c"; then
  628.     echo 'x - skipping rsetclk.c (File already exists)'
  629. else
  630. echo 'x - extracting rsetclk.c (Text)'
  631. sed 's/^X//' << 'SHAR_EOF' > 'rsetclk.c' &&
  632. X/******************************************************************************
  633. X *    RSETCLK                                RSETCLK
  634. X *
  635. X * NAME
  636. X *
  637. X *    rsetclk - sets the system's clocks referenced to a remote host
  638. X *
  639. X * SYNOPSIS
  640. X *
  641. X *    rsetclk [ -l logfile ]  [ -s ] hostname
  642. X *
  643. X * DESCRIPTION
  644. X *
  645. X *    Sets the 3B1's time-of-day and realtime clocks from another system
  646. X *    on the net per the "time" service.  Presently Ethernet is assumed.
  647. X *    Resolution is +/- 1 second; if more accuracy is needed (and on systems
  648. X *    which support it), the NTP facility should be used instead.
  649. X *
  650. X *    If the time drift exceeds 60 seconds, a warning will be issued and
  651. X *    the local time will NOT be changed; on the 3B1, a log message will
  652. X *    be sent to /dev/error informing of the condition.
  653. X *
  654. X *    All time values and variances will be displayed per the example:
  655. X *
  656. X *           Local RTC: Sun Apr  5 03:04:00 1992
  657. X *           Local TOD: Sun Apr  5 03:04:04 1992
  658. X *          Remote TOD: Sun Apr  5 03:03:57 1992  (hostname)
  659. X *        TOD Variance: 7 seconds
  660. X *
  661. X *    If the time was set, new time values will be retrieved and the display
  662. X *    will include the following (where "S" is "+", "-", or " " indicating
  663. X *    the directional adjustment performed):
  664. X *
  665. X *        ==Remote TOD: Sun Apr  5 03:03:57 1992  (hostname)
  666. X *        S= Local TOD: Sun Apr  5 03:03:57 1992
  667. X *        S= Local RTC: Sun Apr  5 03:03:57 1992
  668. X *
  669. X * OPTIONS
  670. X *
  671. X *    -l logfile    the logfile name is used here ONLY for inclusion
  672. X *            in error messages sent to /dev/error.  The actual
  673. X *            logging is controlled by directing stdout and stderr
  674. X *            in the invoking script per (for example):
  675. X *
  676. X *            rsetclk -l $LOGFILE -s rhost 1>> $LOGFILE 2>&1
  677. X *
  678. X *    -s        causes the time-of-day (TOD) clock (and RTC) to be
  679. X *            set to the value received from hostname.
  680. X *
  681. X * AUTHOR
  682. X *
  683. X *    Thad Floryan, 5-Apr-1992 [ thad@btr.com ]
  684. X *
  685. X * NOTES
  686. X *
  687. X *    The program must be setuid root to change the system's clocks.
  688. X *
  689. X *    Clobbered-registers in an onboard RTC will cause strange displays
  690. X *    for the RTC time; this effect could be fixed in mksystime().
  691. X */
  692. X
  693. X#include <stdio.h>
  694. X#include <time.h>
  695. X#include <sys/types.h>
  696. X
  697. X#define VERSKIP    4        /* print displacement in version string    */
  698. X
  699. X#define ABS(x) ((x) >= 0 ? (x) : -(x))
  700. X
  701. Xchar *version =
  702. X    "@(#)rsetclk V1.0, 5-Mar-1992, Thad Floryan [ thad@btr.com ]";
  703. X
  704. Xchar *usage_text[] = {
  705. X    "usage:    rsetclk [-l logfile] [-s] from_host",
  706. X    0
  707. X};
  708. X
  709. Xchar *logfile = "/dev/tty";    /* default name in case "-l logfile" missing */
  710. X
  711. X
  712. Xmain(argc, argv)
  713. X    int         argc;
  714. X    char        *argv[];
  715. X{
  716. Xextern    int         getopt();
  717. Xextern    int         optind;
  718. Xextern    char        *optarg;
  719. X
  720. Xextern    time_t         mksystime();
  721. Xextern    time_t         rhost_time();
  722. Xextern    int         rtc_stime();
  723. Xextern    time_t         rtc_time();
  724. X
  725. X    FILE        *ef;
  726. X    struct tm    *tm_ptr;
  727. X    long         delta;        /* local vs. remote clock delta */
  728. X    long         drift;        /* local vs. remote clock drift */
  729. X    time_t         lcltime;    /* local system's time */
  730. X    time_t         remtime;    /* remote system's time */
  731. X    time_t         rtctime;    /* RTC time */
  732. X    int         optchr;
  733. X    int         setflg = 0;    /* non-zero means actually set time */
  734. X    char         direction;    /* '+', '-' or ' ' */
  735. X    char        *errstr;
  736. X
  737. X
  738. X/*
  739. X *    Process command line argument(s)
  740. X */
  741. X    while ((optchr = getopt(argc, argv, "l:s")) != EOF) {
  742. X        switch (optchr) {
  743. X        case 'l':   logfile = optarg;
  744. X                break;
  745. X        case 's':   setflg++;
  746. X                break;
  747. X        default:    usage();
  748. X        }
  749. X    }
  750. X
  751. X    if ( optind != (argc - 1)) {
  752. X        usage();
  753. X    }
  754. X/*
  755. X *    Get UNIX-style time from remote host and handle any errors
  756. X */
  757. X    remtime = rhost_time(argv[optind], &errstr);
  758. X    if (remtime < 0) {
  759. X        fprintf(stderr, errstr);
  760. X
  761. X#ifdef UNIXPC
  762. X        if (setflg != 0) {
  763. X        ef = fopen("/dev/error", "w");
  764. X        if (ef != NULL) {
  765. X            fprintf(ef, "%s failure with rhost_time()\n", argv[0]);
  766. X            fprintf(ef, "between localhost and %s\n", argv[optind]);
  767. X            fprintf(ef, "See %s for more details.\n", logfile);
  768. X        }
  769. X        fclose(ef);
  770. X        }
  771. X#endif /* UNIXPC */
  772. X
  773. X        exit(1);
  774. X    }
  775. X/*
  776. X *    Get UNIX-style local time from local host
  777. X */
  778. X    lcltime = time((time_t *) 0);
  779. X/*
  780. X *    Get UNIX-style local time from Real Time Clock
  781. X */
  782. X    rtctime = rtc_time((time_t *) 0);
  783. X/*
  784. X *    Compute time variance
  785. X */
  786. X    delta = lcltime - remtime;
  787. X    drift = ABS(delta);
  788. X/*
  789. X *    Check if we're actually setting the time
  790. X */
  791. X    if (setflg != 0) {
  792. X/*
  793. X *    Check for excessive time drift ( >= 60 seconds )
  794. X */
  795. X        if ( drift >= 60 ) {
  796. X        fprintf(stderr, "WARNING: Excessive time drift, %ld seconds\n",
  797. X            drift);
  798. X        setflg = 0;
  799. X#ifdef UNIXPC
  800. X        ef = fopen("/dev/error", "w");
  801. X        if (ef != NULL) {
  802. X            fprintf(ef, "Excessive time drift (%ld seconds)\n", drift);
  803. X            fprintf(ef, "between localhost and %s\n", argv[optind]);
  804. X            fprintf(ef, "See %s for more details.\n", logfile);
  805. X        }
  806. X        fclose(ef);
  807. X#endif /* UNIXPC */
  808. X
  809. X        } else {
  810. X/*
  811. X *    Set UID to root so we can change the system's clocks
  812. X */
  813. X        if (setuid(0) < 0) {
  814. X            perror("setuid");
  815. X            exit(1);
  816. X        }
  817. X/*
  818. X *    Set current time
  819. X */
  820. X        if (stime(&remtime) != 0) {
  821. X            perror("stime");
  822. X            exit(1);
  823. X        }
  824. X        rtc_stime(&remtime);
  825. X        }
  826. X    }
  827. X/*
  828. X *    Display pertinent times
  829. X */
  830. X    tm_ptr = gmtime(&rtctime);
  831. X    printf("   Local RTC: %s", asctime(tm_ptr));
  832. X
  833. X    tm_ptr = localtime(&lcltime);
  834. X    printf("   Local TOD: %s", asctime(tm_ptr));
  835. X
  836. X    tm_ptr = localtime(&remtime);
  837. X    printf("  Remote TOD: %24.24s  (%s)\n", asctime(tm_ptr), argv[optind]);
  838. X
  839. X    printf("TOD Variance: %ld seconds\n", delta);
  840. X/*
  841. X *    Display verification of changes
  842. X */
  843. X    if (setflg != 0) {
  844. X        direction = (delta >= 0) ? ((delta > 0) ? '-' : ' ') : '+';
  845. X
  846. X        remtime = rhost_time(argv[optind], &errstr);
  847. X        if (remtime < 0) {
  848. X        fprintf(stderr, errstr);
  849. X        exit(1);
  850. X        } else {
  851. X        tm_ptr = localtime(&remtime);
  852. X        printf("==Remote TOD: %24.24s  (%s)\n",
  853. X            asctime(tm_ptr),
  854. X            argv[optind]);
  855. X        }
  856. X
  857. X        lcltime = time((time_t *) 0);
  858. X        tm_ptr = localtime(&lcltime);
  859. X        printf("%c= Local TOD: %s", direction, asctime(tm_ptr));
  860. X
  861. X        rtctime = rtc_time((time_t *) 0);
  862. X        tm_ptr = gmtime(&rtctime);
  863. X        printf("%c= Local RTC: %s", direction, asctime(tm_ptr));
  864. X    }
  865. X
  866. X    return 0;
  867. X}
  868. X
  869. X/********************************************************************
  870. X *    USAGE                            USAGE
  871. X *
  872. X *    Display program's usage
  873. X */
  874. X
  875. Xusage()
  876. X{
  877. X    int    ndx = 0;
  878. X
  879. X    while ( usage_text[ndx] != 0 ) {
  880. X
  881. X        (void) fprintf( stderr, "%s\n", usage_text[ndx++] );
  882. X    }
  883. X    (void) fprintf( stderr, "%s\n", version + VERSKIP );
  884. X    exit(1);
  885. X}
  886. SHAR_EOF
  887. chmod 0644 rsetclk.c ||
  888. echo 'restore of rsetclk.c failed'
  889. Wc_c="`wc -c < 'rsetclk.c'`"
  890. test 6203 -eq "$Wc_c" ||
  891.     echo 'rsetclk.c: original size 6203, current size' "$Wc_c"
  892. fi
  893. # ============= rtc_stime.c ==============
  894. if test -f 'rtc_stime.c' -a X"$1" != X"-c"; then
  895.     echo 'x - skipping rtc_stime.c (File already exists)'
  896. else
  897. echo 'x - extracting rtc_stime.c (Text)'
  898. sed 's/^X//' << 'SHAR_EOF' > 'rtc_stime.c' &&
  899. X/*************************************************************************
  900. X *    RTC_STIME                         RTC_STIME
  901. X *
  902. X * NAME
  903. X *
  904. X *    rtc_stime -- sets the battery-backed Real Time Clock in the UNIXPC
  905. X *             to the UNIX-style time given as input
  906. X *
  907. X * SYNOPSIS
  908. X *
  909. X *    rtc_stime(tval)
  910. X *
  911. X *    time_t *tval
  912. X *
  913. X * DESCRIPTION
  914. X *
  915. X *    Sets the RTC's registers to the given time.
  916. X *
  917. X *    On the 3B1, the RTC's registers contain local time.  Thus, the time_t
  918. X *    value should be treated as "gmtime(2)" for any conversions to ASCII.
  919. X *
  920. X *    For many RTCs, problems will occur come 2000 AD because the stored
  921. X *    year comprises only the ones and tens digits, not the century.
  922. X *
  923. X *    Note that on the 3B1, the stock /etc/clockupd.wk script documents why
  924. X *    the RTC is set to the present "software" time at 3:03am each Sunday: to
  925. X *    synchronize the clocks in case of Daylight Savings Time adjustments.
  926. X *    The RTC setting is accomplished by:  date `date +%m%d%H%M`
  927. X *
  928. X * SEE ALSO
  929. X *
  930. X *    time(), stime(), rtc_time()
  931. X *
  932. X */
  933. X
  934. X#include <time.h>
  935. X#include <sys/types.h>
  936. X
  937. X#ifdef UNIXPC
  938. X#include <sys/syslocal.h>
  939. X#include <sys/rtc.h>
  940. X#endif
  941. X
  942. Xrtc_stime(tval)
  943. X    time_t        *tval;
  944. X{
  945. X
  946. X#ifdef UNIXPC
  947. X
  948. X    struct tm    *p_tm;
  949. X    struct rtc     rtc_val;
  950. X
  951. X    p_tm = localtime(tval);
  952. X
  953. X    rtc_val.wkday = p_tm->tm_wday;
  954. X    rtc_val.yr10  = p_tm->tm_year / 10;
  955. X    rtc_val.yr1   = p_tm->tm_year % 10;
  956. X    rtc_val.mon10 = (p_tm->tm_mon + 1) / 10;
  957. X    rtc_val.mon1  = (p_tm->tm_mon + 1) % 10;
  958. X    rtc_val.day10 = p_tm->tm_mday / 10;
  959. X    rtc_val.day1  = p_tm->tm_mday % 10;
  960. X    rtc_val.hr10  = p_tm->tm_hour / 10;
  961. X    rtc_val.hr1   = p_tm->tm_hour % 10;
  962. X    rtc_val.min10 = p_tm->tm_min / 10;
  963. X    rtc_val.min1  = p_tm->tm_min % 10;
  964. X    rtc_val.sec10 = p_tm->tm_sec / 10;
  965. X    rtc_val.sec1  = p_tm->tm_sec % 10;
  966. X
  967. X    syslocal(SYSL_WRTRTC, &rtc_val);    /* write and update RTC */
  968. X
  969. X#endif /* UNIXPC */
  970. X
  971. X}
  972. SHAR_EOF
  973. chmod 0644 rtc_stime.c ||
  974. echo 'restore of rtc_stime.c failed'
  975. Wc_c="`wc -c < 'rtc_stime.c'`"
  976. test 1784 -eq "$Wc_c" ||
  977.     echo 'rtc_stime.c: original size 1784, current size' "$Wc_c"
  978. fi
  979. # ============= rtc_time.c ==============
  980. if test -f 'rtc_time.c' -a X"$1" != X"-c"; then
  981.     echo 'x - skipping rtc_time.c (File already exists)'
  982. else
  983. echo 'x - extracting rtc_time.c (Text)'
  984. sed 's/^X//' << 'SHAR_EOF' > 'rtc_time.c' &&
  985. X/***********************************************************************
  986. X *    RTC_TIME                        RTC_TIME
  987. X *
  988. X * NAME
  989. X *
  990. X *    rtc_time -- gets time from system's Real Time Clock (RTC)
  991. X *
  992. X * SYNOPSIS
  993. X *
  994. X *    time_t rtc_time((time_t *) 0)
  995. X *
  996. X *    time_t rtc_time(tloc)
  997. X *    time_t *tloc
  998. X *
  999. X * DESCRIPTION
  1000. X *
  1001. X *    rtc_time() returns the value of time in seconds since the epoch;
  1002. X *    on UNIX systems, the epoch is January 1, 1970 00:00:00 GMT
  1003. X *
  1004. X *    If tloc is non-zero, the returned value is also stored in the location
  1005. X *    to which tloc points.
  1006. X *
  1007. X *    rtc_time() will fail if tloc points to an illegal address.
  1008. X *
  1009. X *    For many RTCs, problems will occur come 2000 AD because the stored
  1010. X *    year comprises only the ones and tens digits, not the century.
  1011. X *
  1012. X *    On the 3B1, the RTC's registers contain local time.  Thus, the time_t
  1013. X *    value should be treated as "gmtime(2)" for any conversions to ASCII.
  1014. X *
  1015. X *    On the 3B1, the stock /etc/clockupd.wk script documents why the RTC
  1016. X *    is set to the present "software" time at 3:03am each Sunday: to
  1017. X *    synchronize the clocks in case of Daylight Savings Time adjustments.
  1018. X *    The RTC setting is accomplished by:  date `date +%m%d%H%M`
  1019. X *
  1020. X * RETURN VALUE
  1021. X *
  1022. X *    Upon successful completion, rtc_time() returns the value of the RTC's
  1023. X *    time.  Otherwise a value of -1 is returned and errno is set to indicate
  1024. X *    the error.
  1025. X *
  1026. X * SEE ALSO
  1027. X *
  1028. X *    time(), stime(), rtc_stime()
  1029. X *
  1030. X */
  1031. X
  1032. X#include <errno.h>
  1033. X#include <time.h>
  1034. X#include <sys/types.h>
  1035. X
  1036. X#ifdef UNIXPC
  1037. X#include <sys/syslocal.h>
  1038. X#include <sys/rtc.h>
  1039. X#endif
  1040. X
  1041. Xtime_t
  1042. Xrtc_time(tloc)
  1043. X    time_t        *tloc;
  1044. X{
  1045. Xextern    time_t         mksystime();
  1046. X
  1047. X    time_t         curtime = 0;
  1048. X
  1049. X#ifdef UNIXPC
  1050. X
  1051. X    struct rtc    rtc_val;
  1052. X
  1053. X
  1054. X    syslocal(SYSL_RDRTC, &rtc_val);        /* read RTC */
  1055. X
  1056. X    curtime = mksystime(
  1057. X            (rtc_val.yr10  * 10) + rtc_val.yr1  + 1900,
  1058. X            (rtc_val.mon10 * 10) + rtc_val.mon1,
  1059. X            (rtc_val.day10 * 10) + rtc_val.day1,
  1060. X            (rtc_val.hr10  * 10) + rtc_val.hr1,
  1061. X            (rtc_val.min10 * 10) + rtc_val.min1,
  1062. X            (rtc_val.sec10 * 10) + rtc_val.sec1);
  1063. X
  1064. X    if (curtime < 0) {
  1065. X        errno = EINVAL;
  1066. X    }
  1067. X
  1068. X#endif /* UNIXPC */
  1069. X
  1070. X    if (tloc != (time_t *) 0) {
  1071. X        *tloc = curtime;
  1072. X    }
  1073. X
  1074. X    return curtime;
  1075. X
  1076. X}
  1077. SHAR_EOF
  1078. chmod 0644 rtc_time.c ||
  1079. echo 'restore of rtc_time.c failed'
  1080. Wc_c="`wc -c < 'rtc_time.c'`"
  1081. test 2111 -eq "$Wc_c" ||
  1082.     echo 'rtc_time.c: original size 2111, current size' "$Wc_c"
  1083. fi
  1084. exit 0
  1085.  
  1086. -- 
  1087. David H. Brierley
  1088. Home: dave@galaxia.network23.com; Work: dhb@quahog.ssd.ray.com
  1089. Send comp.sources.3b1 submissions to comp-sources-3b1@galaxia.network23.com
  1090. %% Can I be excused, my brain is full. **
  1091.