home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2424 < prev    next >
Encoding:
Internet Message Format  |  1990-12-29  |  29.2 KB

  1. From: wht@n4hgf.Mt-Park.GA.US (Warren Tucker)
  2. Newsgroups: alt.sources
  3. Subject: cmostime3 part 01/02 (was Re: Program to set clock to NBS time)
  4. Message-ID: <276@n4hgf.Mt-Park.GA.US>
  5. Date: 29 Dec 90 03:08:06 GMT
  6.  
  7. As it went out to comp.sources.misc a while back,
  8. the much nicer cmostime; replaces nbs_time, which had a life of six days,
  9. but doesn't seem to want to die :-)
  10.  
  11. Two parts.
  12.  
  13. ---- Cut Here and unpack ----
  14. #!/bin/sh
  15. # This is cmostime3, a shell archive (shar 3.04)
  16. # made 01/17/1990 06:14 UTC by gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu)
  17. # Source directory /u1/src/cmos
  18. #
  19. # existing files WILL be overwritten
  20. #
  21. # This is part 1 of a multipart archive                                    
  22. # do not concatenate these parts, unpack them in order with /bin/sh        
  23. #
  24. # This shar contains:
  25. #    MANIFEST
  26. #    README
  27. #    Makefile
  28. #    CMOSstime.c
  29. #    NBSsetclk.c
  30. #    at_cmos.h
  31. #    cmos_disp.c
  32. #    dev_cmos.c
  33. #    dev_cmos.h
  34. #    set_24hr.c
  35. #
  36. touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
  37. if [ -s /tmp/s3_touch$$ ]
  38. then
  39.     TOUCH=can
  40. else
  41.     TOUCH=cannot
  42. fi
  43. rm -f /tmp/s3_touch$$
  44. if test -r s3_seq_.tmp
  45. then echo "Must unpack archives in sequence!"
  46.      next=`cat s3_seq_.tmp`; echo "Please unpack part $next next"
  47.      exit 1; fi
  48. echo "x - extracting MANIFEST (Text)"
  49. sed 's/^X//' << 'SHAR_EOF' > MANIFEST &&
  50. X-rw-r--r--   1 wht      wht         3601 Jan  5 20:52 CMOSstime.c
  51. X-rw-r--r--   1 wht      wht         1418 Jan  5 20:56 Makefile
  52. X-rw-r--r--   1 wht      wht        24170 Jan  5 20:53 NBSsetclk.c
  53. X-rw-r--r--   1 wht      wht         3793 Jan  5 20:56 README
  54. X-rw-r--r--   1 wht      wht         3746 Jan  5 20:53 at_cmos.h
  55. X-rw-r--r--   1 wht      wht         3964 Jan  5 20:53 cmos_disp.c
  56. X-rw-r--r--   1 wht      wht         4600 Jan  5 20:54 dev_cmos.c
  57. X-rw-r--r--   1 wht      wht          661 Jan  5 20:54 dev_cmos.h
  58. X-rw-r--r--   1 wht      wht         1250 Jan  5 20:55 set_24hr.c
  59. SHAR_EOF
  60. chmod 0644 MANIFEST || echo "restore of MANIFEST fails"
  61. if [ $TOUCH = can ]
  62. then
  63.     touch -m 0117011490 MANIFEST
  64. fi
  65. echo "x - extracting README (Text)"
  66. sed 's/^X//' << 'SHAR_EOF' > README &&
  67. Xcmostime3 AT CMOS RAM TIME UTILITIES FOR SCO UNIX AND XENIX V/286&386
  68. X...gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu) - Wed Dec 27 1989
  69. X
  70. XOverview
  71. X---------------------------------------------------------------------
  72. XSCO UNIX and XENIX supports the AT cmos ram with two devices (/dev/cmos,
  73. X/dev/clock), programs /etc/setclock and /lib/cvtdate and a shell script
  74. X/etc/asktime.  However, there is no way to set the system time or the
  75. Xcmos clock ACCURATELY using these tools since seconds are not in the
  76. Xparadigm of setclock or /dev/clock.  One can, however, set the cmos
  77. Xclock accurately by the direct manipulation of /dev/cmos.  By reading
  78. X/dev/cmos, one can get the correct time and set the system time with
  79. Xstime(S).
  80. X
  81. XThis collection of UNIX/XENIX V programs allows you to:
  82. X
  83. X1) set the AT cmos clock and system time very accurately by calling
  84. X   the Naval Observatory ((202)653-0351 in DC) using NBSsetclk,
  85. X
  86. X2) set the system clock from the (somewhat drifty) cmos clock
  87. X   by using CMOSstime,
  88. X
  89. X3) display "interesting" things in the cmos ram by using cmos_disp.
  90. X
  91. XThese programs have been proven to work on the Compaq Deskpro 286
  92. Xand 386 using SCO XENIX/286 2.2.1 and XENIX/386 2.3.1.
  93. X
  94. XNBSsetclk
  95. X---------------------------------------------------------------------
  96. XNBSsetclk assumes a Hayes modem is connected to the line and that
  97. Xcommand recognition is enabled.  /dev/tty1a is used by default.  The
  98. Xprogram tries up to 40 times (40 seconds) to read the time, making it
  99. Xlikely that you will succeed.  However, the program will terminate
  100. Xbefore the minimum 1 minute connect charge has expired.  NBSsetclk MUST
  101. Xbe run by root.  Why waste a long distance call only to have stime()
  102. Xfail?  Most users will use the default parameters of this program by
  103. Xinvoking it with
  104. X    NBSsetclk -
  105. XRunning the program with no parameters gives you the options available.
  106. X
  107. XExit status codes for the NBSsetclk:
  108. X1-n  signal values if program killed
  109. X200  illogical cmos device behavior (when reading clock)
  110. X249  stime() call failed
  111. X250  could not open communications line
  112. X251  /dev/cmos read&write access denied
  113. X252  user is not root
  114. X253  usage
  115. X254  couldn't get time from line (after 40 retries! BAD line conditions)
  116. X255  couldn't establish a connection
  117. X
  118. XCMOSstime
  119. X---------------------------------------------------------------------
  120. XCMOStime reads the cmos clock and sets the system time to the second.
  121. XRun it in your /etc/rc in place of the rather klunky 'asktime'.  The
  122. Xprogram returns exit status 0 if it succeeds, 1 for most failures
  123. X(stime() failure or /dev/cmos read access failure), or 200 for the rare
  124. Xcases where the cmos device appears to be acting up.
  125. X
  126. Xcmos_disp
  127. X---------------------------------------------------------------------
  128. XThis is an experimental program that displays information contained
  129. Xin the cmos ram.  It has some bugs in it (on my systems, it reports
  130. Xno floppy drives, when I in fact have one).  The information used to
  131. Xbuild the program came from the sketchy notes in the IBM AT Technical
  132. XReference Manual.  Look in header file 'at_cmos.h' and source file
  133. X'cmos_disp.c' for notes I have made about empirical "discoveries".
  134. XThere are certainly some discrepancies, particularly on machines
  135. Xother than the IBM AT.
  136. X
  137. Xset_24hr.c
  138. X---------------------------------------------------------------------
  139. XOnce or twice during a power main glitch, the 24-hour mode bit got
  140. Xreset.  This program sets the bit.
  141. X
  142. XAcknowlegments
  143. X---------------------------------------------------------------------
  144. XThe routines for converting mm/dd/yy hh:mm:ss to seconds since
  145. Xthe epoch were adapted from the 'tm_to_time.c' module in Emmet P.
  146. XGray's conversion of arc to unix.
  147. X
  148. XThe concepts of parsing the Naval Observatory data stream came from
  149. Xan anonymous author's nbs.c (which read the data stream from stdin).
  150. SHAR_EOF
  151. chmod 0644 README || echo "restore of README fails"
  152. if [ $TOUCH = can ]
  153. then
  154.     touch -m 0105205690 README
  155. fi
  156. echo "x - extracting Makefile (Text)"
  157. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  158. X#  CHK=0xDF23
  159. X# Makefile for cmos/rtc programs
  160. X#+:EDITS:
  161. X#:02-03-1989-19:46-wht-386 release
  162. X
  163. XSHELL = /bin/sh
  164. X
  165. X.SUFFIXES:
  166. X.SUFFIXES: .o .c .h  
  167. X
  168. XC_LD_COMMON = -i -s
  169. XCFLAGS  = -c -O -K $(C_LD_COMMON)
  170. XLIB = -lx
  171. X#.c.o:;    fcrc -u $*.c ; $(CC) $(CFLAGS) $*.c 
  172. X
  173. XNBSSETCLK_OFILES = \
  174. X    NBSsetclk.o\
  175. X    dev_cmos.o
  176. X
  177. XCMOSSTIME_OFILES = \
  178. X    CMOSstime.o\
  179. X    dev_cmos.o
  180. X
  181. XCMOS_DISP_OFILES = \
  182. X    cmos_disp.o\
  183. X    dev_cmos.o
  184. X
  185. XS24H_DISP_OFILES = \
  186. X    set_24hr.o\
  187. X    dev_cmos.o
  188. X
  189. XSHAR_FILES = \
  190. X    README\
  191. X    Makefile\
  192. X    CMOSstime.c\
  193. X    NBSsetclk.c\
  194. X    at_cmos.h\
  195. X    cmos_disp.c\
  196. X    dev_cmos.c\
  197. X    dev_cmos.h\
  198. X    set_24hr.c
  199. X
  200. Xall: NBSsetclk CMOSstime cmos_disp
  201. X
  202. XNBSsetclk: $(NBSSETCLK_OFILES)
  203. X    $(CC) $(C_LD_COMMON) $(NBSSETCLK_OFILES) $(LIB) -o $@
  204. X
  205. XCMOSstime: $(CMOSSTIME_OFILES)
  206. X    $(CC) $(C_LD_COMMON) $(CMOSSTIME_OFILES) $(LIB) -o $@
  207. X
  208. Xcmos_disp: $(CMOS_DISP_OFILES)
  209. X    $(CC) $(C_LD_COMMON) $(CMOS_DISP_OFILES) $(LIB) -o $@
  210. X
  211. Xset_24hr: $(S24H_DISP_OFILES)
  212. X    $(CC) $(C_LD_COMMON) $(S24H_DISP_OFILES) $(LIB) -o $@
  213. X
  214. Xshar:
  215. X    ls -l $(SHAR_FILES) > MANIFEST
  216. X    shar -c -ncmostime3 -l30 -ocmostime3. MANIFEST $(SHAR_FILES)
  217. X
  218. Xclean:
  219. X    -rm -f *.o
  220. X
  221. Xclobber: clean
  222. X    rm -f NBSsetclk CMOSstime cmos_disp set_24hr \
  223. X        cmostime.sh.1 cmostime.sh.2 MANIFEST
  224. X
  225. XMANIFEST: $(SHAR1_FILES) $(SHAR2_FILES)
  226. X    echo 'List of files in cmostime.sh.{1,2}' > MANIFEST
  227. X    ls -l $(SHAR1_FILES) $(SHAR2_FILES) > MANIFEST
  228. X
  229. XNBS_setclk.o: at_cmos.h dev_cmos.h
  230. X
  231. XCMOSstime.o: dev_cmos.h
  232. X
  233. Xcmos_disp.o: at_cmos.h dev_cmos.h
  234. SHAR_EOF
  235. chmod 0644 Makefile || echo "restore of Makefile fails"
  236. if [ $TOUCH = can ]
  237. then
  238.     touch -m 0105205690 Makefile
  239. fi
  240. echo "x - extracting CMOSstime.c (Text)"
  241. sed 's/^X//' << 'SHAR_EOF' > CMOSstime.c &&
  242. X/* CHK=0xFC70 */
  243. X/* vi: set tabstop=4 shiftwidth=4: */
  244. X/*+-------------------------------------------------------------------------
  245. X    CMOSstime.c -- read cmos clock then stime()
  246. X    ...!gatech!kd4nc!n4hgf!wht
  247. X
  248. X  Defined functions:
  249. X    date_to_epochsecs(year,month,day,hour,min,sec)
  250. X    days_since_epoch(year,month,day)
  251. X    leap_year(yr)
  252. X    main(argc,argv,envp)
  253. X
  254. X--------------------------------------------------------------------------*/
  255. X/*+:EDITS:*/
  256. X/*:12-04-1989-20:14-wht-support UNIX 3.2 */
  257. X/*:02-03-1989-19:50-wht-386 release */
  258. X/*:07-23-1988-18:59-wht-release */
  259. X/*:07-22-1988-19:34-wht-creation */
  260. X
  261. X#include <stdio.h>
  262. X#include <fcntl.h>
  263. X#include <sys/types.h>
  264. X#include <time.h>
  265. X
  266. X#include "dev_cmos.h"
  267. X
  268. Xint leap_year(int );
  269. Xint days_since_epoch(int ,int ,int );
  270. Xlong date_to_epochsecs(int ,int ,int ,int ,int ,int );
  271. X
  272. Xchar *ctime();
  273. Xint stime(long *);
  274. Xlong time(long *);
  275. X
  276. Xchar *cmos = "/dev/cmos";
  277. X
  278. X/*+-------------------------------------------------------------------------
  279. X    leap_year(yr) -- returns 1 if leap year, 0 otherwise 
  280. X--------------------------------------------------------------------------*/
  281. Xint
  282. Xleap_year(yr)
  283. Xint yr;
  284. X{
  285. X    return((yr % 4 == 0) && (yr % 100 != 0) || (yr % 400 == 0));
  286. X}    /* end of leap_year */
  287. X
  288. X/*+-------------------------------------------------------------------------
  289. X    days_since_epoch(year,month,day)
  290. XReturn the number of days between Jan 1, 1970 and year,month,day
  291. Xyear is full year (e.g., 1988)
  292. Xmonth is 0-11
  293. Xday is 0-30 (must be legal day in month)
  294. X--------------------------------------------------------------------------*/
  295. Xint
  296. Xdays_since_epoch(year,month,day)
  297. Xint year;
  298. Xint month;
  299. Xregister int day;
  300. X{
  301. Xregister int mm;
  302. Xregister int yy;
  303. Xstatic char days_per_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  304. X
  305. X    day++;            /* adjust for day 0-n instead of 1-n */
  306. X
  307. X    for(yy = 1970; yy < year; ++yy) 
  308. X    {
  309. X        day += 365;
  310. X        if(leap_year(yy))
  311. X            day++;
  312. X    }
  313. X    for(mm = 0; mm < month; ++mm)
  314. X        day += days_per_month[mm] + (mm == 1 && leap_year(yy));
  315. X
  316. X    return(day);
  317. X
  318. X}    /* end of days_since_epoch */
  319. X
  320. X/*+-------------------------------------------------------------------------
  321. X    date_to_epochsecs(year,month,day,hour,min,sec)
  322. XConvert arguments into long seconds since 1/1/1970
  323. Xyear is full year (e.g., 1988)
  324. Xmonth is 0-11
  325. Xday is 0-30 (must be legal day in month)
  326. Xhour is 0-23, min and sec 0-59
  327. X--------------------------------------------------------------------------*/
  328. Xlong
  329. Xdate_to_epochsecs(year,month,day,hour,min,sec)
  330. Xint year;
  331. Xint month;
  332. Xint day;
  333. Xint hour;
  334. Xint min;
  335. Xint sec;
  336. X{
  337. Xregister int m1;
  338. Xregister int m2;
  339. Xlong t;
  340. Xstruct tm *tp;
  341. Xstruct tm *localtime();
  342. X
  343. X    t = (days_since_epoch(year,month,day) - 1) * 86400L
  344. X        + (hour * 3600L) + (min * 60L) + sec;
  345. X#if !defined(M_UNIX)
  346. X    /* correct for the time zone */
  347. X    tp = localtime(&t);
  348. X    m1 = tp->tm_hour * 60 + tp->tm_min;
  349. X    m2 = (hour * 60) + min;
  350. X    t -= ((m1 - m2 + 720 + 1440) % 1440 - 720) * 60L;
  351. X#endif
  352. X
  353. X    return(t);
  354. X
  355. X}    /* end of date_to_epochsecs */
  356. X
  357. X/*+-------------------------------------------------------------------------
  358. X    main(argc,argv,envp)
  359. X--------------------------------------------------------------------------*/
  360. Xmain(argc,argv,envp)
  361. Xint argc;
  362. Xchar **argv;
  363. Xchar **envp;
  364. X{
  365. Xint year,month,day,hour,min,sec;
  366. Xint fdcmos;
  367. Xlong now;
  368. X
  369. X    setbuf(stdout,NULL);
  370. X    setbuf(stderr,NULL);
  371. X
  372. X    if((fdcmos = open(cmos,O_RDONLY)) < 0)
  373. X    {
  374. X        perror(cmos);
  375. X        exit(1);
  376. X    }
  377. X
  378. X    get_clock(fdcmos,&year,&month,&day,&hour,&min,&sec);
  379. X    now = date_to_epochsecs(year,month,day,hour,min,sec);
  380. X    if(stime(&now))
  381. X    {
  382. X        perror("stime");
  383. X        exit(1);
  384. X    }
  385. X    time(&now);
  386. X    fputs("System time after stime(): ",stdout);
  387. X    fputs(ctime(&now),stdout);
  388. X
  389. X    exit(0);
  390. X}    /* end of main */
  391. SHAR_EOF
  392. chmod 0644 CMOSstime.c || echo "restore of CMOSstime.c fails"
  393. if [ $TOUCH = can ]
  394. then
  395.     touch -m 0105205290 CMOSstime.c
  396. fi
  397. echo "x - extracting NBSsetclk.c (Text)"
  398. sed 's/^X//' << 'SHAR_EOF' > NBSsetclk.c &&
  399. X/* CHK=0x9B09 */
  400. X/* vi: set tabstop=4 shiftwidth=4: */
  401. X/*+-----------------------------------------------------------------------
  402. X  NBSsetclk.c -- call NBS, get time, hangup QUICKly, set system time,
  403. X                 update cmos clock (/dev/cmos)
  404. X    ...!gatech!kd4nc!n4hgf!wht
  405. X
  406. X  Defined functions:
  407. X    create_lock_file(lock_file_name)
  408. X    hangup(sig)
  409. X    hayes_dial()
  410. X    hayes_modem_init(cmd)
  411. X    hayes_send_cmd(cmd)
  412. X    lclose()
  413. X    lgetc(char_rtnd)
  414. X    lgetc_timeout(timeout_msec)
  415. X    lgets_timeout(lrwt)
  416. X    lkill_buf()
  417. X    lock_tty()
  418. X    lopen()
  419. X    lputc(lchar)
  420. X    lputs_paced(pace_msec,string)
  421. X    lset_baud_rate(ioctl_flag)
  422. X    lset_parity(ioctl_flag)
  423. X    main(argc,argv,envp)
  424. X    make_lock_name(ttyname,lock_file_name)
  425. X    other_lock_name(first_lock_name)
  426. X    unlock_tty()
  427. X    usage()
  428. X    valid_baud_rate(baud)
  429. X
  430. X  Note: must be root to execute
  431. X
  432. X  Exit status codes for the program:
  433. X  1-n  signal values if program killed
  434. X  200  illogical cmos device behavior (when reading clock)
  435. X  249  stime() call failed
  436. X  250  could not open communications line
  437. X  251  /dev/cmos read&write access denied
  438. X  252  user is not root
  439. X  253  usage
  440. X  254  couldn't get time from line (after 40 retries! BAD line conditions)
  441. X  255  could not establish a connection or line error
  442. X
  443. X------------------------------------------------------------------------*/
  444. X/*+:EDITS:*/
  445. X/*:12-27-1989-15:46-wht-use getopt */
  446. X/*:12-27-1989-15:42-wht-time was of by one second (bitch,bitch,bitch) */
  447. X/*:12-04-1989-20:14-wht-support UNIX 3.2 */
  448. X/*:05-18-1989-15:12-wht-improve hangup() error reporting */
  449. X/*:05-18-1989-15:04-wht-use ltoggle_dtr: close/open chg'd baudrate */
  450. X/*:02-03-1989-19:50-wht-386 release */
  451. X/*:12-07-1988-15:13-wht-show cmos time before setting it */
  452. X/*:07-23-1988-19:03-wht-release */
  453. X/*:07-23-1988-13:11-wht-get good parsed time before hanging up w/max retries */
  454. X/*:07-23-1988-12:50-wht-do not use setclock ... messes up new system time */
  455. X/*:07-22-1988-20:17-wht-change output format */
  456. X/*:07-18-1988-22:07-wht-working! */
  457. X/*:07-18-1988-17:27-wht-creation */
  458. X
  459. X#include <stdio.h>
  460. X#include <signal.h>
  461. X#include <ctype.h>
  462. X#include <sys/types.h>
  463. X#include <sys/stat.h>
  464. X#include <sys/ioctl.h>
  465. X#include <time.h>
  466. X#include <string.h>
  467. X#include <fcntl.h>
  468. X#include <errno.h>
  469. X#include <termio.h>
  470. X
  471. X#include "dev_cmos.h"
  472. X
  473. X#ifndef ushort
  474. X#define ushort    unsigned short
  475. X#endif
  476. X#ifndef uchar
  477. X#define uchar unsigned char
  478. X#endif
  479. X#ifndef uint
  480. X#define uint    unsigned int
  481. X#endif
  482. X#ifndef ulong
  483. X#define ulong    unsigned long
  484. X#endif
  485. X
  486. Xvoid usage(void);
  487. Xvoid hangup(int );
  488. Xint make_lock_name(char *,char *);
  489. Xint create_lock_file(char *);
  490. Xchar *other_lock_name(char *);
  491. Xint lock_tty(void );
  492. Xvoid unlock_tty(void );
  493. Xint valid_baud_rate(unsigned int );
  494. Xint lset_baud_rate(int );
  495. Xvoid lset_parity(int );
  496. Xvoid lgetc(char *);
  497. Xvoid lputc(char );
  498. Xvoid lputs_paced(int ,char *);
  499. Xchar *lgets_timeout(struct lrwt *);
  500. Xint lgetc_timeout(unsigned long );
  501. Xvoid lkill_buf(void );
  502. Xint lopen(void );
  503. Xvoid lclose(void );
  504. Xint hayes_send_cmd(char *);
  505. Xint hayes_dial(void );
  506. X
  507. Xushort    geteuid();
  508. Xushort    getuid();
  509. Xlong    nap(long);
  510. Xlong time(long *);
  511. Xchar *ctime();
  512. X
  513. Xtypedef struct lrwt    /* param to lgets_timeout in eculine.c */
  514. X{
  515. X    ulong to1;        /* timeout for 1st character (granularity 20) */
  516. X    ulong to2;        /* timeout for each next char (granularity 20) */
  517. X    int raw_flag;    /* !=0, rtn full buffer, ==0, rtn filtered hayes result */
  518. X    char *buffer;    /* buffer to fill */
  519. X    int bufsize;    /* size of buffer */
  520. X    int count;        /* from proc, count rcvd */
  521. X}    LRWT;
  522. X
  523. X#define    EPOCH        40587                    /* UNIX starts JD 2440587, */
  524. X#define    leap(y,m)    ((y+m-1 - 70%m) / m)    /* also known as 1/1/70 */
  525. X#define    NBSTONE        '*'                        /* time "hack" */
  526. X#define    NBSFMT        "%05ld %03d %02d%02d%02d UTC"
  527. X
  528. X#define pf    printf
  529. X#define    ff    fprintf
  530. X#define se    stderr
  531. X#define so    stdout
  532. X
  533. X/* lopen() and related routines error codes */
  534. X#define LOPEN_INVALID    -1        /* for invalid tty name */
  535. X#define LOPEN_UNKPID    -2        /* unknown pid using line */
  536. X#define LOPEN_LCKERR    -3        /* lock file open error */
  537. X#define LOPEN_NODEV        -4        /* device does not exist */
  538. X#define LOPEN_OPNFAIL    -5        /* count not open line */
  539. X#define LOPEN_ALREADY    -6        /* line already open */
  540. X
  541. Xextern char *revision;        /* ecurev.c temp file from buildrev */
  542. Xextern char *numeric_revision;    /*ecunumrev.c */
  543. X
  544. Xchar LLCKname[128];        /* lock file name */
  545. Xint Lmodem_already_init = 0;
  546. Xchar Ltelno[64];        /* telephone number for remote or null */
  547. Xchar Lline[64];            /* line name */
  548. Xint Liofd;                /* file descriptor for line */
  549. Xint Lparity;            /* 0==NONE, 'e' == even, 'o' == odd */
  550. Xstruct termio    Ltermio;    /* attributes for the line to remote */
  551. Xuint Lbaud;                /* baud rate */
  552. Xushort euid;
  553. Xushort uid;
  554. Xchar *cmos = "/dev/cmos";
  555. X
  556. X/*+-------------------------------------------------------------------------
  557. X    usage()
  558. X--------------------------------------------------------------------------*/
  559. Xvoid
  560. Xusage()
  561. X{
  562. X    ff(se,"Usage: NBSsetclk [-][-e][-o][-n][-b#][-t#][-l<name>]\n");
  563. X    ff(se,"Defaults 1200-N %s %s\n",Ltelno,Lline);
  564. X    ff(se," -        use defaults\n");
  565. X    ff(se," -e       even parity\n");
  566. X    ff(se," -o       odd parity\n");
  567. X    ff(se," -n       no parity\n");
  568. X    ff(se," -b#      baud rate\n");
  569. X    ff(se," -t#      telephone number\n");
  570. X    ff(se," -l<name> line (e.g., /dev/tty2A)\n");
  571. X    exit(253);
  572. X
  573. X}    /* end of usage */
  574. X
  575. X/*+-----------------------------------------------------------------------
  576. X    hangup(sig) -- terminate program (with comm line cleanup)
  577. X------------------------------------------------------------------------*/
  578. Xvoid
  579. Xhangup(sig)
  580. Xint sig;
  581. X{
  582. Xvoid    lclose();
  583. X
  584. X    ff(se,"\nhangup %d (see code)\n",sig);
  585. X    if(Liofd != -1)
  586. X        lclose();            /* close line */
  587. X    exit(sig);
  588. X}    /* end of hangup */
  589. X
  590. X/*+-------------------------------------------------------------------------
  591. X    make_lock_name(ttyname,lock_file_name)
  592. X--------------------------------------------------------------------------*/
  593. Xmake_lock_name(ttyname,lock_file_name)
  594. Xregister char *ttyname;
  595. Xchar *lock_file_name;
  596. X{
  597. X    if(strncmp(ttyname,"/dev/tty",8))
  598. X        return(LOPEN_INVALID);
  599. X
  600. X    strcpy(lock_file_name,"/usr/spool/uucp/LCK..");
  601. X    strcat(lock_file_name,ttyname + 8);
  602. X    return(0);
  603. X
  604. X}    /* end of make_lock_name */
  605. X
  606. X/*+-----------------------------------------------------------------------
  607. X    create_lock_file()
  608. X
  609. X  Returns 0 if lock file created, else error codes:
  610. X    LOPEN_ if error
  611. X    else pid of process currently busy on device
  612. X  Everybody's uucp is diffeent - hack this if you like
  613. X------------------------------------------------------------------------*/
  614. Xcreate_lock_file(lock_file_name)
  615. Xchar *lock_file_name;
  616. X{
  617. Xregister int fdlock;
  618. Xint pid;
  619. Xint old_umask;
  620. X
  621. X    old_umask = umask(0);
  622. X
  623. X    if((fdlock = open(lock_file_name,O_CREAT | O_EXCL | O_RDWR,0666)) < 0)
  624. X    {        /* file already exists */
  625. X        if((fdlock = open(lock_file_name,O_RDWR,0666)) < 0)
  626. X        {
  627. X            umask(old_umask);
  628. X            return(LOPEN_LCKERR);
  629. X        }
  630. X
  631. X        if(read(fdlock,(char *)&pid,sizeof(pid)) > 0)
  632. X        {
  633. X            if(kill(pid,0) && (errno == ESRCH))    /* is owner dead? */
  634. X            {
  635. X                pid = getpid();
  636. X                lseek(fdlock,0L,0);
  637. X                write(fdlock,(char *)&pid,sizeof(pid));
  638. X                close(fdlock);
  639. X                umask(old_umask);
  640. X                return(0);
  641. X            } 
  642. X            /* owner pid still active with lock */
  643. X            close(fdlock);
  644. X            umask(old_umask);
  645. X            return(pid);
  646. X        }
  647. X        close(fdlock);
  648. X        umask(old_umask);
  649. X        return(LOPEN_UNKPID);
  650. X    } 
  651. X    pid = getpid();
  652. X    write(fdlock,(char *)&pid,sizeof(pid));
  653. X    close(fdlock);
  654. X    chmod(lock_file_name,0666);
  655. X    umask(old_umask);
  656. X    return(0);
  657. X
  658. X}    /* end of create_lock_file */
  659. X
  660. X/*+-------------------------------------------------------------------------
  661. X    other_lock_name(first_lock_name)
  662. X--------------------------------------------------------------------------*/
  663. Xchar *
  664. Xother_lock_name(first_lock_name)
  665. Xchar *first_lock_name;
  666. X{
  667. Xregister int itmp;
  668. Xstatic char other_lock_name[64];
  669. X
  670. X    strcpy(other_lock_name,first_lock_name);
  671. X    itmp = strlen(other_lock_name) - 1;
  672. X    if(islower(other_lock_name[itmp]))
  673. X        other_lock_name[itmp] = toupper(other_lock_name[itmp]);
  674. X    else if(isupper(other_lock_name[itmp]))
  675. X        other_lock_name[itmp] = tolower(other_lock_name[itmp]);
  676. X
  677. X    return(other_lock_name);
  678. X        
  679. X}    /* end of other_lock_name */
  680. X
  681. X/*+-------------------------------------------------------------------------
  682. X    lock_tty()
  683. X--------------------------------------------------------------------------*/
  684. Xlock_tty()
  685. X{
  686. Xregister int itmp;
  687. Xstruct stat ttystat;
  688. X
  689. X    if(itmp = make_lock_name(Lline,LLCKname))
  690. X        return(itmp);
  691. X
  692. X    if(stat(Lline,&ttystat) < 0)
  693. X        return(LOPEN_NODEV);
  694. X
  695. X    if(itmp = create_lock_file(LLCKname))
  696. X        return(itmp);
  697. X
  698. X    if(itmp = create_lock_file(other_lock_name(LLCKname)))
  699. X    {
  700. X        unlink(LLCKname);
  701. X        LLCKname[0] = 0;
  702. X        return(itmp);
  703. X    }
  704. X
  705. X}    /* end of lock_tty */
  706. X
  707. X/*+-----------------------------------------------------------------------
  708. X    void unlock_tty()
  709. X------------------------------------------------------------------------*/
  710. Xvoid
  711. Xunlock_tty()
  712. X{
  713. X
  714. X    if(LLCKname[0] == 0)
  715. X        return;
  716. X    unlink(LLCKname);
  717. X    unlink(other_lock_name(LLCKname));
  718. X    LLCKname[0] = 0;
  719. X}    /* end of unlock_tty */
  720. X
  721. X/*+-------------------------------------------------------------------------
  722. X    valid_baud_rate(baud) -- returns (positive) baud rate selector
  723. Xor -1 if invalid baud rate
  724. X--------------------------------------------------------------------------*/
  725. Xvalid_baud_rate(baud)
  726. Xuint    baud;
  727. X{
  728. X    switch(baud)
  729. X    {
  730. X        case 110: return(B110);
  731. X        case 300: return(B300);
  732. X        case 600: return(B600);
  733. X        case 1200: return(B1200);
  734. X        case 2400: return(B2400);
  735. X        case 4800: return(B4800);
  736. X        case 9600: return(B9600);
  737. X        case 19200: return(EXTA);
  738. X        case 38400: return(EXTB);
  739. X        default: return(-1);
  740. X    }
  741. X}    /* end of valid_baud_rate */
  742. X
  743. X/*+-----------------------------------------------------------------------
  744. X    lset_baud_rate(ioctl_flag)
  745. X
  746. X  If 'ioctl_flag' is set,then ioctl(Liofd,TCSETA,&Ltermio)
  747. X  is executed after setting baud rate
  748. X------------------------------------------------------------------------*/
  749. Xlset_baud_rate(ioctl_flag)
  750. Xint ioctl_flag;
  751. X{
  752. Xint baud_selector = valid_baud_rate(Lbaud);
  753. X
  754. X    if(baud_selector < 0)
  755. X    {
  756. X        ff(se,"invalid baud rate: %u\n",Lbaud);
  757. X        ff(se,"valid rates: 110,300,600,1200,2400,4800,9600,19200\n");
  758. X        return(1);
  759. X    }
  760. X    Ltermio.c_cflag &= ~CBAUD;
  761. X    Ltermio.c_cflag |= baud_selector;
  762. X
  763. X    if(ioctl_flag)
  764. X         ioctl(Liofd,(int)TCSETA,(char *)&Ltermio);
  765. X    return(1);
  766. X
  767. X}    /* end of lset_baud_rate */
  768. X
  769. X/*+-----------------------------------------------------------------------
  770. X    lset_parity(ioctl_flag)
  771. X
  772. X  If 'ioctl_flag' is set,then ioctl(Liofd,TCSETA,&Ltermio)
  773. X  is executed after setting parity
  774. X------------------------------------------------------------------------*/
  775. Xvoid
  776. Xlset_parity(ioctl_flag)
  777. Xint ioctl_flag;
  778. X{
  779. X    Ltermio.c_cflag &= ~(CS8 | PARENB | PARODD);
  780. X    switch(Lparity)
  781. X    {
  782. X        case 'e':
  783. X            Ltermio.c_cflag |= CS7 | PARENB;
  784. X            Ltermio.c_iflag |= ISTRIP;
  785. X            break;
  786. X        case 'o':
  787. X            Ltermio.c_cflag |= PARODD | CS7 | PARENB;
  788. X            Ltermio.c_iflag |= ISTRIP;
  789. X            break;
  790. X        default:
  791. X            ff(se,"invalid parity: %c ... defaulting to no parity\n");
  792. X        case 0:
  793. X        case 'n':
  794. X            Ltermio.c_cflag |= CS8;
  795. X            Ltermio.c_iflag &= ~(ISTRIP);
  796. X            Lparity = 0;
  797. X            break;
  798. X    }            
  799. X
  800. X    if(ioctl_flag)
  801. X         ioctl(Liofd,(int)TCSETA,(char *)&Ltermio);
  802. X
  803. X}    /* end of lset_parity */
  804. X
  805. X/*+-------------------------------------------------------------------------
  806. X    lgetc(char_rtnd)
  807. X--------------------------------------------------------------------------*/
  808. Xvoid
  809. Xlgetc(char_rtnd)
  810. Xchar *char_rtnd;
  811. X{
  812. X    if(read(Liofd,char_rtnd,1) < 1)
  813. X    {
  814. X        perror("line read error");
  815. X        hangup(255);
  816. X    }
  817. X}    /* end of lgetc */
  818. X
  819. X/*+-----------------------------------------------------------------------
  820. X    lputc(lchar) -- write lchar to comm line
  821. X------------------------------------------------------------------------*/
  822. Xvoid
  823. Xlputc(lchar)
  824. Xchar lchar;
  825. X{
  826. Xregister int itmp;
  827. X
  828. X    if((itmp = write(Liofd,&lchar,1)) < 1)
  829. X    {
  830. X        if(itmp < 0)
  831. X            perror("\nline write error");
  832. X        else
  833. X            fputs("\nline write error\n",se);
  834. X        hangup(255);
  835. X    }
  836. X}    /* end of lputc */
  837. X
  838. X/*+-----------------------------------------------------------------------
  839. X    lputs_paced(pace_msec,string) -- write string to comm line
  840. X  with time between each character 
  841. X------------------------------------------------------------------------*/
  842. Xvoid
  843. Xlputs_paced(pace_msec,string)
  844. Xregister int pace_msec;
  845. Xregister char *string;
  846. X{
  847. Xregister long msec = (pace_msec) ? (long)pace_msec : 20L;
  848. X
  849. X    while(*string)
  850. X    {
  851. X        lputc(*string++);
  852. X        nap(msec);
  853. X    }
  854. X
  855. X}    /* end of lputs_paced */
  856. X
  857. X/*+-------------------------------------------------------------------------
  858. X    char *lgets_timeout(LRWT *)
  859. X
  860. XRefer to LWRT structure.
  861. X
  862. Xto1 and to2 are unsigned long values in milliseconds (not currently
  863. Xsupported well under BSD4); to1 is the time to wait for the first
  864. Xcharacter, to2 the time to wait for subsequent characters.
  865. X
  866. Xif raw_flag 0,     non-printables are stripped from beginning
  867. X                   and end of received characters (i.e., modem
  868. X                   response reads); NULs discarded, parity stripped
  869. Xif raw_flag 1,     full raw read buffer returned
  870. Xif raw_flag 2,     full buffer, NULs discarded, parity stripped
  871. X
  872. Xbuffer is address to read chars into
  873. X
  874. Xbufsize is buffer max size (allowing room for terminating null) which
  875. Xshould be at least 2 if raw_size includes 0x80 bit, else at least 12
  876. Xcharacters if 0x80 omitted.
  877. X
  878. Xcount is a int which, at return, receives the actual count read
  879. X
  880. X--------------------------------------------------------------------------*/
  881. Xchar *
  882. Xlgets_timeout(lrwt)
  883. XLRWT    *lrwt;
  884. X{
  885. Xregister int actual_count = 0;
  886. Xregister char *cptr = lrwt->buffer;
  887. Xint max_count = lrwt->bufsize;
  888. Xchar *rtn_val;
  889. Xint timeout_counter;
  890. Xint qc1,qc2;
  891. Xlong quantum,ltmp;
  892. X
  893. X/* minimum wait is 60 msec */
  894. X    if(Lbaud < 300)
  895. X        if(lrwt->to2 < 300L) lrwt->to2 = 300L;
  896. X    if(Lbaud < 1200)
  897. X        if(lrwt->to2 < 200L) lrwt->to2 = 200L;
  898. X    else
  899. X        if(lrwt->to2 < 60L) lrwt->to2 = 60L;
  900. X
  901. X/* shortest interval */
  902. X    ltmp = (lrwt->to1 < lrwt->to2) ? lrwt->to1 : lrwt->to2;
  903. X
  904. X/* calculate wait quantum */
  905. X    quantum = ltmp / 10L;                /* try for ten ticks */
  906. X    if(quantum < 20L)
  907. X        quantum = 20L;
  908. X    qc1 = lrwt->to1 / quantum;
  909. X    if(!qc1) qc1 = 1L;
  910. X    qc2 = lrwt->to2 / quantum;
  911. X    if(!qc2) qc2 = 1L;
  912. X
  913. X/* perform the lrtw function
  914. X   input: qc1 is first nap count (for first charcters) 
  915. X          qc2 is 2nd nap count (for subsequent characters) 
  916. X          quantum is the nap period in milliseconds
  917. X          cptr is char* to receive read string
  918. X          max_count is max number of characters incl null
  919. X          lrwt->raw_flag as described above
  920. X
  921. X  output: lrwt->count is actual count of return result
  922. X          lrwt->buffer is return read buffer
  923. X*/
  924. X    max_count--;                /* leave room for null */
  925. X
  926. X    lrwt->raw_flag &= 0x0F;        /* get rid of 0xF0 flags */
  927. X    timeout_counter = qc1;        /* first timeout */ 
  928. X    *cptr = 0;                    /* init result string */
  929. X    while(timeout_counter--)
  930. X    {
  931. X        nap(quantum);
  932. X        while(rdchk(Liofd))
  933. X        {
  934. X            lgetc(cptr);
  935. X            if(lrwt->raw_flag != 1)
  936. X            {
  937. X                *cptr &= 0x7F;
  938. X                if(*cptr == 0)
  939. X                    continue;
  940. X            }
  941. X
  942. X            *++cptr = 0;
  943. X            actual_count++;
  944. X            if(--max_count == 0)
  945. X                goto READ_LINE_POST_PROCESS;
  946. X            timeout_counter = qc2;
  947. X        }
  948. X    }
  949. X
  950. XREAD_LINE_POST_PROCESS:
  951. X    if(lrwt->raw_flag)
  952. X    {
  953. X        lrwt->count = actual_count;
  954. X        return(lrwt->buffer);
  955. X    }
  956. X    cptr = lrwt->buffer;
  957. X    while(((*cptr >0) && (*cptr < 0x20)) || (*cptr >= 0x7F))
  958. X        cptr++;
  959. X    rtn_val = cptr;
  960. X    actual_count = 0;
  961. X    while(((*cptr &= 0x7F) >= 0x20) && (*cptr <= 0x7E))
  962. X    {
  963. X        cptr++;
  964. X        actual_count++;
  965. X    }
  966. X    *cptr = 0;
  967. X    strcpy(lrwt->buffer,rtn_val);
  968. X    lrwt->count = actual_count;
  969. X    return(lrwt->buffer);
  970. X}    /* end of lgets_timeout */
  971. X
  972. X/*+-------------------------------------------------------------------------
  973. X    lgetc_timeout(timeout_msec)
  974. X
  975. X reads one character from line unless timeout_msec passes with no receipt.
  976. X timeout_msec < 20 msec becomes 20 msec
  977. X return char if received, else -1 if timeout
  978. X--------------------------------------------------------------------------*/
  979. Xint
  980. Xlgetc_timeout(timeout_msec)
  981. Xulong    timeout_msec;
  982. X{
  983. XLRWT    lr;
  984. Xchar getc_buf[2];        /* room for one char + null */
  985. X
  986. X    lr.to1 = timeout_msec;
  987. X    lr.to2 = timeout_msec;
  988. X    lr.raw_flag = 1;        /* full raw read */
  989. X    lr.buffer = getc_buf;
  990. X    lr.bufsize = sizeof(getc_buf);
  991. X    lgets_timeout(&lr);
  992. X    return(  (lr.count == 1) ? (int)getc_buf[0] : -1 );
  993. X
  994. X}    /* end of lgetc_timeout */
  995. X
  996. X/*+-------------------------------------------------------------------------
  997. X    lkill_buf()
  998. X--------------------------------------------------------------------------*/
  999. Xvoid
  1000. Xlkill_buf()
  1001. X{
  1002. X    ioctl(Liofd,(int)TCFLSH,(char *)2); /* flush input and output */
  1003. X}    /* end of lkill_buf */
  1004. X
  1005. X/*+----------------------------------------------------------------------
  1006. X    lopen()
  1007. Xreturns negative LOPEN_ codes if failure else positive pid using line
  1008. Xelse 0 if successful open
  1009. X------------------------------------------------------------------------*/
  1010. Xint
  1011. Xlopen()
  1012. X{
  1013. Xregister int    itmp;
  1014. X
  1015. X    if(Liofd >= 0)
  1016. X        return(LOPEN_ALREADY);
  1017. X    if(itmp = lock_tty())        /* get lock file */
  1018. X        return(itmp);
  1019. X    Liofd = open(Lline,O_RDWR | O_NDELAY,0777);
  1020. X    if(Liofd < 0)
  1021. X        return(LOPEN_OPNFAIL);
  1022. X    else
  1023. X    {
  1024. X        ioctl(Liofd,(int)TCGETA,(char *)&Ltermio);
  1025. X        Ltermio.c_iflag = (IGNPAR | IGNBRK | IXOFF );
  1026. X        Ltermio.c_cflag |= (CREAD | HUPCL);
  1027. X        Ltermio.c_lflag = 0;
  1028. X
  1029. X        Ltermio.c_cc[VMIN]   = 1;
  1030. X        Ltermio.c_cc[VTIME]  = 1;
  1031. X
  1032. X        lset_baud_rate(0);        /* do not perform ioctl */
  1033. X        lset_parity(1);            /* do perform ioctl */
  1034. X    }
  1035. X
  1036. X    return(0);
  1037. X
  1038. X}    /* end of lopen */
  1039. X
  1040. X/*+-----------------------------------------------------------------------
  1041. SHAR_EOF
  1042. echo "End of cmostime3 part 1"
  1043. echo "File NBSsetclk.c is continued in part 2"
  1044. echo "2" > s3_seq_.tmp
  1045. exit 0
  1046.  
  1047. ----------------------------------------------------------------------------
  1048. Warren Tucker                     emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
  1049. "I was 35 years old before I knew a pie was meant to be eaten." - Moe Howard
  1050.