home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / cvs-berliner / part05 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  53.3 KB

  1. Subject:  v22i019:  Brian Berliner's concurrent RCS system, Part05/07
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 11b1db10 c67b1e76 f8b8c43e 063bd5be
  5.  
  6. Submitted-by: Brian Berliner <berliner@prisma.com>
  7. Posting-number: Volume 22, Issue 19
  8. Archive-name: cvs-berliner/part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 7)."
  17. # Contents:  examples/modules src/commit.c src/partime.c
  18. # Wrapped by rsalz@litchi.bbn.com on Thu May  3 16:59:05 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'examples/modules' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'examples/modules'\"
  22. else
  23. echo shar: Extracting \"'examples/modules'\" \(14454 characters\)
  24. sed "s/^X//" >'examples/modules' <<'END_OF_FILE'
  25. X#
  26. X# CVS Modules file for Prisma sources
  27. X# $Id: modules,v 1.1 89/08/25 00:00:15 berliner Exp $
  28. X#
  29. X# Three differnt line formats are valid:
  30. X#    key     -a    aliases...
  31. X#    key [options] directory
  32. X#    key [options] directory files...
  33. X#
  34. X# Where "options" are composed of:
  35. X#    -i prog        Run "prog" on checkin of files
  36. X#    -o prog        Run "prog" on "checkout" of files
  37. X#    -t prog        Run "prog" on tagging of files
  38. X#
  39. X
  40. X# Convenient aliases
  41. Xworld        -a .
  42. Xkernel        -a sys lang/adb sparcsim
  43. X
  44. X# CVSROOT.adm support
  45. XCVSROOT        -i /usr/local/bin/mkmodules CVSROOT.adm
  46. XCVSROOT.adm    -i /usr/local/bin/mkmodules CVSROOT.adm
  47. Xmodules        -i /usr/local/bin/mkmodules CVSROOT.adm modules
  48. Xloginfo        -i /usr/local/bin/mkmodules CVSROOT.adm loginfo
  49. X
  50. X# The "sys" entry exists only to make symbolic links after checkout
  51. Xsys        -o sys/tools/make_links sys
  52. X
  53. X# Sub-directories of "bin"
  54. Xawk        bin/awk
  55. Xcsh        bin/csh
  56. Xdiff        bin/diff
  57. Xmake        bin/make
  58. Xsed        bin/sed
  59. Xsh        bin/sh
  60. X
  61. X# Programs that live in "bin"
  62. Xcat        bin Makefile cat.c
  63. Xchgrp        bin Makefile chgrp.c
  64. Xchmod        bin Makefile chmod.c
  65. Xcmp        bin Makefile cmp.c
  66. Xcp        bin Makefile cp.c
  67. Xdate        bin Makefile date.c
  68. Xdd        bin Makefile dd.c
  69. Xdf        bin Makefile df.c
  70. Xdomainname    bin Makefile domainname.c
  71. Xdu        bin Makefile du.c
  72. Xecho        bin Makefile echo.c
  73. Xed        bin Makefile ed.c
  74. Xenv        bin Makefile env.c
  75. Xexpr        bin Makefile expr.c
  76. Xgrep        bin Makefile grep.c
  77. Xhostid        bin Makefile hostid.c
  78. Xhostname    bin Makefile hostname.c
  79. Xkill        bin Makefile kill.c
  80. Xldd        bin Makefile ldd.c
  81. Xline        bin Makefile line.c
  82. Xln        bin Makefile ln.c
  83. Xlogin        bin Makefile login.c
  84. Xls        bin Makefile ls.c
  85. Xmail        bin Makefile mail.c
  86. Xmkdir        bin Makefile mkdir.c
  87. Xmt        bin Makefile mt.c
  88. Xmv        bin Makefile mv.c
  89. Xnewgrp        bin Makefile newgrp.c
  90. Xnice        bin Makefile nice.c
  91. Xod        bin Makefile od.c
  92. Xpagesize    bin Makefile pagesize.c
  93. Xpasswd        bin Makefile passwd.c
  94. Xpr        bin Makefile pr.c
  95. Xps        bin Makefile ps.c
  96. Xpwd        bin Makefile pwd.c
  97. Xrm        bin Makefile rm.c
  98. Xrmail        bin Makefile rmail.c
  99. Xrmdir        bin Makefile rmdir.c
  100. Xstty        bin Makefile stty.c
  101. Xsu        bin Makefile su.c
  102. Xsync        bin Makefile sync.c
  103. Xtar        bin Makefile tar.c
  104. Xtee        bin Makefile tee.c
  105. Xtest        bin Makefile test.c
  106. Xtime        bin Makefile time.c
  107. Xwall        bin Makefile wall.c
  108. Xwho        bin Makefile who.c
  109. Xwrite        bin Makefile write.c
  110. X
  111. X# Sub-directories of "etc"
  112. Xdump        etc/dump
  113. Xfiles        etc/files
  114. Xfsck        etc/fsck
  115. Xgetty        etc/getty
  116. Xin.routed    etc/in.routed
  117. Xrestore        etc/restore
  118. Xrpc.lockd    etc/rpc.lockd
  119. Xrpc.statd    etc/rpc.statd
  120. X
  121. X# Programs that live in "etc"
  122. Xarp        etc Makefile arp.c
  123. Xbiod        etc Makefile biod.c
  124. Xchown        etc Makefile chown.c
  125. Xclri        etc Makefile clri.c
  126. Xdkinfo        etc Makefile dkinfo.c
  127. Xdmesg        etc Makefile dmesg.c
  128. Xfsirand        etc Makefile fsirand.c
  129. Xhalt        etc Makefile halt.c
  130. Xifconfig    etc Makefile ifconfig.c
  131. Xin.rlogind    etc Makefile in.rlogind.c
  132. Xin.rshd        etc Makefile in.rshd.c
  133. Xinetd        etc Makefile inetd.c
  134. Xinit        etc Makefile init.c
  135. Xmkfs        etc Makefile mkfs.c
  136. Xmknod        etc Makefile mknod.c
  137. Xmount        etc Makefile mount.c
  138. Xnewfs        etc Makefile newfs.c
  139. Xnfsd        etc Makefile nfsd.c
  140. Xportmap        etc Makefile portmap.c
  141. Xpstat        etc Makefile pstat.c
  142. Xreboot        etc Makefile reboot.c
  143. Xrenice        etc Makefile renice.c
  144. Xrmt        etc Makefile rmt.c
  145. Xshutdown    etc Makefile shutdown.c
  146. Xsyslogd        etc Makefile syslogd.c
  147. Xumount        etc Makefile umount.c
  148. Xupdate        etc Makefile update.c
  149. Xvipw        etc Makefile vipw.c
  150. Xypbind        etc Makefile ypbind.c
  151. X
  152. X# Sub-directories of "games"
  153. Xadventure    games/adventure
  154. Xbackgammon    games/backgammon
  155. Xbattlestar    games/battlestar
  156. Xboggle        games/boggle
  157. Xchess        games/chess
  158. Xching        games/ching
  159. Xcribbage    games/cribbage
  160. Xfortune        games/fortune
  161. Xhack        games/hack
  162. Xhangman        games/hangman
  163. Xhunt        games/hunt
  164. Xlife        games/life
  165. Xmille        games/mille
  166. Xmonop        games/monop
  167. Xquiz        games/quiz
  168. Xrobots        games/robots
  169. Xsail        games/sail
  170. Xsnake        games/snake
  171. Xtrek        games/trek
  172. X
  173. X# Programs that live in "games"
  174. Xarithmetic    games Makefile arithmetic.c
  175. Xbanner        games Makefile banner.c
  176. Xbcd        games Makefile bcd.c
  177. Xbj        games Makefile bj.c
  178. Xbtlgammon    games Makefile btlgammon.c
  179. Xcanfield    games Makefile canfield.c
  180. Xcfscores    games Makefile cfscores.c
  181. Xcraps        games Makefile craps.c
  182. Xfactor        games Makefile factor.c
  183. Xfish        games Makefile fish.c
  184. Xmoo        games Makefile moo.c
  185. Xnumber        games Makefile number.c
  186. Xprimes        games Makefile primes.c
  187. Xrain        games Makefile rain.c
  188. Xrandom        games Makefile random.c
  189. Xworm        games Makefile worm.c
  190. Xworms        games Makefile worms.c
  191. Xwump        games Makefile wump.c
  192. X
  193. X# Sub-directories of "lang"
  194. Xadb        lang/adb
  195. Xas        lang/as
  196. Xboot        lang/boot
  197. Xc2        lang/c2
  198. Xcgrdr        lang/cgrdr
  199. Xcompile        lang/compile
  200. Xcpp        lang/cpp
  201. Xdbx        lang/dbx
  202. Xf77        lang/f77
  203. Xinline        lang/inline
  204. Xiropt        lang/iropt
  205. Xld        lang/ld
  206. Xlint        lang/lint
  207. Xm4        lang/m4
  208. Xpascal        lang/pascal
  209. Xpcc        lang/pcc
  210. Xratfor        lang/ratfor
  211. Xrtld        lang/rtld
  212. Xtcov        lang/tcov
  213. Xvroot        lang/vroot
  214. X
  215. X# Programs that live in "lang"
  216. Xar        lang Makefile ar.c
  217. Xnm        lang Makefile nm.c
  218. Xranlib        lang Makefile ranlib.c
  219. Xsize        lang Makefile size.c
  220. Xstrip        lang Makefile strip.c
  221. Xsymorder    lang Makefile symorder.c
  222. X
  223. X# Sub-directories of "lib"
  224. Xcsu        lib/csu
  225. Xlibc        lib/libc
  226. X
  227. X# Programs that live in "lib"
  228. X# NONE
  229. X
  230. X# Sub-directories of "lib/libc"
  231. Xlibc_compat    lib/libc/compat
  232. Xlibc_crt    lib/libc/crt
  233. Xlibc_des    lib/libc/des
  234. Xlibc_gen    lib/libc/gen
  235. Xlibc_net    lib/libc/net
  236. Xlibc_inet    lib/libc/inet
  237. Xlibc_rpc    lib/libc/rpc
  238. Xlibc_stdio    lib/libc/stdio
  239. Xlibc_sun    lib/libc/sun
  240. Xlibc_sys    lib/libc/sys
  241. Xlibc_yp        lib/libc/yp
  242. X
  243. X# Programs that live in "lib/libc"
  244. X# NONE
  245. X
  246. X#Sub-directories of "local"
  247. Xnotes        local/notes
  248. X
  249. X# Sub-directories of "man"
  250. Xman1        man/man1
  251. Xman2        man/man2
  252. Xman3        man/man3
  253. Xman4        man/man4
  254. Xman5        man/man5
  255. Xman6        man/man6
  256. Xman7        man/man7
  257. Xman8        man/man8
  258. Xmanl        man/manl
  259. X
  260. X# Programs that live in "man"
  261. X# NONE
  262. X
  263. X# Sub-directories of "old"
  264. Xold_compact    old/compact
  265. Xold_eyacc    old/eyacc
  266. Xold_filemerge    old/filemerge
  267. Xold_make    old/make
  268. X
  269. X# Programs that live in "old"
  270. Xold_analyze    old Makefile analyze.c
  271. Xold_prmail    old Makefile prmail.c
  272. Xold_pti        old Makefile pti.c
  273. Xold_syslog    old Makefile syslog.c
  274. X
  275. X# Sub-directories of "ucb"
  276. XMail        ucb/Mail
  277. Xcompress    ucb/compress
  278. Xerror        ucb/error
  279. Xex        ucb/ex
  280. Xftp        ucb/ftp
  281. Xgprof        ucb/gprof
  282. Xindent        ucb/indent
  283. Xlpr        ucb/lpr
  284. Xmore        ucb/more
  285. Xmsgs        ucb/msgs
  286. Xnetstat        ucb/netstat
  287. Xrdist        ucb/rdist
  288. Xtalk        ucb/talk
  289. Xtftp        ucb/tftp
  290. Xtset        ucb/tset
  291. Xvgrind        ucb/vgrind
  292. X
  293. X# Programs that live in "ucb"
  294. Xbiff        ucb Makefile biff.c
  295. Xchecknr        ucb Makefile checknr.c
  296. Xclear        ucb Makefile clear.c
  297. Xcolcrt        ucb Makefile colcrt.c
  298. Xcolrm        ucb Makefile colrm.c
  299. Xctags        ucb Makefile ctags.c
  300. Xexpand        ucb Makefile expand.c
  301. Xfinger        ucb Makefile finger.c
  302. Xfold        ucb Makefile fold.c
  303. Xfrom        ucb Makefile from.c
  304. Xfsplit        ucb Makefile fsplit.c
  305. Xgcore        ucb Makefile gcore.c
  306. Xgroups        ucb Makefile groups.c
  307. Xhead        ucb Makefile head.c
  308. Xlast        ucb Makefile last.c
  309. Xlastcomm    ucb Makefile lastcomm.c
  310. Xleave        ucb Makefile leave.c
  311. Xlogger        ucb Makefile logger.c
  312. Xman_prog    ucb Makefile man.c
  313. Xmkstr        ucb Makefile mkstr.c
  314. Xprintenv    ucb Makefile printenv.c
  315. Xquota        ucb Makefile quota.c
  316. Xrcp        ucb Makefile rcp.c
  317. Xrdate        ucb Makefile rdate.c
  318. Xrlogin        ucb Makefile rlogin.c
  319. Xrsh        ucb Makefile rsh.c
  320. Xrup        ucb Makefile rup.c
  321. Xruptime        ucb Makefile ruptime.c
  322. Xrusers        ucb Makefile rusers.c
  323. Xrwho        ucb Makefile rwho.c
  324. Xsccs        ucb Makefile sccs.c
  325. Xscript        ucb Makefile script.c
  326. Xsoelim        ucb Makefile soelim.c
  327. Xstrings        ucb Makefile strings.c
  328. Xtail        ucb Makefile tail.c
  329. Xtcopy        ucb Makefile tcopy.c
  330. Xtelnet        ucb Makefile telnet.c
  331. Xul        ucb Makefile ul.c
  332. Xunexpand    ucb Makefile unexpand.c
  333. Xunifdef        ucb Makefile unifdef.c
  334. Xusers        ucb Makefile users.c
  335. Xvmstat        ucb Makefile vmstat.c
  336. Xw        ucb Makefile w.c
  337. Xwc        ucb Makefile wc.c
  338. Xwhat        ucb Makefile what.c
  339. Xwhatis        ucb Makefile whatis.c
  340. Xwhereis        ucb Makefile whereis.c
  341. Xwhoami        ucb Makefile whoami.c
  342. Xwhois        ucb Makefile whois.c
  343. Xxstr        ucb Makefile xstr.c
  344. Xyes        ucb Makefile yes.c
  345. X
  346. X# Sub-directories of "usr.bin"
  347. Xcalendar    usr.bin/calendar
  348. Xcflow        usr.bin/cflow
  349. Xctrace        usr.bin/ctrace
  350. Xcxref        usr.bin/cxref
  351. Xdc        usr.bin/dc
  352. Xdes        usr.bin/des
  353. Xdiff3        usr.bin/diff3
  354. Xsun_eqn        usr.bin/eqn
  355. Xfile        usr.bin/file
  356. Xfind        usr.bin/find
  357. Xgraph        usr.bin/graph
  358. Xlex        usr.bin/lex
  359. Xsun_neqn    usr.bin/neqn
  360. Xsun_nroff    usr.bin/nroff
  361. Xsun_plot    usr.bin/plot
  362. Xprof        usr.bin/prof
  363. Xrefer        usr.bin/refer
  364. Xrpcgen        usr.bin/rpcgen
  365. Xspell        usr.bin/spell
  366. Xsun_tbl        usr.bin/tbl
  367. Xtip        usr.bin/tip
  368. Xtrace        usr.bin/trace
  369. Xsun_troff    usr.bin/troff
  370. Xuucp        usr.bin/uucp
  371. Xxsend        usr.bin/xsend
  372. Xyacc        usr.bin/yacc
  373. X
  374. X# Programs that live in "usr.bin"
  375. Xbasename    usr.bin Makefile basename.c
  376. Xbc        usr.bin Makefile bc.c
  377. Xcal        usr.bin Makefile cal.c
  378. Xcb        usr.bin Makefile cb.c
  379. Xcheckeq        usr.bin Makefile checkeq.c
  380. Xchkey        usr.bin Makefile chkey.c
  381. Xclick        usr.bin Makefile click.c
  382. Xcol        usr.bin Makefile col.c
  383. Xcomm        usr.bin Makefile comm.c
  384. Xcpio        usr.bin Makefile cpio.c
  385. Xcrypt        usr.bin Makefile crypt.c
  386. Xcsplit        usr.bin Makefile csplit.c
  387. Xcut        usr.bin Makefile cut.c
  388. Xderoff        usr.bin Makefile deroff.c
  389. Xegrep        usr.bin Makefile egrep.c
  390. Xfgrep        usr.bin Makefile fgrep.c
  391. Xgetopt        usr.bin Makefile getopt.c
  392. Xid        usr.bin Makefile id.c
  393. Xinstallcmd    usr.bin Makefile installcmd.c
  394. Xiostat        usr.bin Makefile iostat.c
  395. Xipcrm        usr.bin Makefile ipcrm.c
  396. Xipcs        usr.bin Makefile ipcs.c
  397. Xjoin        usr.bin Makefile join.c
  398. Xkeylogin    usr.bin Makefile keylogin.c
  399. Xlogname        usr.bin Makefile logname.c
  400. Xlook        usr.bin Makefile look.c
  401. Xmesg        usr.bin Makefile mesg.c
  402. Xnl        usr.bin Makefile nl.c
  403. Xpack        usr.bin Makefile pack.c
  404. Xpaste        usr.bin Makefile paste.c
  405. Xptx        usr.bin Makefile ptx.c
  406. Xrev        usr.bin Makefile rev.c
  407. Xscreenblank    usr.bin Makefile screenblank.c
  408. Xsdiff        usr.bin Makefile sdiff.c
  409. Xsleep        usr.bin Makefile sleep.c
  410. Xsort        usr.bin Makefile sort.c
  411. Xspline        usr.bin Makefile spline.c
  412. Xsplit        usr.bin Makefile split.c
  413. Xsum        usr.bin Makefile sum.c
  414. Xtouch        usr.bin Makefile touch.c
  415. Xtr        usr.bin Makefile tr.c
  416. Xtsort        usr.bin Makefile tsort.c
  417. Xtty        usr.bin Makefile tty.c
  418. Xuniq        usr.bin Makefile uniq.c
  419. Xunits        usr.bin Makefile units.c
  420. Xunpack        usr.bin Makefile unpack.c
  421. Xxargs        usr.bin Makefile xargs.c
  422. Xypcat        usr.bin Makefile ypcat.c
  423. Xypmatch        usr.bin Makefile ypmatch.c
  424. Xyppasswd    usr.bin Makefile yppasswd.c
  425. Xypwhich        usr.bin Makefile ypwhich.c
  426. X
  427. X# Sub-directories of "usr.etc"
  428. Xautomount    usr.etc/automount
  429. Xc2convert    usr.etc/c2convert
  430. Xconfig        usr.etc/config
  431. Xcron        usr.etc/cron
  432. Xeeprom        usr.etc/eeprom
  433. Xetherfind    usr.etc/etherfind
  434. Xformat        usr.etc/format
  435. Xhtable        usr.etc/htable
  436. Ximplog        usr.etc/implog
  437. Xin.ftpd        -a usr.etc/in.ftpd ucb/ftp
  438. Xin.named    usr.etc/in.named
  439. Xin.rwhod    usr.etc/in.rwhod
  440. Xkeyserv        usr.etc/keyserv
  441. Xndbootd        usr.etc/ndbootd
  442. Xpraudit        usr.etc/praudit
  443. Xrexd        usr.etc/rexd
  444. Xrpc.bootparamd    usr.etc/rpc.bootparamd
  445. Xtermcap        usr.etc/termcap
  446. Xupgrade        usr.etc/upgrade
  447. Xyp        usr.etc/yp
  448. Xzic        usr.etc/zic
  449. X
  450. X# Programs that live in "usr.etc"
  451. Xac        usr.etc Makefile ac.c
  452. Xaccton        usr.etc Makefile accton.c
  453. Xaudit        usr.etc Makefile audit.c
  454. Xauditd        usr.etc Makefile auditd.c
  455. Xcatman        usr.etc Makefile catman.c
  456. Xchroot        usr.etc Makefile chroot.c
  457. Xdcheck        usr.etc Makefile dcheck.c
  458. Xdevnm        usr.etc Makefile devnm.c
  459. Xdumpfs        usr.etc Makefile dumpfs.c
  460. Xedquota        usr.etc Makefile edquota.c
  461. Xexportfs    usr.etc Makefile exportfs.c
  462. Xfoption        usr.etc Makefile foption.c
  463. Xgettable    usr.etc Makefile gettable.c
  464. Xgrpck        usr.etc Makefile grpck.c
  465. Xicheck        usr.etc Makefile icheck.c
  466. Xin.comsat    usr.etc Makefile in.comsat.c
  467. Xin.fingerd    usr.etc Makefile in.fingerd.c
  468. Xin.rexecd    usr.etc Makefile in.rexecd.c
  469. Xin.telnetd    usr.etc Makefile in.telnetd.c
  470. Xin.tnamed    usr.etc Makefile in.tnamed.c
  471. Xkgmon        usr.etc Makefile kgmon.c
  472. Xlink        usr.etc Makefile link.c
  473. Xmkfile        usr.etc Makefile mkfile.c
  474. Xmkproto        usr.etc Makefile mkproto.c
  475. Xmount_lo    usr.etc Makefile mount_lo.c
  476. Xncheck        usr.etc Makefile ncheck.c
  477. Xnfsstat        usr.etc Makefile nfsstat.c
  478. Xping        usr.etc Makefile ping.c
  479. Xpwck        usr.etc Makefile pwck.c
  480. Xquot        usr.etc Makefile quot.c
  481. Xquotacheck    usr.etc Makefile quotacheck.c
  482. Xquotaon        usr.etc Makefile quotaon.c
  483. Xrarpd        usr.etc Makefile rarpd.c
  484. Xrepquota    usr.etc Makefile repquota.c
  485. Xroute        usr.etc Makefile route.c
  486. Xrpc.etherd    usr.etc Makefile rpc.etherd.c
  487. Xrpc.mountd    usr.etc Makefile rpc.mountd.c
  488. Xrpc.pwdauthd    usr.etc Makefile rpc.pwdauthd.c
  489. Xrpc.rquotad    usr.etc Makefile rpc.rquotad.c
  490. Xrpc.rstatd    usr.etc Makefile rpc.rstatd.c
  491. Xrpc.rusersd    usr.etc Makefile rpc.rusersd.c
  492. Xrpc.rwalld    usr.etc Makefile rpc.rwalld.c
  493. Xrpc.sprayd    usr.etc Makefile rpc.sprayd.c
  494. Xrpc.yppasswdd    usr.etc Makefile rpc.yppasswdd.c
  495. Xrpc.ypupdated    usr.etc Makefile rpc.ypupdated.c
  496. Xrpcinfo        usr.etc Makefile rpcinfo.c
  497. Xrwall        usr.etc Makefile rwall.c
  498. Xsa        usr.etc Makefile sa.c
  499. Xsavecore    usr.etc Makefile savecore.c
  500. Xshowmount    usr.etc Makefile showmount.c
  501. Xspray        usr.etc Makefile spray.c
  502. Xswapon        usr.etc Makefile swapon.c
  503. Xtrpt        usr.etc Makefile trpt.c
  504. Xtunefs        usr.etc Makefile tunefs.c
  505. Xunlink        usr.etc Makefile unlink.c
  506. X
  507. X# Sub-directories of "usr.lib"
  508. Xbb_count    usr.lib/bb_count
  509. Xfixedwidthfonts    usr.lib/fixedwidthfonts
  510. Xlibcurses    usr.lib/libcurses
  511. Xlibdbm        usr.lib/libdbm
  512. Xlibg        usr.lib/libg
  513. Xlibkvm        usr.lib/libkvm
  514. Xlibln        usr.lib/libln
  515. Xliblwp        usr.lib/liblwp
  516. Xlibm        usr.lib/libm
  517. Xlibmp        usr.lib/libmp
  518. Xlibpixrect    usr.lib/libpixrect
  519. Xlibplot        usr.lib/libplot
  520. Xlibresolv    usr.lib/libresolv
  521. Xlibrpcsvc    usr.lib/librpcsvc
  522. Xlibtermlib    usr.lib/libtermlib
  523. Xliby        usr.lib/liby
  524. Xme        usr.lib/me
  525. Xms        usr.lib/ms
  526. Xsendmail    usr.lib/sendmail
  527. Xsun_tmac    usr.lib/tmac
  528. Xvfont        usr.lib/vfont
  529. X
  530. X# Programs that live in "usr.lib"
  531. XgetNAME        usr.lib Makefile getNAME
  532. Xmakekey        usr.lib Makefile makekey
  533. X
  534. X# Sub-directories of "5bin"
  535. X5diff3        5bin/diff3
  536. X5m4        5bin/m4
  537. X
  538. X# Sub-directories of "5bin", but use sources from other places
  539. X5cxref        -a 5bin/cxref usr.bin/cxref
  540. X5sed        -a 5bin/sed bin/sed
  541. X5lint        -a 5bin/lint lang/pcc lang/lint
  542. X
  543. X# Programs that live in "5bin"
  544. X5banner        5bin Makefile banner.c
  545. X5cat        5bin Makefile cat.c
  546. X5du        5bin Makefile du.c
  547. X5echo        5bin Makefile echo.c
  548. X5expr        5bin Makefile expr.c
  549. X5ls        5bin Makefile ls.c
  550. X5nohup        5bin Makefile nohup.c
  551. X5od        5bin Makefile od.c
  552. X5pg        5bin Makefile pg.c
  553. X5pr        5bin Makefile pr.c
  554. X5sum        5bin Makefile sum.c
  555. X5tabs        5bin Makefile tabs.c
  556. X5time        5bin Makefile time.c
  557. X5tr        5bin Makefile tr.c
  558. X5uname        5bin Makefile uname.c
  559. X
  560. X# Programs that live in "5bin", but use sources from other places
  561. X5chmod        -a 5bin/Makefile bin/chmod.c
  562. X5date        -a 5bin/Makefile bin/date.c
  563. X5grep        -a 5bin/Makefile bin/grep.c
  564. X5stty        -a 5bin/Makefile bin/stty.c
  565. X5col        -a 5bin/Makefile usr.bin/col.c
  566. X5sort        -a 5bin/Makefile usr.bin/sort.c
  567. X5touch        -a 5bin/Makefile usr.bin/touch.c
  568. X
  569. X# Sub-directories of "5lib"
  570. X5compile    5lib/compile
  571. X5libcurses    5lib/libcurses
  572. X5liby        5lib/liby
  573. X5terminfo    5lib/terminfo
  574. X
  575. X# Programs that live in "5lib"
  576. X# NONE
  577. X
  578. X# Programs that live in "prisma"
  579. Xcvs        prisma/cvs
  580. Xmicrokernel    prisma/microkernel
  581. Xtms        prisma/tms
  582. X
  583. X# Programs that live in "doctools"
  584. Xdcan        doctools/dcan
  585. Xditrev        doctools/ditrev
  586. Xditsee        doctools/ditsee
  587. Xeqn        doctools/eqn
  588. Xgrap        doctools/grap
  589. Xiprx        doctools/iprx
  590. Xm3        doctools/m3
  591. Xneqn        doctools/neqn
  592. Xpic        doctools/pic
  593. Xroff        doctools/roff
  594. Xtroff        doctools/roff
  595. Xtbl        doctools/tbl
  596. Xtgraph        doctools/tgraph
  597. Xtmac        doctools/tmac
  598. END_OF_FILE
  599. if test 14454 -ne `wc -c <'examples/modules'`; then
  600.     echo shar: \"'examples/modules'\" unpacked with wrong size!
  601. fi
  602. # end of 'examples/modules'
  603. fi
  604. if test -f 'src/commit.c' -a "${1}" != "-c" ; then 
  605.   echo shar: Will not clobber existing file \"'src/commit.c'\"
  606. else
  607. echo shar: Extracting \"'src/commit.c'\" \(21136 characters\)
  608. sed "s/^X//" >'src/commit.c' <<'END_OF_FILE'
  609. X#ifndef lint
  610. Xstatic char rcsid[] = "$Id: commit.c,v 1.28 89/11/19 23:40:32 berliner Exp $";
  611. X#endif !lint
  612. X
  613. X/*
  614. X *    Copyright (c) 1989, Brian Berliner
  615. X *
  616. X *    You may distribute under the terms of the GNU General Public License
  617. X *    as specified in the README file that comes with the CVS 1.0 kit.
  618. X *
  619. X * Commit Files
  620. X *
  621. X *    "commit" commits the present version to the RCS repository, AFTER
  622. X *    having done a test on conflicts.  The call is:
  623. X *        cvs commit [options] files...
  624. X *
  625. X *    "commit" accepts the following options:
  626. X *        -f        Force a commit, even if the RCS $Id string
  627. X *                is not found
  628. X *        -n        Causes "commit" to *not* run any commit prog
  629. X *        -a        Commits all files in the current directory
  630. X *                that have been modified.
  631. X *        -m 'message'    Does not start up the editor for the
  632. X *                log message; just gleans it from the
  633. X *                'message' argument.
  634. X *        -r Revision    Allows committing to a particular *numeric*
  635. X *                revision number.
  636. X *
  637. X *    Note that "commit" does not do a recursive commit.  You must do
  638. X *    "commit" in each directory where there are files that you'd
  639. X *    like to commit.
  640. X */
  641. X
  642. X#include <sys/param.h>
  643. X#include <sys/types.h>
  644. X#include <sys/stat.h>
  645. X#include <ctype.h>
  646. X#include "cvs.h"
  647. X
  648. Xstatic int force_commit_no_rcsid = 0;
  649. X
  650. Xextern int run_module_prog;
  651. X
  652. Xcommit(argc, argv)
  653. X    int argc;
  654. X    char *argv[];
  655. X{
  656. X    int commit_all = 0, err = 0;
  657. X    char *rev = "";            /* not NULL! */
  658. X    char line[MAXLINELEN], message[MAXMESGLEN];
  659. X    int c;
  660. X
  661. X    if (argc == -1)
  662. X    commit_usage();
  663. X    /*
  664. X     * For log purposes, do not allow "root" to commit files
  665. X     */
  666. X    if (geteuid() == 0)
  667. X    error(0, "cannot commit files as 'root'");
  668. X    optind = 1;
  669. X    while ((c = getopt(argc, argv, "fnam:r:")) != -1) {
  670. X    switch (c) {
  671. X    case 'f':
  672. X        force_commit_no_rcsid = 1;
  673. X        break;
  674. X    case 'n':
  675. X        run_module_prog = 0;
  676. X        break;
  677. X    case 'a':
  678. X        commit_all = 1;
  679. X        break;
  680. X    case 'm':
  681. X        use_editor = FALSE;
  682. X        if (strlen(optarg) >= sizeof(message)) {
  683. X        warn(0, "warning: message too long; truncated!");
  684. X        (void) strncpy(message, optarg, sizeof(message));
  685. X        message[sizeof(message) - 1] = '\0';
  686. X        } else
  687. X        (void) strcpy(message, optarg);
  688. X        break;
  689. X    case 'r':
  690. X        if (!isdigit(optarg[0]))
  691. X        error(0, "specified revision %s must be numeric!", optarg);
  692. X        rev = optarg;
  693. X        break;
  694. X    case '?':
  695. X    default:
  696. X        commit_usage();
  697. X        break;
  698. X    }
  699. X    }
  700. X    argc -= optind;
  701. X    argv += optind;
  702. X    if (!commit_all && argc == 0)
  703. X    error(0, "must specify the files you'd like to check-in");
  704. X    if (commit_all && argc != 0)
  705. X    error(0, "cannot specify files with the -a option");
  706. X    Name_Repository();
  707. X    Writer_Lock();
  708. X    if (commit_all) {
  709. X    Find_Names(&fileargc, fileargv, ALL);
  710. X    argc = fileargc;
  711. X    argv = fileargv;
  712. X    }
  713. X    if (rev[0] != '\0') {
  714. X    register int i;
  715. X    FILE *fptty;
  716. X
  717. X    fptty = open_file("/dev/tty", "r");
  718. X    printf("WARNING:\n");
  719. X    printf("\tCommitting with a specific revision number\n");
  720. X    printf("\tbypasses all consistency checks.  Are you abosulutely\n");
  721. X    printf("\tsure you want to continue (y/n) [n] ? ");
  722. X    (void) fflush(stdout);
  723. X    if (fgets(line, sizeof(line), fptty) == NULL ||
  724. X        (line[0] != 'y' && line[0] != 'Y')) {
  725. X        error(0, "commit of revision %s aborted", rev);
  726. X    }
  727. X    (void) fclose(fptty);
  728. X    /*
  729. X     * When committing with a specific revision number, we simply
  730. X     * fudge the lists that Collect_Sets() would have created for
  731. X     * us.  This is all so gross, but sometimes useful.
  732. X     */
  733. X    Clist[0] = Glist[0] = Mlist[0] = Olist[0] = Dlist[0] = '\0';
  734. X    Alist[0] = Rlist[0] = Wlist[0] = Llist[0] = Blist[0] = '\0';
  735. X    for (i = 0; i < argc; i++) {
  736. X        (void) strcat(Mlist, " ");
  737. X        (void) strcat(Mlist, argv[i]);
  738. X    }
  739. X    } else {
  740. X    err += Collect_Sets(argc, argv);
  741. X    }
  742. X    if (err == 0) {
  743. X    err += commit_process_lists(message, rev);
  744. X    if (err == 0 && run_module_prog) {
  745. X        char *cp;
  746. X        FILE *fp;
  747. X
  748. X        /*
  749. X         * It is not an error if Checkin.prog does not exist.
  750. X         */
  751. X        if ((fp = fopen(CVSADM_CIPROG, "r")) != NULL) {
  752. X        if (fgets(line, sizeof(line), fp) != NULL) {
  753. X            if ((cp = rindex(line, '\n')) != NULL)
  754. X            *cp = '\0';
  755. X            (void) sprintf(prog, "%s %s", line, Repository);
  756. X            printf("%s %s: Executing '%s'\n", progname, command, prog);
  757. X            (void) system(prog);
  758. X        }
  759. X        (void) fclose(fp);
  760. X        }
  761. X    }
  762. X    Update_Logfile(Repository, message);
  763. X    }
  764. X    Lock_Cleanup(0);
  765. X    exit(err);
  766. X}
  767. X
  768. X/*
  769. X * Process all the lists, returning the number of errors found.
  770. X */
  771. Xstatic
  772. Xcommit_process_lists(message, rev)
  773. X    char *message;
  774. X    char *rev;
  775. X{
  776. X    char line[MAXLISTLEN], fname[MAXPATHLEN], revision[50];
  777. X    FILE *fp;
  778. X    char *cp;
  779. X    int first, err = 0;
  780. X
  781. X    /*
  782. X     * Doesn't make much sense to commit a directory...
  783. X     */
  784. X    if (Dlist[0])
  785. X    warn(0, "committing directories ignored -%s", Dlist);
  786. X    /*
  787. X     * Is everything up-to-date?
  788. X     * Only if Glist, Olist, and Wlist are all NULL!
  789. X     */
  790. X    if (Glist[0] || Olist[0] || Wlist[0]) {
  791. X    (void) fprintf(stderr, "%s: the following files are not ", progname);
  792. X    (void) fprintf(stderr,
  793. X               "up to date; use '%s update' first:\n", progname);
  794. X    if (Glist[0] != '\0')
  795. X        (void) fprintf(stderr, "\t%s\n", Glist);
  796. X    if (Olist[0] != '\0')
  797. X        (void) fprintf(stderr, "\t%s\n", Olist);
  798. X    if (Wlist[0] != '\0')
  799. X        (void) fprintf(stderr, "\t%s\n", Wlist);
  800. X    Lock_Cleanup(0);
  801. X    exit(1);
  802. X    }
  803. X    /*
  804. X     * Is there anything to do in the first place?
  805. X     */
  806. X    if (Mlist[0] == '\0' && Rlist[0] == '\0' && Alist[0] == '\0')
  807. X    error(0, "there is nothing to commit!");
  808. X    /*
  809. X     * First we make sure that the file has an RCS $Id string in it
  810. X     * and if it does not, the user is prompted for verification to continue.
  811. X     */
  812. X    if (force_commit_no_rcsid == 0) {
  813. X    (void) strcpy(line, Mlist);
  814. X    (void) strcat(line, Alist);
  815. X    for (first = 1, cp = strtok(line, " \t"); cp;
  816. X        cp = strtok((char *)NULL, " \t")) {
  817. X        (void) sprintf(prog, "%s -s %s %s", GREP, RCSID_PAT, cp);
  818. X        if (system(prog) != 0) {
  819. X        if (first) {
  820. X            printf("%s %s: WARNING!\n", progname, command);
  821. X            printf("\tThe following file(s) do not contain an RCS $Id keyword:\n");
  822. X            first = 0;
  823. X        }
  824. X        printf("\t\t%s\n", cp);
  825. X        }
  826. X    }
  827. X    if (first == 0) {
  828. X        FILE *fptty = open_file("/dev/tty", "r");
  829. X        printf("\tAre you sure you want to continue (y/n) [n] ? ");
  830. X        (void) fflush(stdout);
  831. X        if (fgets(line, sizeof(line), fptty) == NULL ||
  832. X        (line[0] != 'y' && line[0] != 'Y')) {
  833. X        error(0, "commit aborted");
  834. X        }
  835. X        (void) fclose(fptty);
  836. X    }
  837. X    }
  838. X    if (use_editor)
  839. X    do_editor(message);
  840. X    /*
  841. X     * Mlist is the "modified, needs committing" list
  842. X     */
  843. X    (void) strcpy(line, Mlist);
  844. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  845. X    (void) strcpy(User, cp);
  846. X    (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  847. X    if (lock_RCS(rev) != 0)
  848. X        err++;
  849. X    }
  850. X    /*
  851. X     * Rlist is the "to be removed" list
  852. X     */
  853. X    (void) strcpy(line, Rlist);
  854. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  855. X    (void) strcpy(User, cp);
  856. X    (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  857. X    if (lock_RCS(rev) != 0)
  858. X        err++;
  859. X    }
  860. X    /*
  861. X     * Alist is the "to be added" list
  862. X     */
  863. X    (void) strcpy(line, Alist);
  864. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  865. X    (void) strcpy(User, cp);
  866. X    (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  867. X    (void) sprintf(prog, "%s/%s -i -t%s/%s%s", Rcsbin, RCS, CVSADM,
  868. X               User, CVSEXT_LOG);
  869. X    (void) sprintf(fname, "%s/%s%s", CVSADM, User, CVSEXT_OPT);
  870. X    fp = open_file(fname, "r");
  871. X    while (fgets(fname, sizeof(fname), fp) != NULL) {
  872. X        if ((cp = rindex(fname, '\n')) != NULL)
  873. X        *cp = '\0';
  874. X        (void) strcat(prog, " ");
  875. X        (void) strcat(prog, fname);
  876. X    }
  877. X    (void) fclose(fp);
  878. X    (void) strcat(prog, " ");
  879. X    (void) strcat(prog, Rcs);
  880. X    if (system(prog) == 0) {
  881. X        fix_rcs_modes(Rcs, User);
  882. X    } else {
  883. X        warn(0, "could not create %s", Rcs);
  884. X        err++;
  885. X    }
  886. X    }
  887. X    /*
  888. X     * If something failed, release all locks and restore the default
  889. X     * branches
  890. X     */
  891. X    if (err) {
  892. X    int didllist = 0;
  893. X    char *branch;
  894. X
  895. X    for (cp = strtok(Llist, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  896. X        didllist = 1;
  897. X        (void) strcpy(User, cp);
  898. X        (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  899. X        (void) sprintf(prog, "%s/%s -q -u %s", Rcsbin, RCS, Rcs);
  900. X        if (system(prog) != 0)
  901. X        warn(0, "could not UNlock %s", Rcs);
  902. X    }
  903. X    if (didllist) {
  904. X        for (cp=strtok(Blist, " \t"); cp; cp=strtok((char *)NULL, " \t")) {
  905. X        if ((branch = rindex(cp, ':')) == NULL)
  906. X            continue;
  907. X        *branch++ = '\0';
  908. X        (void) strcpy(User, cp);
  909. X        (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  910. X        (void) sprintf(prog, "%s/%s -q -b%s %s", Rcsbin, RCS,
  911. X                   branch, Rcs);
  912. X        if (system(prog) != 0)
  913. X            warn(0, "could not restore branch %s to %s", branch, Rcs);
  914. X        }
  915. X    }
  916. X    for (cp = strtok(Alist, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  917. X        (void) strcpy(User, cp);
  918. X        (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  919. X        (void) unlink(Rcs);
  920. X    }
  921. X    Lock_Cleanup(0);
  922. X    exit(1);
  923. X    }
  924. X    /*
  925. X     * Got them all, now go ahead;
  926. X     * First, add the files in the Alist
  927. X     */
  928. X    if (Alist[0] != '\0') {
  929. X    int maxrev, rev;
  930. X
  931. X    /* scan the entries file looking for the max revision number */
  932. X    fp = open_file(CVSADM_ENT, "r");
  933. X    maxrev = 0;
  934. X    while (fgets(line, sizeof(line), fp) != NULL) {
  935. X        rev = atoi(line);
  936. X        if (rev > maxrev)
  937. X        maxrev = rev;
  938. X    }
  939. X    if (maxrev == 0)
  940. X        maxrev = 1;
  941. X    (void) fclose(fp);
  942. X    (void) sprintf(revision, "-r%d", maxrev);
  943. X    (void) strcpy(line, Alist);
  944. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  945. X        (void) strcpy(User, cp);
  946. X        if (Checkin(revision, message) != 0)
  947. X        err++;
  948. X        (void) sprintf(fname, "%s/%s%s", CVSADM, User, CVSEXT_OPT);
  949. X        (void) unlink(fname);
  950. X        (void) sprintf(fname, "%s/%s%s", CVSADM, User, CVSEXT_LOG);
  951. X        (void) unlink(fname);
  952. X    }
  953. X    }
  954. X    /*
  955. X     * Everyone else uses the head as it is set in the RCS file,
  956. X     * or the revision that was specified on the command line.
  957. X     */
  958. X    if (rev[0] != '\0')
  959. X    (void) sprintf(revision, "-r%s", rev);
  960. X    else
  961. X    revision[0] = '\0';
  962. X    /*
  963. X     * Commit the user modified files in Mlist
  964. X     */
  965. X    (void) strcpy(line, Mlist);
  966. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  967. X    (void) strcpy(User, cp);
  968. X    if (Checkin(revision, message) != 0)
  969. X        err++;
  970. X    }
  971. X    /*
  972. X     * And remove the RCS files in Rlist, by placing it in the Attic
  973. X     */
  974. X    (void) strcpy(line, Rlist);
  975. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  976. X    int omask;
  977. X
  978. X    (void) strcpy(User, cp);
  979. X    (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  980. X    (void) sprintf(fname, "%s/%s", Repository, CVSATTIC);
  981. X    omask = umask(2);
  982. X    (void) mkdir(fname, 0777);
  983. X    (void) umask(omask);
  984. X    (void) sprintf(fname, "%s/%s/%s%s", Repository, CVSATTIC,
  985. X               User, RCSEXT);
  986. X    (void) sprintf(prog, "%s/%s -u -q %s", Rcsbin, RCS, Rcs);
  987. X    if ((system(prog) == 0 && rename(Rcs, fname) != -1) ||
  988. X        (!isreadable(Rcs) && isreadable(fname)))
  989. X        Scratch_Entry(User);
  990. X    else
  991. X        err++;
  992. X    }
  993. X    return (err);
  994. X}
  995. X
  996. X/*
  997. X * Attempt to place a lock on the RCS file; returns 0 if it could and
  998. X * 1 if it couldn't.  If the RCS file currently has a branch as the head,
  999. X * we must move the head back to the trunk before locking the file, and
  1000. X * be sure to put the branch back as the head if there are any errors.
  1001. X */
  1002. Xstatic
  1003. Xlock_RCS(rev)
  1004. X    char *rev;
  1005. X{
  1006. X    char branch[50];
  1007. X    int err = 0;
  1008. X
  1009. X    branch[0] = '\0';
  1010. X    /*
  1011. X     * For a specified, numeric revision of the form "1" or "1.1",
  1012. X     * (or when no revision is specified ""), definitely move the
  1013. X     * branch to the trunk before locking the RCS file.
  1014. X     *
  1015. X     * The assumption is that if there is more than one revision
  1016. X     * on the trunk, the head points to the trunk, not a branch...
  1017. X     * and as such, it's not necessary to move the head in this case.
  1018. X     */
  1019. X    if (numdots(rev) < 2) {
  1020. X    branch_number(Rcs, branch);
  1021. X    if (branch[0] != '\0') {
  1022. X        (void) sprintf(prog, "%s/%s -q -b %s", Rcsbin, RCS, Rcs);
  1023. X        if (system(prog) != 0) {
  1024. X        warn(0, "cannot change branch to default for %s", Rcs);
  1025. X        return (1);
  1026. X        }
  1027. X    }
  1028. X    (void) sprintf(prog, "%s/%s -q -l %s", Rcsbin, RCS, Rcs);
  1029. X    err = system(prog);
  1030. X    } else {
  1031. X    (void) sprintf(prog, "%s/%s -q -l%s %s 2>%s",
  1032. X               Rcsbin, RCS, rev, Rcs, DEVNULL);
  1033. X    (void) system(prog);
  1034. X    }
  1035. X    if (err == 0) {
  1036. X    (void) strcat(Llist, " ");
  1037. X    (void) strcat(Llist, User);
  1038. X    (void) strcat(Blist, " ");
  1039. X    (void) strcat(Blist, User);
  1040. X    if (branch[0] != '\0') {
  1041. X        (void) strcat(Blist, ":");
  1042. X        (void) strcat(Blist, branch);
  1043. X    }
  1044. X    return (0);
  1045. X    }
  1046. X    if (branch[0] != '\0') {
  1047. X    (void) sprintf(prog, "%s/%s -q -b%s %s", Rcsbin, RCS, branch, Rcs);
  1048. X    if (system(prog) != 0)
  1049. X        warn(0, "cannot restore branch to %s for %s", branch, Rcs);
  1050. X    }
  1051. X    return (1);
  1052. X}
  1053. X
  1054. X/*
  1055. X * A special function used only by lock_RCS() to determine if the current
  1056. X * head is pointed at a branch.  Returns the result in "branch" as a null
  1057. X * string if the trunk is the head, or as the branch number if the branch
  1058. X * is the head.
  1059. X */
  1060. Xstatic
  1061. Xbranch_number(rcs, branch)
  1062. X    char *rcs;
  1063. X    char *branch;
  1064. X{
  1065. X    char line[MAXLINELEN];
  1066. X    FILE *fp;
  1067. X    char *cp;
  1068. X
  1069. X    branch[0] = '\0';            /* Assume trunk is head */
  1070. X    fp = open_file(rcs, "r");
  1071. X    if (fgets(line, sizeof(line), fp) == NULL) {
  1072. X    (void) fclose(fp);
  1073. X    return;
  1074. X    }
  1075. X    if (fgets(line, sizeof(line), fp) == NULL) {
  1076. X    (void) fclose(fp);
  1077. X    return;
  1078. X    }
  1079. X    (void) fclose(fp);
  1080. X    if (strncmp(line, RCSBRANCH, sizeof(RCSBRANCH) - 1) != 0 ||
  1081. X    (cp = rindex(line, ';')) == NULL)
  1082. X    return;
  1083. X    *cp = '\0';                /* strip the ';' */
  1084. X    if ((cp = rindex(line, ' ')) == NULL &&
  1085. X    (cp = rindex(line, '\t')) == NULL)
  1086. X    return;
  1087. X    cp++;
  1088. X    if (*cp == NULL)
  1089. X    return;
  1090. X    (void) strcpy(branch, cp);
  1091. X}
  1092. X
  1093. X/*
  1094. X * Puts a standard header on the output which is either being prepared for
  1095. X * an editor session, or being sent to a logfile program.  The modified, added,
  1096. X * and removed files are included (if any) and formatted to look pretty.
  1097. X */
  1098. Xstatic
  1099. Xsetup_tmpfile(fp, prefix)
  1100. X    FILE *fp;
  1101. X    char *prefix;
  1102. X{
  1103. X    if (Mlist[0] != '\0') {
  1104. X    (void) fprintf(fp, "%sModified Files:\n", prefix);
  1105. X    fmt(fp, Mlist, prefix);
  1106. X    }
  1107. X    if (Alist[0] != '\0') {
  1108. X    (void) fprintf(fp, "%sAdded Files:\n", prefix);
  1109. X    fmt(fp, Alist, prefix);
  1110. X    }
  1111. X    if (Rlist[0] != '\0') {
  1112. X    (void) fprintf(fp, "%sRemoved Files:\n", prefix);
  1113. X    fmt(fp, Rlist, prefix);
  1114. X    }
  1115. X}
  1116. X
  1117. X/*
  1118. X * Breaks the files list into reasonable sized lines to avoid line
  1119. X * wrap...  all in the name of pretty output.
  1120. X */
  1121. Xstatic
  1122. Xfmt(fp, instring, prefix)
  1123. X    FILE *fp;
  1124. X    char *instring;
  1125. X    char *prefix;
  1126. X{
  1127. X    char line[MAXLINELEN];
  1128. X    char *cp;
  1129. X    int col;
  1130. X
  1131. X    (void) strcpy(line, instring);    /* since strtok() is destructive */
  1132. X    (void) fprintf(fp, "%s\t", prefix);
  1133. X    col = 8;                /* assumes that prefix is < 8 chars */
  1134. X    for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  1135. X    if ((col + strlen(cp)) > 70) {
  1136. X        (void) fprintf(fp, "\n%s\t", prefix);
  1137. X        col = 8;
  1138. X    }
  1139. X    (void) fprintf(fp, "%s ", cp);
  1140. X    col += strlen(cp) + 1;
  1141. X    }
  1142. X    (void) fprintf(fp, "\n%s\n", prefix);
  1143. X}
  1144. X
  1145. X/*
  1146. X * Builds a temporary file using setup_tmpfile() and invokes the user's
  1147. X * editor on the file.  The header garbage in the resultant file is then
  1148. X * stripped and the log message is stored in the "message" argument.
  1149. X */
  1150. Xstatic
  1151. Xdo_editor(message)
  1152. X    char *message;
  1153. X{
  1154. X    FILE *fp;
  1155. X    char line[MAXLINELEN], fname[MAXPATHLEN];
  1156. X    int fd;
  1157. X
  1158. X    message[0] = '\0';
  1159. X    (void) strcpy(fname, CVSTEMP);
  1160. X    if ((fd = mkstemp(fname)) < 0)
  1161. X    error(0, "cannot create temporary file %s", fname);
  1162. X    if ((fp = fdopen(fd, "w+")) == NULL)
  1163. X    error(0, "cannot create FILE * to %s", fname);
  1164. X    setup_tmpfile(fp, CVSEDITPREFIX);
  1165. X    (void) fprintf(fp, "%sEnter Log.  Lines beginning with '%s' are removed automatically\n",
  1166. X           CVSEDITPREFIX, CVSEDITPREFIX);
  1167. X    (void) fprintf(fp, "%s----------------------------------------------------------------------\n");
  1168. X    (void) fclose(fp);
  1169. X    (void) sprintf(prog, "%s %s", Editor, fname);
  1170. X    if (system(prog) != 0) {
  1171. X    (void) unlink(fname);
  1172. X    warn(0, "warning: editor session failed");
  1173. X    }
  1174. X    fp = open_file(fname, "r");
  1175. X    while (fgets(line, sizeof(line), fp) != NULL) {
  1176. X    if (strncmp(line, CVSEDITPREFIX, sizeof(CVSEDITPREFIX)-1) == 0)
  1177. X        continue;
  1178. X    if ((strlen(message) + strlen(line)) >= MAXMESGLEN) {
  1179. X        warn(0, "warning: log message truncated!");
  1180. X        break;
  1181. X    }
  1182. X    (void) strcat(message, line);
  1183. X    }
  1184. X    (void) fclose(fp);
  1185. X    (void) unlink(fname);
  1186. X}
  1187. X
  1188. X/*
  1189. X * Uses setup_tmpfile() to pass the updated message on directly to
  1190. X * any logfile programs that have a regular expression match for the
  1191. X * checked in directory in the source repository.  The log information
  1192. X * is fed into the specified program as standard input.
  1193. X */
  1194. XUpdate_Logfile(repository, message)
  1195. X    char *repository;
  1196. X    char *message;
  1197. X{
  1198. X    FILE *fp_info;
  1199. X    char logfile[MAXPATHLEN], title[MAXLISTLEN+MAXPATHLEN], line[MAXLINELEN];
  1200. X    char path[MAXPATHLEN], default_filter[MAXLINELEN];
  1201. X    char *exp, *filter, *cp, *short_repository;
  1202. X    int filter_run, line_number;
  1203. X
  1204. X    if (CVSroot == NULL) {
  1205. X    warn(0, "CVSROOT variable not set; no log message will be sent");
  1206. X    return;
  1207. X    }
  1208. X    (void) sprintf(logfile, "%s/%s", CVSroot, CVSROOTADM_LOGINFO);
  1209. X    if ((fp_info = fopen(logfile, "r")) == NULL) {
  1210. X    warn(0, "warning: cannot open %s", logfile);
  1211. X    return;
  1212. X    }
  1213. X    if (CVSroot != NULL)
  1214. X    (void) sprintf(path, "%s/", CVSroot);
  1215. X    else
  1216. X    (void) strcpy(path, REPOS_STRIP);
  1217. X    if (strncmp(repository, path, strlen(path)) == 0)
  1218. X    short_repository = repository + strlen(path);
  1219. X    else
  1220. X    short_repository = repository;
  1221. X    (void) sprintf(title, "'%s%s'", short_repository, Llist);
  1222. X    default_filter[0] = '\0';
  1223. X    filter_run = line_number = 0;
  1224. X    while (fgets(line, sizeof(line), fp_info) != NULL) {
  1225. X    line_number++;
  1226. X    if (line[0] == '#')
  1227. X        continue;
  1228. X    for (cp = line; *cp && isspace(*cp); cp++)
  1229. X        ;
  1230. X    if (*cp == '\0')
  1231. X        continue;            /* blank line */
  1232. X    for (exp = cp; *cp && !isspace(*cp); cp++)
  1233. X        ;
  1234. X    if (*cp != '\0')
  1235. X        *cp++ = '\0';
  1236. X    while (*cp && isspace(*cp))
  1237. X        cp++;
  1238. X    if (*cp == '\0') {
  1239. X        warn(0, "syntax error at line %d file %s; ignored",
  1240. X         line_number, logfile);
  1241. X        continue;
  1242. X    }
  1243. X    filter = cp;
  1244. X    if ((cp = rindex(filter, '\n')) != NULL)
  1245. X        *cp = '\0';            /* strip the newline */
  1246. X    /*
  1247. X     * At this point, exp points to the regular expression, and
  1248. X     * filter points to the program to exec.  Evaluate the regular
  1249. X     * expression against short_repository and exec the filter
  1250. X     * if it matches.
  1251. X     */
  1252. X    if (strcmp(exp, "DEFAULT") == 0) {
  1253. X        (void) strcpy(default_filter, filter);
  1254. X        continue;
  1255. X    }
  1256. X    /*
  1257. X     * For a regular expression of "ALL", send the log message
  1258. X     * to the requested filter *without* noting that a filter was run.
  1259. X     * This allows the "DEFAULT" regular expression to be more
  1260. X     * meaningful with all updates going to a master log file.
  1261. X     */
  1262. X    if (strcmp(exp, "ALL") == 0) {
  1263. X        (void) logfile_write(repository, filter, title, message);
  1264. X        continue;
  1265. X    }
  1266. X    if ((cp = re_comp(exp)) != NULL) {
  1267. X        warn(0, "bad regular expression at line %d file %s: %s",
  1268. X         line_number, logfile, cp);
  1269. X        continue;
  1270. X    }
  1271. X    if (re_exec(short_repository) == 0)
  1272. X        continue;            /* no match */
  1273. X    if (logfile_write(repository, filter, title, message) == 0)
  1274. X        filter_run = 1;
  1275. X    }
  1276. X    if (filter_run == 0 && default_filter[0] != '\0')
  1277. X    (void) logfile_write(repository, default_filter, title, message);
  1278. X}
  1279. X
  1280. X/*
  1281. X * Since some systems don't define this...
  1282. X */
  1283. X#ifndef MAXHOSTNAMELEN
  1284. X#define    MAXHOSTNAMELEN    64
  1285. X#endif !MAXHOSTNAMELEN
  1286. X
  1287. X/*
  1288. X * Writes some stuff to the logfile "filter" and returns the status of the
  1289. X * filter program.
  1290. X */
  1291. Xstatic
  1292. Xlogfile_write(repository, filter, title, message)
  1293. X    char *repository;
  1294. X    char *filter;
  1295. X    char *title;
  1296. X    char *message;
  1297. X{
  1298. X    char cwd[MAXPATHLEN], host[MAXHOSTNAMELEN];
  1299. X    FILE *fp;
  1300. X    char *cp;
  1301. X
  1302. X    /*
  1303. X     * A maximum of 6 %s arguments are supported in the filter
  1304. X     */
  1305. X    (void) sprintf(prog, filter, title, title, title, title, title, title);
  1306. X    if ((fp = popen(prog, "w")) == NULL) {
  1307. X    warn(0, "cannot write entry to log filter: %s", prog);
  1308. X    return (1);
  1309. X    }
  1310. X    if (gethostname(host, sizeof(host)) < 0)
  1311. X    (void) strcpy(host, "(unknown)");
  1312. X    (void) fprintf(fp, "Update of %s\n", repository);
  1313. X    (void) fprintf(fp, "In directory %s:%s\n\n", host,
  1314. X           (cp = getwd(cwd)) ? cp : cwd);
  1315. X    setup_tmpfile(fp, "");
  1316. X    (void) fprintf(fp, "Log Message:\n%s\n", message);
  1317. X    return (pclose(fp));
  1318. X}
  1319. X
  1320. X/*
  1321. X * Called when "add"ing files to the RCS respository, as it is necessary
  1322. X * to preserve the file modes in the same fashion that RCS does.  This would
  1323. X * be automatic except that we are placing the RCS ,v file very far away from
  1324. X * the user file, and I can't seem to convince RCS of the location of the
  1325. X * user file.  So we munge it here, after the ,v file has been successfully
  1326. X * initialized with "rcs -i".
  1327. X */
  1328. Xstatic
  1329. Xfix_rcs_modes(rcs, user)
  1330. X    char *rcs;
  1331. X    char *user;
  1332. X{
  1333. X    struct stat sb;
  1334. X
  1335. X    if (stat(user, &sb) != -1) {
  1336. X    (void) chmod(rcs, (int) sb.st_mode & ~0222);
  1337. X    }
  1338. X}
  1339. X
  1340. Xstatic
  1341. Xcommit_usage()
  1342. X{
  1343. X    (void) fprintf(stderr,
  1344. X    "%s %s [-fn] [-a] [-m 'message'] [-r revision] [files...]\n",
  1345. X           progname, command);
  1346. X    exit(1);
  1347. X}
  1348. END_OF_FILE
  1349. if test 21136 -ne `wc -c <'src/commit.c'`; then
  1350.     echo shar: \"'src/commit.c'\" unpacked with wrong size!
  1351. fi
  1352. # end of 'src/commit.c'
  1353. fi
  1354. if test -f 'src/partime.c' -a "${1}" != "-c" ; then 
  1355.   echo shar: Will not clobber existing file \"'src/partime.c'\"
  1356. else
  1357. echo shar: Extracting \"'src/partime.c'\" \(14739 characters\)
  1358. sed "s/^X//" >'src/partime.c' <<'END_OF_FILE'
  1359. X#ifndef lint
  1360. Xstatic char rcsid[] = "$Id: partime.c,v 1.1 89/05/09 11:51:02 berliner Exp $";
  1361. X#endif
  1362. X
  1363. X/*
  1364. X * PARTIME        parse date/time string into a TM structure
  1365. X *
  1366. X * Usage:
  1367. X *      #include "time.h"             -- expanded tm structure
  1368. X *    char *str; struct tm *tp;
  1369. X *    partime(str,tp);
  1370. X * Returns:
  1371. X *    0 if parsing failed
  1372. X *    else time values in specified TM structure (unspecified values
  1373. X *        set to TMNULL)
  1374. X * Notes:
  1375. X *    This code is quasi-public; it may be used freely in like software.
  1376. X *    It is not to be sold, nor used in licensed software without
  1377. X *    permission of the author.
  1378. X *    For everyone's benefit, please report bugs and improvements!
  1379. X *     Copyright 1980 by Ken Harrenstien, SRI International.
  1380. X *    (ARPANET: KLH @ SRI)
  1381. X */
  1382. X
  1383. X/* Hacknotes:
  1384. X *    If parsing changed so that no backup needed, could perhaps modify
  1385. X *        to use a FILE input stream.  Need terminator, though.
  1386. X *    Perhaps should return 0 on success, else a non-zero error val?
  1387. X *    Flush AMPM from TM structure and handle locally within PARTIME,
  1388. X *        like midnight/noon?
  1389. X */
  1390. X
  1391. X#include <stdio.h>
  1392. X#include <ctype.h>
  1393. X#include "rcstime.h"
  1394. X
  1395. X#ifndef lint
  1396. Xstatic char timeid[] = TIMEID;
  1397. X#endif
  1398. X
  1399. Xstruct tmwent {
  1400. X    char *went;
  1401. X    long wval;    /* must be big enough to hold pointer or integer */
  1402. X    char wflgs;
  1403. X    char wtype;
  1404. X};
  1405. X    /* wflgs */
  1406. X#define TWSPEC 01    /* Word wants special processing */
  1407. X#define TWTIME 02    /* Word is a time value (absence implies date) */
  1408. X#define TWDST  04    /* Word is a DST-type timezone */
  1409. X#define TW1200 010    /* Word is NOON or MIDNIGHT (sigh) */
  1410. X
  1411. Xint pt12hack();
  1412. Xint ptnoise();
  1413. Xstruct tmwent tmwords [] = {
  1414. X    {"january",      0, 0, TM_MON},
  1415. X    {"february",     1, 0, TM_MON},
  1416. X    {"march",        2, 0, TM_MON},
  1417. X    {"april",        3, 0, TM_MON},
  1418. X    {"may",          4, 0, TM_MON},
  1419. X    {"june",         5, 0, TM_MON},
  1420. X    {"july",         6, 0, TM_MON},
  1421. X    {"august",       7, 0, TM_MON},
  1422. X    {"september",    8, 0, TM_MON},
  1423. X    {"october",      9, 0, TM_MON},
  1424. X    {"november",     10, 0, TM_MON},
  1425. X    {"december",     11, 0, TM_MON},
  1426. X
  1427. X    {"sunday",       0, 0, TM_WDAY},
  1428. X    {"monday",       1, 0, TM_WDAY},
  1429. X    {"tuesday",      2, 0, TM_WDAY},
  1430. X    {"wednesday",    3, 0, TM_WDAY},
  1431. X    {"thursday",     4, 0, TM_WDAY},
  1432. X    {"friday",       5, 0, TM_WDAY},
  1433. X    {"saturday",     6, 0, TM_WDAY},
  1434. X
  1435. X    {"gmt",          0*60, TWTIME, TM_ZON},   /* Greenwich */
  1436. X    {"gst",          0*60, TWTIME, TM_ZON},
  1437. X    {"gdt",          0*60, TWTIME+TWDST, TM_ZON},     /* ?? */
  1438. X
  1439. X    {"ast",          4*60, TWTIME, TM_ZON},   /* Atlantic */
  1440. X    {"est",          5*60, TWTIME, TM_ZON},   /* Eastern */
  1441. X    {"cst",          6*60, TWTIME, TM_ZON},   /* Central */
  1442. X    {"mst",          7*60, TWTIME, TM_ZON},   /* Mountain */
  1443. X    {"pst",          8*60, TWTIME, TM_ZON},   /* Pacific */
  1444. X    {"yst",          9*60, TWTIME, TM_ZON},   /* Yukon */
  1445. X    {"hst",          10*60, TWTIME, TM_ZON},  /* Hawaii */
  1446. X    {"bst",          11*60, TWTIME, TM_ZON},  /* Bering */
  1447. X
  1448. X    {"adt",          4*60, TWTIME+TWDST, TM_ZON},     /* Atlantic */
  1449. X    {"edt",          5*60, TWTIME+TWDST, TM_ZON},     /* Eastern */
  1450. X    {"cdt",          6*60, TWTIME+TWDST, TM_ZON},     /* Central */
  1451. X    {"mdt",          7*60, TWTIME+TWDST, TM_ZON},     /* Mountain */
  1452. X    {"pdt",          8*60, TWTIME+TWDST, TM_ZON},     /* Pacific */
  1453. X    {"ydt",          9*60, TWTIME+TWDST, TM_ZON},     /* Yukon */
  1454. X    {"hdt",          10*60, TWTIME+TWDST, TM_ZON},    /* Hawaii */
  1455. X    {"bdt",          11*60, TWTIME+TWDST, TM_ZON},    /* Bering */
  1456. X
  1457. X    {"daylight",     1, TWTIME+TWDST, TM_ZON},        /* Local Daylight */
  1458. X    {"standard",     1, TWTIME, TM_ZON},      /* Local Standard */
  1459. X    {"std",          1, TWTIME, TM_ZON},      /*   "       "    */
  1460. X
  1461. X    {"am",           1, TWTIME, TM_AMPM},
  1462. X    {"pm",           2, TWTIME, TM_AMPM},
  1463. X    {"noon",         12,TWTIME+TW1200, 0},    /* Special frobs */
  1464. X    {"midnight",     0, TWTIME+TW1200, 0},
  1465. X    {"at",           (long)ptnoise, TWSPEC, 0},    /* Noise word */
  1466. X
  1467. X    {0, 0, 0, 0},             /* Zero entry to terminate searches */
  1468. X};
  1469. X
  1470. X#define TMWILD (-2)    /* Value meaning item specified as wild-card */
  1471. X            /* (May use someday...) */
  1472. X
  1473. Xstruct token {
  1474. X    char *tcp;    /* pointer to string */
  1475. X    int tcnt;    /* # chars */
  1476. X    char tbrk;    /* "break" char */
  1477. X    char tbrkl;    /* last break char */
  1478. X    char tflg;    /* 0 = alpha, 1 = numeric */
  1479. X    union {         /* Resulting value; */
  1480. X        int tnum;/* either a #, or */
  1481. X        struct tmwent *ttmw;/* ptr to a tmwent. */
  1482. X    } tval;
  1483. X};
  1484. X
  1485. Xpartime(astr, atm)
  1486. Xchar *astr;
  1487. Xstruct tm *atm;
  1488. X{    register int *tp;
  1489. X    register struct tmwent *twp;
  1490. X    register int i;
  1491. X    struct token btoken, atoken;
  1492. X    char *cp, ch;
  1493. X    int ord, midnoon;
  1494. X    int (*aproc)();
  1495. X
  1496. X    tp = (int *)atm;
  1497. X    zaptime(tp);             /* Initialize the TM structure */
  1498. X    midnoon = TMNULL;        /* and our own temp stuff */
  1499. X    btoken.tcnt = btoken.tbrkl = 0;
  1500. X    btoken.tcp = astr;
  1501. X
  1502. Xdomore:
  1503. X    if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))    /* Get a token */
  1504. X      {     if(btoken.tval.tnum) return(0);         /* Read error? */
  1505. X        if(midnoon != TMNULL)            /* EOF, wrap up */
  1506. X            return(pt12hack(tp, midnoon));
  1507. X        return(1);                /* Win return! */
  1508. X      }
  1509. X    if(btoken.tflg == 0)        /* Alpha? */
  1510. X      {     twp = btoken.tval.ttmw;         /* Yes, get ptr to entry */
  1511. X        if(twp->wflgs&TWSPEC)        /* Special alpha crock */
  1512. X          {     aproc = (int (*) ()) (twp->wval);
  1513. X            if(!(*aproc)(tp, twp, &btoken))
  1514. X                return(0);    /* ERR: special word err */
  1515. X            goto domore;
  1516. X          }
  1517. X        if(twp->wflgs&TW1200)
  1518. X            if(ptstash(&midnoon,(int)twp->wval))
  1519. X                return(0);    /* ERR: noon/midnite clash */
  1520. X            else goto domore;
  1521. X        if(ptstash(&tp[twp->wtype],(int)twp->wval))
  1522. X            return(0);        /* ERR: val already set */
  1523. X        if(twp->wtype == TM_ZON)    /* If was zone, hack DST */
  1524. X            if(ptstash(&tp[TM_ISDST],(twp->wflgs&TWDST)))
  1525. X                return(0);    /* ERR: DST conflict */
  1526. X        goto domore;
  1527. X      }
  1528. X
  1529. X    /* Token is number.  Lots of hairy heuristics. */
  1530. X    if(btoken.tcnt >= 7)    /* More than 6 digits in string? */
  1531. X        return(0);    /* ERR: number too big */
  1532. X    if(btoken.tcnt == 6)    /* 6 digits = HHMMSS.  Needs special crock */
  1533. X      {            /* since 6 digits are too big for integer! */
  1534. X        i = (btoken.tcp[0]-'0')*10    /* Gobble 1st 2 digits */
  1535. X           + btoken.tcp[1]-'0';
  1536. X        btoken.tcnt = 2;        /* re-read last 4 chars */
  1537. X        goto coltime;
  1538. X      }
  1539. X
  1540. X    i = btoken.tval.tnum;   /* Value now known to be valid; get it. */
  1541. X    if( btoken.tcnt == 5    /*  5 digits = HMMSS */
  1542. X     || btoken.tcnt == 3)    /*  3 digits = HMM   */
  1543. X      {    if(btoken.tcnt != 3)
  1544. X            if(ptstash(&tp[TM_SEC], i%100))
  1545. X                return(0);    /* ERR: sec conflict */
  1546. X            else i /= 100;
  1547. Xhhmm4:        if(ptstash(&tp[TM_MIN], i%100))
  1548. X            return(0);        /* ERR: min conflict */
  1549. X        i /= 100;
  1550. Xhh2:            if(ptstash(&tp[TM_HOUR], i))
  1551. X            return(0);        /* ERR: hour conflict */
  1552. X        goto domore;
  1553. X      }
  1554. X
  1555. X    if(btoken.tcnt == 4)    /* 4 digits = YEAR or HHMM */
  1556. X      {    if(tp[TM_YEAR] != TMNULL) goto hhmm4;    /* Already got yr? */
  1557. X        if(tp[TM_HOUR] != TMNULL) goto year4;    /* Already got hr? */
  1558. X        if((i%100) > 59) goto year4;        /* MM >= 60? */
  1559. X        if(btoken.tbrk == ':')            /* HHMM:SS ? */
  1560. X            if( ptstash(&tp[TM_HOUR],i/100)
  1561. X             || ptstash(&tp[TM_MIN], i%100))
  1562. X                return(0);        /* ERR: hr/min clash */
  1563. X            else goto coltm2;        /* Go handle SS */
  1564. X        if(btoken.tbrk != ',' && btoken.tbrk != '/'
  1565. X          && ptitoken(btoken.tcp+btoken.tcnt,&atoken)    /* Peek */
  1566. X          && atoken.tflg == 0            /* alpha */
  1567. X          && (atoken.tval.ttmw->wflgs&TWTIME))  /* HHMM-ZON */
  1568. X            goto hhmm4;
  1569. X        if(btoken.tbrkl == '-'        /* DD-Mon-YYYY */
  1570. X          || btoken.tbrkl == ','    /* Mon DD, YYYY */
  1571. X          || btoken.tbrkl == '/'    /* MM/DD/YYYY */
  1572. X          || btoken.tbrkl == '.'    /* DD.MM.YYYY */
  1573. X          || btoken.tbrk == '-'        /* YYYY-MM-DD */
  1574. X            ) goto year4;
  1575. X        goto hhmm4;            /* Give up, assume HHMM. */
  1576. X      }
  1577. X
  1578. X    /* From this point on, assume tcnt == 1 or 2 */
  1579. X    /* 2 digits = YY, MM, DD, or HH (MM and SS caught at coltime) */
  1580. X    if(btoken.tbrk == ':')        /* HH:MM[:SS] */
  1581. X        goto coltime;        /*  must be part of time. */
  1582. X    if(i > 31) goto yy2;        /* If >= 32, only YY poss. */
  1583. X
  1584. X    /* Check for numerical-format date */
  1585. X    for (cp = "/-."; ch = *cp++;)
  1586. X      {    ord = (ch == '.' ? 0 : 1);    /* n/m = D/M or M/D */
  1587. X        if(btoken.tbrk == ch)            /* "NN-" */
  1588. X          {    if(btoken.tbrkl != ch)
  1589. X              {    if(ptitoken(btoken.tcp+btoken.tcnt,&atoken)
  1590. X                  && atoken.tflg == 0
  1591. X                  && atoken.tval.ttmw->wtype == TM_MON)
  1592. X                    goto dd2;
  1593. X                if(ord)goto mm2; else goto dd2; /* "NN-" */
  1594. X              }                /* "-NN-" */
  1595. X            if(tp[TM_DAY] == TMNULL
  1596. X            && tp[TM_YEAR] != TMNULL)    /* If "YY-NN-" */
  1597. X                goto mm2;        /* then always MM */
  1598. X            if(ord)goto dd2; else goto mm2;
  1599. X          }
  1600. X        if(btoken.tbrkl == ch            /* "-NN" */
  1601. X          && tp[ord ? TM_MON : TM_DAY] != TMNULL)
  1602. X            if(tp[ord ? TM_DAY : TM_MON] == TMNULL)    /* MM/DD */
  1603. X                if(ord)goto dd2; else goto mm2;
  1604. X            else goto yy2;            /* "-YY" */
  1605. X      }
  1606. X
  1607. X    /* At this point only YY, DD, and HH are left.
  1608. X     * YY is very unlikely since value is <= 32 and there was
  1609. X     * no numerical format date.  Make one last try at YY
  1610. X     * before dropping through to DD vs HH code.
  1611. X     */
  1612. X    if(btoken.tcnt == 2        /* If 2 digits */
  1613. X      && tp[TM_HOUR] != TMNULL    /* and already have hour */
  1614. X      && tp[TM_DAY] != TMNULL    /* and day, but  */
  1615. X      && tp[TM_YEAR] == TMNULL)    /* no year, then assume */
  1616. X        goto yy2;        /* that's what we have. */
  1617. X
  1618. X    /* Now reduced to choice between HH and DD */
  1619. X    if(tp[TM_HOUR] != TMNULL) goto dd2;    /* Have hour? Assume day. */
  1620. X    if(tp[TM_DAY] != TMNULL) goto hh2;    /* Have day? Assume hour. */
  1621. X    if(i > 24) goto dd2;            /* Impossible HH means DD */
  1622. X    if(!ptitoken(btoken.tcp+btoken.tcnt, &atoken))    /* Read ahead! */
  1623. X        if(atoken.tval.tnum) return(0); /* ERR: bad token */
  1624. X        else goto dd2;            /* EOF, assume day. */
  1625. X    if( atoken.tflg == 0        /* If next token is an alpha */
  1626. X     && atoken.tval.ttmw->wflgs&TWTIME)  /* time-spec, assume hour */
  1627. X        goto hh2;        /* e.g. "3 PM", "11-EDT"  */
  1628. X
  1629. Xdd2:    if(ptstash(&tp[TM_DAY],i))    /* Store day (1 based) */
  1630. X        return(0);
  1631. X    goto domore;
  1632. X
  1633. Xmm2:    if(ptstash(&tp[TM_MON], i-1))    /* Store month (make zero based) */
  1634. X        return(0);
  1635. X    goto domore;
  1636. X
  1637. Xyy2:    i += 1900;
  1638. Xyear4:    if(ptstash(&tp[TM_YEAR],i))    /* Store year (full number) */
  1639. X        return(0);        /* ERR: year conflict */
  1640. X    goto domore;
  1641. X
  1642. X    /* Hack HH:MM[[:]SS] */
  1643. Xcoltime:
  1644. X    if(ptstash(&tp[TM_HOUR],i)) return(0);
  1645. X    if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
  1646. X        return(!btoken.tval.tnum);
  1647. X    if(!btoken.tflg) return(0);    /* ERR: HH:<alpha> */
  1648. X    if(btoken.tcnt == 4)        /* MMSS */
  1649. X        if(ptstash(&tp[TM_MIN],btoken.tval.tnum/100)
  1650. X          || ptstash(&tp[TM_SEC],btoken.tval.tnum%100))
  1651. X            return(0);
  1652. X        else goto domore;
  1653. X    if(btoken.tcnt != 2
  1654. X      || ptstash(&tp[TM_MIN],btoken.tval.tnum))
  1655. X        return(0);        /* ERR: MM bad */
  1656. X    if(btoken.tbrk != ':') goto domore;    /* Seconds follow? */
  1657. Xcoltm2:    if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
  1658. X        return(!btoken.tval.tnum);
  1659. X    if(!btoken.tflg || btoken.tcnt != 2    /* Verify SS */
  1660. X      || ptstash(&tp[TM_SEC], btoken.tval.tnum))
  1661. X        return(0);        /* ERR: SS bad */
  1662. X    goto domore;
  1663. X}
  1664. X
  1665. X/* Store date/time value, return 0 if successful.
  1666. X * Fails if entry already set to a different value.
  1667. X */
  1668. Xptstash(adr,val)
  1669. Xint *adr;
  1670. X{    register int *a;
  1671. X    if( *(a=adr) != TMNULL)
  1672. X        return(*a != val);
  1673. X    *a = val;
  1674. X    return(0);
  1675. X}
  1676. X
  1677. X/* This subroutine is invoked for NOON or MIDNIGHT when wrapping up
  1678. X * just prior to returning from partime.
  1679. X */
  1680. Xpt12hack(atp, aval)
  1681. Xint *atp, aval;
  1682. X{    register int *tp, i, h;
  1683. X    tp = atp;
  1684. X    if (((i=tp[TM_MIN]) && i != TMNULL)    /* Ensure mins, secs */
  1685. X     || ((i=tp[TM_SEC]) && i != TMNULL))    /* are 0 or unspec'd */
  1686. X        return(0);            /* ERR: MM:SS not 00:00 */
  1687. X    i = aval;            /* Get 0 or 12 (midnite or noon) */
  1688. X    if ((h = tp[TM_HOUR]) == TMNULL    /* If hour unspec'd, win */
  1689. X     || h == 12)            /* or if 12:00 (matches either) */
  1690. X        tp[TM_HOUR] = i;    /* Then set time */
  1691. X    else if(!(i == 0        /* Nope, but if midnight and */
  1692. X        &&(h == 0 || h == 24)))    /* time matches, can pass. */
  1693. X            return(0);    /* ERR: HH conflicts */
  1694. X    tp[TM_AMPM] = TMNULL;        /* Always reset this value if won */
  1695. X    return(1);
  1696. X}
  1697. X
  1698. X/* Null routine for no-op tokens */
  1699. X
  1700. Xptnoise() { return(1); }
  1701. X
  1702. X/* Get a token and identify it to some degree.
  1703. X * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
  1704. X * hit error of some sort
  1705. X */
  1706. X
  1707. Xptitoken(astr, tkp)
  1708. Xregister struct token *tkp;
  1709. Xchar *astr;
  1710. X{
  1711. X    register char *cp;
  1712. X    register int i;
  1713. X
  1714. X    tkp->tval.tnum = 0;
  1715. X    if(pttoken(astr,tkp) == 0)
  1716. X#ifdef DEBUG
  1717. X    VOID printf("EOF\n");
  1718. X#endif DEBUG
  1719. X        return(0);
  1720. X    cp = tkp->tcp;
  1721. X
  1722. X#ifdef DEBUG
  1723. X    i = cp[tkp->tcnt];
  1724. X    cp[tkp->tcnt] = 0;
  1725. X    VOID printf("Token: \"%s\" ",cp);
  1726. X    cp[tkp->tcnt] = i;
  1727. X#endif DEBUG
  1728. X
  1729. X    if(tkp->tflg)
  1730. X        for(i = tkp->tcnt; i > 0; i--)
  1731. X            tkp->tval.tnum = (int)tkp->tval.tnum*10 + ((*cp++)-'0');
  1732. X    else
  1733. X      {     i = ptmatchstr(cp, tkp->tcnt, tmwords);
  1734. X        tkp->tval.tnum = i ? i : -1;         /* Set -1 for error */
  1735. X
  1736. X#ifdef DEBUG
  1737. X        if(!i) VOID printf("Not found!\n");
  1738. X#endif DEBUG
  1739. X
  1740. X        if(!i) return(0);
  1741. X      }
  1742. X
  1743. X#ifdef DEBUG
  1744. X    if(tkp->tflg)
  1745. X        VOID printf("Val: %d.\n",tkp->tval.tnum);
  1746. X    else VOID printf("Found: \"%s\", val: %d., type %d\n",
  1747. X        tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
  1748. X#endif DEBUG
  1749. X
  1750. X    return(1);
  1751. X}
  1752. X
  1753. X/* Read token from input string into token structure */
  1754. Xpttoken(astr,tkp)
  1755. Xregister struct token *tkp;
  1756. Xchar *astr;
  1757. X{
  1758. X    register char *cp;
  1759. X    register int c;
  1760. X
  1761. X    tkp->tcp = cp = astr;
  1762. X    tkp->tbrkl = tkp->tbrk;        /* Set "last break" */
  1763. X    tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
  1764. X
  1765. X    while(c = *cp++)
  1766. X      {    switch(c)
  1767. X          {    case ' ': case '\t':    /* Flush all whitespace */
  1768. X                while((c = *cp++) && isspace(c));
  1769. X                cp--;        /* Drop thru to handle brk */
  1770. X            case '(': case ')':    /* Perhaps any non-alphanum */
  1771. X            case '-': case ',':    /* shd qualify as break? */
  1772. X            case '/': case ':': case '.':    /* Break chars */
  1773. X                if(tkp->tcnt == 0)    /* If no token yet */
  1774. X                  {    tkp->tcp = cp;    /* ignore the brk */
  1775. X                    tkp->tbrkl = c;
  1776. X                      continue;    /* and go on. */
  1777. X                  }
  1778. X                tkp->tbrk = c;
  1779. X                return(tkp->tcnt);
  1780. X          }
  1781. X        if(tkp->tcnt == 0)        /* If first char of token, */
  1782. X            tkp->tflg = isdigit(c);    /*    determine type */
  1783. X          if(( isdigit(c) &&  tkp->tflg)    /* If not first, make sure */
  1784. X         ||(!isdigit(c) && !tkp->tflg))    /*    char matches type */
  1785. X            tkp->tcnt++;        /* Win, add to token. */
  1786. X        else {
  1787. X            cp--;            /* Wrong type, back up */
  1788. X            tkp->tbrk = c;
  1789. X            return(tkp->tcnt);
  1790. X          }
  1791. X      }
  1792. X    return(tkp->tcnt);        /* When hit EOF */
  1793. X}
  1794. X
  1795. X
  1796. Xptmatchstr(astr,cnt,astruc)
  1797. Xchar *astr;
  1798. Xint cnt;
  1799. Xstruct tmwent *astruc;
  1800. X{    register char *cp, *mp;
  1801. X    register int c;
  1802. X    struct tmwent *lastptr;
  1803. X    struct integ { int word; };   /* For getting at array ptr */
  1804. X    int i;
  1805. X
  1806. X    lastptr = 0;
  1807. X    for(;mp = (char *)((struct integ *)astruc)->word; astruc += 1)
  1808. X      {    cp = astr;
  1809. X        for(i = cnt; i > 0; i--)
  1810. X          {    switch((c = *cp++) ^ *mp++)    /* XOR the chars */
  1811. X              {    case 0: continue;    /* Exact match */
  1812. X                case 040: if(isalpha(c))
  1813. X                    continue;
  1814. X              }
  1815. X            break;
  1816. X          }
  1817. X        if(i==0)
  1818. X            if(*mp == 0) return((unsigned int)astruc);    /* Exact match */
  1819. X            else if(lastptr) return(0);    /* Ambiguous */
  1820. X            else lastptr = astruc;        /* 1st ambig */
  1821. X      }
  1822. X    return((unsigned int)lastptr);
  1823. X}
  1824. X
  1825. X
  1826. X
  1827. Xzaptime(tp)
  1828. Xregister int *tp;
  1829. X/* clears tm structure pointed to by tp */
  1830. X{    register int i;
  1831. X    i = (sizeof (struct tm))/(sizeof (int));
  1832. X    do *tp++ = TMNULL;        /* Set entry to "unspecified" */
  1833. X    while(--i);            /* Faster than FOR */
  1834. X}
  1835. END_OF_FILE
  1836. if test 14739 -ne `wc -c <'src/partime.c'`; then
  1837.     echo shar: \"'src/partime.c'\" unpacked with wrong size!
  1838. fi
  1839. # end of 'src/partime.c'
  1840. fi
  1841. echo shar: End of archive 5 \(of 7\).
  1842. cp /dev/null ark5isdone
  1843. MISSING=""
  1844. for I in 1 2 3 4 5 6 7 ; do
  1845.     if test ! -f ark${I}isdone ; then
  1846.     MISSING="${MISSING} ${I}"
  1847.     fi
  1848. done
  1849. if test "${MISSING}" = "" ; then
  1850.     echo You have unpacked all 7 archives.
  1851.     rm -f ark[1-9]isdone
  1852. else
  1853.     echo You still need to unpack the following archives:
  1854.     echo "        " ${MISSING}
  1855. fi
  1856. ##  End of shell archive.
  1857. exit 0
  1858. exit 0 # Just in case...
  1859.