home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i019: Brian Berliner's concurrent RCS system, Part05/07
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 11b1db10 c67b1e76 f8b8c43e 063bd5be
-
- Submitted-by: Brian Berliner <berliner@prisma.com>
- Posting-number: Volume 22, Issue 19
- Archive-name: cvs-berliner/part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 7)."
- # Contents: examples/modules src/commit.c src/partime.c
- # Wrapped by rsalz@litchi.bbn.com on Thu May 3 16:59:05 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'examples/modules' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'examples/modules'\"
- else
- echo shar: Extracting \"'examples/modules'\" \(14454 characters\)
- sed "s/^X//" >'examples/modules' <<'END_OF_FILE'
- X#
- X# CVS Modules file for Prisma sources
- X# $Id: modules,v 1.1 89/08/25 00:00:15 berliner Exp $
- X#
- X# Three differnt line formats are valid:
- X# key -a aliases...
- X# key [options] directory
- X# key [options] directory files...
- X#
- X# Where "options" are composed of:
- X# -i prog Run "prog" on checkin of files
- X# -o prog Run "prog" on "checkout" of files
- X# -t prog Run "prog" on tagging of files
- X#
- X
- X# Convenient aliases
- Xworld -a .
- Xkernel -a sys lang/adb sparcsim
- X
- X# CVSROOT.adm support
- XCVSROOT -i /usr/local/bin/mkmodules CVSROOT.adm
- XCVSROOT.adm -i /usr/local/bin/mkmodules CVSROOT.adm
- Xmodules -i /usr/local/bin/mkmodules CVSROOT.adm modules
- Xloginfo -i /usr/local/bin/mkmodules CVSROOT.adm loginfo
- X
- X# The "sys" entry exists only to make symbolic links after checkout
- Xsys -o sys/tools/make_links sys
- X
- X# Sub-directories of "bin"
- Xawk bin/awk
- Xcsh bin/csh
- Xdiff bin/diff
- Xmake bin/make
- Xsed bin/sed
- Xsh bin/sh
- X
- X# Programs that live in "bin"
- Xcat bin Makefile cat.c
- Xchgrp bin Makefile chgrp.c
- Xchmod bin Makefile chmod.c
- Xcmp bin Makefile cmp.c
- Xcp bin Makefile cp.c
- Xdate bin Makefile date.c
- Xdd bin Makefile dd.c
- Xdf bin Makefile df.c
- Xdomainname bin Makefile domainname.c
- Xdu bin Makefile du.c
- Xecho bin Makefile echo.c
- Xed bin Makefile ed.c
- Xenv bin Makefile env.c
- Xexpr bin Makefile expr.c
- Xgrep bin Makefile grep.c
- Xhostid bin Makefile hostid.c
- Xhostname bin Makefile hostname.c
- Xkill bin Makefile kill.c
- Xldd bin Makefile ldd.c
- Xline bin Makefile line.c
- Xln bin Makefile ln.c
- Xlogin bin Makefile login.c
- Xls bin Makefile ls.c
- Xmail bin Makefile mail.c
- Xmkdir bin Makefile mkdir.c
- Xmt bin Makefile mt.c
- Xmv bin Makefile mv.c
- Xnewgrp bin Makefile newgrp.c
- Xnice bin Makefile nice.c
- Xod bin Makefile od.c
- Xpagesize bin Makefile pagesize.c
- Xpasswd bin Makefile passwd.c
- Xpr bin Makefile pr.c
- Xps bin Makefile ps.c
- Xpwd bin Makefile pwd.c
- Xrm bin Makefile rm.c
- Xrmail bin Makefile rmail.c
- Xrmdir bin Makefile rmdir.c
- Xstty bin Makefile stty.c
- Xsu bin Makefile su.c
- Xsync bin Makefile sync.c
- Xtar bin Makefile tar.c
- Xtee bin Makefile tee.c
- Xtest bin Makefile test.c
- Xtime bin Makefile time.c
- Xwall bin Makefile wall.c
- Xwho bin Makefile who.c
- Xwrite bin Makefile write.c
- X
- X# Sub-directories of "etc"
- Xdump etc/dump
- Xfiles etc/files
- Xfsck etc/fsck
- Xgetty etc/getty
- Xin.routed etc/in.routed
- Xrestore etc/restore
- Xrpc.lockd etc/rpc.lockd
- Xrpc.statd etc/rpc.statd
- X
- X# Programs that live in "etc"
- Xarp etc Makefile arp.c
- Xbiod etc Makefile biod.c
- Xchown etc Makefile chown.c
- Xclri etc Makefile clri.c
- Xdkinfo etc Makefile dkinfo.c
- Xdmesg etc Makefile dmesg.c
- Xfsirand etc Makefile fsirand.c
- Xhalt etc Makefile halt.c
- Xifconfig etc Makefile ifconfig.c
- Xin.rlogind etc Makefile in.rlogind.c
- Xin.rshd etc Makefile in.rshd.c
- Xinetd etc Makefile inetd.c
- Xinit etc Makefile init.c
- Xmkfs etc Makefile mkfs.c
- Xmknod etc Makefile mknod.c
- Xmount etc Makefile mount.c
- Xnewfs etc Makefile newfs.c
- Xnfsd etc Makefile nfsd.c
- Xportmap etc Makefile portmap.c
- Xpstat etc Makefile pstat.c
- Xreboot etc Makefile reboot.c
- Xrenice etc Makefile renice.c
- Xrmt etc Makefile rmt.c
- Xshutdown etc Makefile shutdown.c
- Xsyslogd etc Makefile syslogd.c
- Xumount etc Makefile umount.c
- Xupdate etc Makefile update.c
- Xvipw etc Makefile vipw.c
- Xypbind etc Makefile ypbind.c
- X
- X# Sub-directories of "games"
- Xadventure games/adventure
- Xbackgammon games/backgammon
- Xbattlestar games/battlestar
- Xboggle games/boggle
- Xchess games/chess
- Xching games/ching
- Xcribbage games/cribbage
- Xfortune games/fortune
- Xhack games/hack
- Xhangman games/hangman
- Xhunt games/hunt
- Xlife games/life
- Xmille games/mille
- Xmonop games/monop
- Xquiz games/quiz
- Xrobots games/robots
- Xsail games/sail
- Xsnake games/snake
- Xtrek games/trek
- X
- X# Programs that live in "games"
- Xarithmetic games Makefile arithmetic.c
- Xbanner games Makefile banner.c
- Xbcd games Makefile bcd.c
- Xbj games Makefile bj.c
- Xbtlgammon games Makefile btlgammon.c
- Xcanfield games Makefile canfield.c
- Xcfscores games Makefile cfscores.c
- Xcraps games Makefile craps.c
- Xfactor games Makefile factor.c
- Xfish games Makefile fish.c
- Xmoo games Makefile moo.c
- Xnumber games Makefile number.c
- Xprimes games Makefile primes.c
- Xrain games Makefile rain.c
- Xrandom games Makefile random.c
- Xworm games Makefile worm.c
- Xworms games Makefile worms.c
- Xwump games Makefile wump.c
- X
- X# Sub-directories of "lang"
- Xadb lang/adb
- Xas lang/as
- Xboot lang/boot
- Xc2 lang/c2
- Xcgrdr lang/cgrdr
- Xcompile lang/compile
- Xcpp lang/cpp
- Xdbx lang/dbx
- Xf77 lang/f77
- Xinline lang/inline
- Xiropt lang/iropt
- Xld lang/ld
- Xlint lang/lint
- Xm4 lang/m4
- Xpascal lang/pascal
- Xpcc lang/pcc
- Xratfor lang/ratfor
- Xrtld lang/rtld
- Xtcov lang/tcov
- Xvroot lang/vroot
- X
- X# Programs that live in "lang"
- Xar lang Makefile ar.c
- Xnm lang Makefile nm.c
- Xranlib lang Makefile ranlib.c
- Xsize lang Makefile size.c
- Xstrip lang Makefile strip.c
- Xsymorder lang Makefile symorder.c
- X
- X# Sub-directories of "lib"
- Xcsu lib/csu
- Xlibc lib/libc
- X
- X# Programs that live in "lib"
- X# NONE
- X
- X# Sub-directories of "lib/libc"
- Xlibc_compat lib/libc/compat
- Xlibc_crt lib/libc/crt
- Xlibc_des lib/libc/des
- Xlibc_gen lib/libc/gen
- Xlibc_net lib/libc/net
- Xlibc_inet lib/libc/inet
- Xlibc_rpc lib/libc/rpc
- Xlibc_stdio lib/libc/stdio
- Xlibc_sun lib/libc/sun
- Xlibc_sys lib/libc/sys
- Xlibc_yp lib/libc/yp
- X
- X# Programs that live in "lib/libc"
- X# NONE
- X
- X#Sub-directories of "local"
- Xnotes local/notes
- X
- X# Sub-directories of "man"
- Xman1 man/man1
- Xman2 man/man2
- Xman3 man/man3
- Xman4 man/man4
- Xman5 man/man5
- Xman6 man/man6
- Xman7 man/man7
- Xman8 man/man8
- Xmanl man/manl
- X
- X# Programs that live in "man"
- X# NONE
- X
- X# Sub-directories of "old"
- Xold_compact old/compact
- Xold_eyacc old/eyacc
- Xold_filemerge old/filemerge
- Xold_make old/make
- X
- X# Programs that live in "old"
- Xold_analyze old Makefile analyze.c
- Xold_prmail old Makefile prmail.c
- Xold_pti old Makefile pti.c
- Xold_syslog old Makefile syslog.c
- X
- X# Sub-directories of "ucb"
- XMail ucb/Mail
- Xcompress ucb/compress
- Xerror ucb/error
- Xex ucb/ex
- Xftp ucb/ftp
- Xgprof ucb/gprof
- Xindent ucb/indent
- Xlpr ucb/lpr
- Xmore ucb/more
- Xmsgs ucb/msgs
- Xnetstat ucb/netstat
- Xrdist ucb/rdist
- Xtalk ucb/talk
- Xtftp ucb/tftp
- Xtset ucb/tset
- Xvgrind ucb/vgrind
- X
- X# Programs that live in "ucb"
- Xbiff ucb Makefile biff.c
- Xchecknr ucb Makefile checknr.c
- Xclear ucb Makefile clear.c
- Xcolcrt ucb Makefile colcrt.c
- Xcolrm ucb Makefile colrm.c
- Xctags ucb Makefile ctags.c
- Xexpand ucb Makefile expand.c
- Xfinger ucb Makefile finger.c
- Xfold ucb Makefile fold.c
- Xfrom ucb Makefile from.c
- Xfsplit ucb Makefile fsplit.c
- Xgcore ucb Makefile gcore.c
- Xgroups ucb Makefile groups.c
- Xhead ucb Makefile head.c
- Xlast ucb Makefile last.c
- Xlastcomm ucb Makefile lastcomm.c
- Xleave ucb Makefile leave.c
- Xlogger ucb Makefile logger.c
- Xman_prog ucb Makefile man.c
- Xmkstr ucb Makefile mkstr.c
- Xprintenv ucb Makefile printenv.c
- Xquota ucb Makefile quota.c
- Xrcp ucb Makefile rcp.c
- Xrdate ucb Makefile rdate.c
- Xrlogin ucb Makefile rlogin.c
- Xrsh ucb Makefile rsh.c
- Xrup ucb Makefile rup.c
- Xruptime ucb Makefile ruptime.c
- Xrusers ucb Makefile rusers.c
- Xrwho ucb Makefile rwho.c
- Xsccs ucb Makefile sccs.c
- Xscript ucb Makefile script.c
- Xsoelim ucb Makefile soelim.c
- Xstrings ucb Makefile strings.c
- Xtail ucb Makefile tail.c
- Xtcopy ucb Makefile tcopy.c
- Xtelnet ucb Makefile telnet.c
- Xul ucb Makefile ul.c
- Xunexpand ucb Makefile unexpand.c
- Xunifdef ucb Makefile unifdef.c
- Xusers ucb Makefile users.c
- Xvmstat ucb Makefile vmstat.c
- Xw ucb Makefile w.c
- Xwc ucb Makefile wc.c
- Xwhat ucb Makefile what.c
- Xwhatis ucb Makefile whatis.c
- Xwhereis ucb Makefile whereis.c
- Xwhoami ucb Makefile whoami.c
- Xwhois ucb Makefile whois.c
- Xxstr ucb Makefile xstr.c
- Xyes ucb Makefile yes.c
- X
- X# Sub-directories of "usr.bin"
- Xcalendar usr.bin/calendar
- Xcflow usr.bin/cflow
- Xctrace usr.bin/ctrace
- Xcxref usr.bin/cxref
- Xdc usr.bin/dc
- Xdes usr.bin/des
- Xdiff3 usr.bin/diff3
- Xsun_eqn usr.bin/eqn
- Xfile usr.bin/file
- Xfind usr.bin/find
- Xgraph usr.bin/graph
- Xlex usr.bin/lex
- Xsun_neqn usr.bin/neqn
- Xsun_nroff usr.bin/nroff
- Xsun_plot usr.bin/plot
- Xprof usr.bin/prof
- Xrefer usr.bin/refer
- Xrpcgen usr.bin/rpcgen
- Xspell usr.bin/spell
- Xsun_tbl usr.bin/tbl
- Xtip usr.bin/tip
- Xtrace usr.bin/trace
- Xsun_troff usr.bin/troff
- Xuucp usr.bin/uucp
- Xxsend usr.bin/xsend
- Xyacc usr.bin/yacc
- X
- X# Programs that live in "usr.bin"
- Xbasename usr.bin Makefile basename.c
- Xbc usr.bin Makefile bc.c
- Xcal usr.bin Makefile cal.c
- Xcb usr.bin Makefile cb.c
- Xcheckeq usr.bin Makefile checkeq.c
- Xchkey usr.bin Makefile chkey.c
- Xclick usr.bin Makefile click.c
- Xcol usr.bin Makefile col.c
- Xcomm usr.bin Makefile comm.c
- Xcpio usr.bin Makefile cpio.c
- Xcrypt usr.bin Makefile crypt.c
- Xcsplit usr.bin Makefile csplit.c
- Xcut usr.bin Makefile cut.c
- Xderoff usr.bin Makefile deroff.c
- Xegrep usr.bin Makefile egrep.c
- Xfgrep usr.bin Makefile fgrep.c
- Xgetopt usr.bin Makefile getopt.c
- Xid usr.bin Makefile id.c
- Xinstallcmd usr.bin Makefile installcmd.c
- Xiostat usr.bin Makefile iostat.c
- Xipcrm usr.bin Makefile ipcrm.c
- Xipcs usr.bin Makefile ipcs.c
- Xjoin usr.bin Makefile join.c
- Xkeylogin usr.bin Makefile keylogin.c
- Xlogname usr.bin Makefile logname.c
- Xlook usr.bin Makefile look.c
- Xmesg usr.bin Makefile mesg.c
- Xnl usr.bin Makefile nl.c
- Xpack usr.bin Makefile pack.c
- Xpaste usr.bin Makefile paste.c
- Xptx usr.bin Makefile ptx.c
- Xrev usr.bin Makefile rev.c
- Xscreenblank usr.bin Makefile screenblank.c
- Xsdiff usr.bin Makefile sdiff.c
- Xsleep usr.bin Makefile sleep.c
- Xsort usr.bin Makefile sort.c
- Xspline usr.bin Makefile spline.c
- Xsplit usr.bin Makefile split.c
- Xsum usr.bin Makefile sum.c
- Xtouch usr.bin Makefile touch.c
- Xtr usr.bin Makefile tr.c
- Xtsort usr.bin Makefile tsort.c
- Xtty usr.bin Makefile tty.c
- Xuniq usr.bin Makefile uniq.c
- Xunits usr.bin Makefile units.c
- Xunpack usr.bin Makefile unpack.c
- Xxargs usr.bin Makefile xargs.c
- Xypcat usr.bin Makefile ypcat.c
- Xypmatch usr.bin Makefile ypmatch.c
- Xyppasswd usr.bin Makefile yppasswd.c
- Xypwhich usr.bin Makefile ypwhich.c
- X
- X# Sub-directories of "usr.etc"
- Xautomount usr.etc/automount
- Xc2convert usr.etc/c2convert
- Xconfig usr.etc/config
- Xcron usr.etc/cron
- Xeeprom usr.etc/eeprom
- Xetherfind usr.etc/etherfind
- Xformat usr.etc/format
- Xhtable usr.etc/htable
- Ximplog usr.etc/implog
- Xin.ftpd -a usr.etc/in.ftpd ucb/ftp
- Xin.named usr.etc/in.named
- Xin.rwhod usr.etc/in.rwhod
- Xkeyserv usr.etc/keyserv
- Xndbootd usr.etc/ndbootd
- Xpraudit usr.etc/praudit
- Xrexd usr.etc/rexd
- Xrpc.bootparamd usr.etc/rpc.bootparamd
- Xtermcap usr.etc/termcap
- Xupgrade usr.etc/upgrade
- Xyp usr.etc/yp
- Xzic usr.etc/zic
- X
- X# Programs that live in "usr.etc"
- Xac usr.etc Makefile ac.c
- Xaccton usr.etc Makefile accton.c
- Xaudit usr.etc Makefile audit.c
- Xauditd usr.etc Makefile auditd.c
- Xcatman usr.etc Makefile catman.c
- Xchroot usr.etc Makefile chroot.c
- Xdcheck usr.etc Makefile dcheck.c
- Xdevnm usr.etc Makefile devnm.c
- Xdumpfs usr.etc Makefile dumpfs.c
- Xedquota usr.etc Makefile edquota.c
- Xexportfs usr.etc Makefile exportfs.c
- Xfoption usr.etc Makefile foption.c
- Xgettable usr.etc Makefile gettable.c
- Xgrpck usr.etc Makefile grpck.c
- Xicheck usr.etc Makefile icheck.c
- Xin.comsat usr.etc Makefile in.comsat.c
- Xin.fingerd usr.etc Makefile in.fingerd.c
- Xin.rexecd usr.etc Makefile in.rexecd.c
- Xin.telnetd usr.etc Makefile in.telnetd.c
- Xin.tnamed usr.etc Makefile in.tnamed.c
- Xkgmon usr.etc Makefile kgmon.c
- Xlink usr.etc Makefile link.c
- Xmkfile usr.etc Makefile mkfile.c
- Xmkproto usr.etc Makefile mkproto.c
- Xmount_lo usr.etc Makefile mount_lo.c
- Xncheck usr.etc Makefile ncheck.c
- Xnfsstat usr.etc Makefile nfsstat.c
- Xping usr.etc Makefile ping.c
- Xpwck usr.etc Makefile pwck.c
- Xquot usr.etc Makefile quot.c
- Xquotacheck usr.etc Makefile quotacheck.c
- Xquotaon usr.etc Makefile quotaon.c
- Xrarpd usr.etc Makefile rarpd.c
- Xrepquota usr.etc Makefile repquota.c
- Xroute usr.etc Makefile route.c
- Xrpc.etherd usr.etc Makefile rpc.etherd.c
- Xrpc.mountd usr.etc Makefile rpc.mountd.c
- Xrpc.pwdauthd usr.etc Makefile rpc.pwdauthd.c
- Xrpc.rquotad usr.etc Makefile rpc.rquotad.c
- Xrpc.rstatd usr.etc Makefile rpc.rstatd.c
- Xrpc.rusersd usr.etc Makefile rpc.rusersd.c
- Xrpc.rwalld usr.etc Makefile rpc.rwalld.c
- Xrpc.sprayd usr.etc Makefile rpc.sprayd.c
- Xrpc.yppasswdd usr.etc Makefile rpc.yppasswdd.c
- Xrpc.ypupdated usr.etc Makefile rpc.ypupdated.c
- Xrpcinfo usr.etc Makefile rpcinfo.c
- Xrwall usr.etc Makefile rwall.c
- Xsa usr.etc Makefile sa.c
- Xsavecore usr.etc Makefile savecore.c
- Xshowmount usr.etc Makefile showmount.c
- Xspray usr.etc Makefile spray.c
- Xswapon usr.etc Makefile swapon.c
- Xtrpt usr.etc Makefile trpt.c
- Xtunefs usr.etc Makefile tunefs.c
- Xunlink usr.etc Makefile unlink.c
- X
- X# Sub-directories of "usr.lib"
- Xbb_count usr.lib/bb_count
- Xfixedwidthfonts usr.lib/fixedwidthfonts
- Xlibcurses usr.lib/libcurses
- Xlibdbm usr.lib/libdbm
- Xlibg usr.lib/libg
- Xlibkvm usr.lib/libkvm
- Xlibln usr.lib/libln
- Xliblwp usr.lib/liblwp
- Xlibm usr.lib/libm
- Xlibmp usr.lib/libmp
- Xlibpixrect usr.lib/libpixrect
- Xlibplot usr.lib/libplot
- Xlibresolv usr.lib/libresolv
- Xlibrpcsvc usr.lib/librpcsvc
- Xlibtermlib usr.lib/libtermlib
- Xliby usr.lib/liby
- Xme usr.lib/me
- Xms usr.lib/ms
- Xsendmail usr.lib/sendmail
- Xsun_tmac usr.lib/tmac
- Xvfont usr.lib/vfont
- X
- X# Programs that live in "usr.lib"
- XgetNAME usr.lib Makefile getNAME
- Xmakekey usr.lib Makefile makekey
- X
- X# Sub-directories of "5bin"
- X5diff3 5bin/diff3
- X5m4 5bin/m4
- X
- X# Sub-directories of "5bin", but use sources from other places
- X5cxref -a 5bin/cxref usr.bin/cxref
- X5sed -a 5bin/sed bin/sed
- X5lint -a 5bin/lint lang/pcc lang/lint
- X
- X# Programs that live in "5bin"
- X5banner 5bin Makefile banner.c
- X5cat 5bin Makefile cat.c
- X5du 5bin Makefile du.c
- X5echo 5bin Makefile echo.c
- X5expr 5bin Makefile expr.c
- X5ls 5bin Makefile ls.c
- X5nohup 5bin Makefile nohup.c
- X5od 5bin Makefile od.c
- X5pg 5bin Makefile pg.c
- X5pr 5bin Makefile pr.c
- X5sum 5bin Makefile sum.c
- X5tabs 5bin Makefile tabs.c
- X5time 5bin Makefile time.c
- X5tr 5bin Makefile tr.c
- X5uname 5bin Makefile uname.c
- X
- X# Programs that live in "5bin", but use sources from other places
- X5chmod -a 5bin/Makefile bin/chmod.c
- X5date -a 5bin/Makefile bin/date.c
- X5grep -a 5bin/Makefile bin/grep.c
- X5stty -a 5bin/Makefile bin/stty.c
- X5col -a 5bin/Makefile usr.bin/col.c
- X5sort -a 5bin/Makefile usr.bin/sort.c
- X5touch -a 5bin/Makefile usr.bin/touch.c
- X
- X# Sub-directories of "5lib"
- X5compile 5lib/compile
- X5libcurses 5lib/libcurses
- X5liby 5lib/liby
- X5terminfo 5lib/terminfo
- X
- X# Programs that live in "5lib"
- X# NONE
- X
- X# Programs that live in "prisma"
- Xcvs prisma/cvs
- Xmicrokernel prisma/microkernel
- Xtms prisma/tms
- X
- X# Programs that live in "doctools"
- Xdcan doctools/dcan
- Xditrev doctools/ditrev
- Xditsee doctools/ditsee
- Xeqn doctools/eqn
- Xgrap doctools/grap
- Xiprx doctools/iprx
- Xm3 doctools/m3
- Xneqn doctools/neqn
- Xpic doctools/pic
- Xroff doctools/roff
- Xtroff doctools/roff
- Xtbl doctools/tbl
- Xtgraph doctools/tgraph
- Xtmac doctools/tmac
- END_OF_FILE
- if test 14454 -ne `wc -c <'examples/modules'`; then
- echo shar: \"'examples/modules'\" unpacked with wrong size!
- fi
- # end of 'examples/modules'
- fi
- if test -f 'src/commit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/commit.c'\"
- else
- echo shar: Extracting \"'src/commit.c'\" \(21136 characters\)
- sed "s/^X//" >'src/commit.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char rcsid[] = "$Id: commit.c,v 1.28 89/11/19 23:40:32 berliner Exp $";
- X#endif !lint
- X
- X/*
- X * Copyright (c) 1989, Brian Berliner
- X *
- X * You may distribute under the terms of the GNU General Public License
- X * as specified in the README file that comes with the CVS 1.0 kit.
- X *
- X * Commit Files
- X *
- X * "commit" commits the present version to the RCS repository, AFTER
- X * having done a test on conflicts. The call is:
- X * cvs commit [options] files...
- X *
- X * "commit" accepts the following options:
- X * -f Force a commit, even if the RCS $Id string
- X * is not found
- X * -n Causes "commit" to *not* run any commit prog
- X * -a Commits all files in the current directory
- X * that have been modified.
- X * -m 'message' Does not start up the editor for the
- X * log message; just gleans it from the
- X * 'message' argument.
- X * -r Revision Allows committing to a particular *numeric*
- X * revision number.
- X *
- X * Note that "commit" does not do a recursive commit. You must do
- X * "commit" in each directory where there are files that you'd
- X * like to commit.
- X */
- X
- X#include <sys/param.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <ctype.h>
- X#include "cvs.h"
- X
- Xstatic int force_commit_no_rcsid = 0;
- X
- Xextern int run_module_prog;
- X
- Xcommit(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int commit_all = 0, err = 0;
- X char *rev = ""; /* not NULL! */
- X char line[MAXLINELEN], message[MAXMESGLEN];
- X int c;
- X
- X if (argc == -1)
- X commit_usage();
- X /*
- X * For log purposes, do not allow "root" to commit files
- X */
- X if (geteuid() == 0)
- X error(0, "cannot commit files as 'root'");
- X optind = 1;
- X while ((c = getopt(argc, argv, "fnam:r:")) != -1) {
- X switch (c) {
- X case 'f':
- X force_commit_no_rcsid = 1;
- X break;
- X case 'n':
- X run_module_prog = 0;
- X break;
- X case 'a':
- X commit_all = 1;
- X break;
- X case 'm':
- X use_editor = FALSE;
- X if (strlen(optarg) >= sizeof(message)) {
- X warn(0, "warning: message too long; truncated!");
- X (void) strncpy(message, optarg, sizeof(message));
- X message[sizeof(message) - 1] = '\0';
- X } else
- X (void) strcpy(message, optarg);
- X break;
- X case 'r':
- X if (!isdigit(optarg[0]))
- X error(0, "specified revision %s must be numeric!", optarg);
- X rev = optarg;
- X break;
- X case '?':
- X default:
- X commit_usage();
- X break;
- X }
- X }
- X argc -= optind;
- X argv += optind;
- X if (!commit_all && argc == 0)
- X error(0, "must specify the files you'd like to check-in");
- X if (commit_all && argc != 0)
- X error(0, "cannot specify files with the -a option");
- X Name_Repository();
- X Writer_Lock();
- X if (commit_all) {
- X Find_Names(&fileargc, fileargv, ALL);
- X argc = fileargc;
- X argv = fileargv;
- X }
- X if (rev[0] != '\0') {
- X register int i;
- X FILE *fptty;
- X
- X fptty = open_file("/dev/tty", "r");
- X printf("WARNING:\n");
- X printf("\tCommitting with a specific revision number\n");
- X printf("\tbypasses all consistency checks. Are you abosulutely\n");
- X printf("\tsure you want to continue (y/n) [n] ? ");
- X (void) fflush(stdout);
- X if (fgets(line, sizeof(line), fptty) == NULL ||
- X (line[0] != 'y' && line[0] != 'Y')) {
- X error(0, "commit of revision %s aborted", rev);
- X }
- X (void) fclose(fptty);
- X /*
- X * When committing with a specific revision number, we simply
- X * fudge the lists that Collect_Sets() would have created for
- X * us. This is all so gross, but sometimes useful.
- X */
- X Clist[0] = Glist[0] = Mlist[0] = Olist[0] = Dlist[0] = '\0';
- X Alist[0] = Rlist[0] = Wlist[0] = Llist[0] = Blist[0] = '\0';
- X for (i = 0; i < argc; i++) {
- X (void) strcat(Mlist, " ");
- X (void) strcat(Mlist, argv[i]);
- X }
- X } else {
- X err += Collect_Sets(argc, argv);
- X }
- X if (err == 0) {
- X err += commit_process_lists(message, rev);
- X if (err == 0 && run_module_prog) {
- X char *cp;
- X FILE *fp;
- X
- X /*
- X * It is not an error if Checkin.prog does not exist.
- X */
- X if ((fp = fopen(CVSADM_CIPROG, "r")) != NULL) {
- X if (fgets(line, sizeof(line), fp) != NULL) {
- X if ((cp = rindex(line, '\n')) != NULL)
- X *cp = '\0';
- X (void) sprintf(prog, "%s %s", line, Repository);
- X printf("%s %s: Executing '%s'\n", progname, command, prog);
- X (void) system(prog);
- X }
- X (void) fclose(fp);
- X }
- X }
- X Update_Logfile(Repository, message);
- X }
- X Lock_Cleanup(0);
- X exit(err);
- X}
- X
- X/*
- X * Process all the lists, returning the number of errors found.
- X */
- Xstatic
- Xcommit_process_lists(message, rev)
- X char *message;
- X char *rev;
- X{
- X char line[MAXLISTLEN], fname[MAXPATHLEN], revision[50];
- X FILE *fp;
- X char *cp;
- X int first, err = 0;
- X
- X /*
- X * Doesn't make much sense to commit a directory...
- X */
- X if (Dlist[0])
- X warn(0, "committing directories ignored -%s", Dlist);
- X /*
- X * Is everything up-to-date?
- X * Only if Glist, Olist, and Wlist are all NULL!
- X */
- X if (Glist[0] || Olist[0] || Wlist[0]) {
- X (void) fprintf(stderr, "%s: the following files are not ", progname);
- X (void) fprintf(stderr,
- X "up to date; use '%s update' first:\n", progname);
- X if (Glist[0] != '\0')
- X (void) fprintf(stderr, "\t%s\n", Glist);
- X if (Olist[0] != '\0')
- X (void) fprintf(stderr, "\t%s\n", Olist);
- X if (Wlist[0] != '\0')
- X (void) fprintf(stderr, "\t%s\n", Wlist);
- X Lock_Cleanup(0);
- X exit(1);
- X }
- X /*
- X * Is there anything to do in the first place?
- X */
- X if (Mlist[0] == '\0' && Rlist[0] == '\0' && Alist[0] == '\0')
- X error(0, "there is nothing to commit!");
- X /*
- X * First we make sure that the file has an RCS $Id string in it
- X * and if it does not, the user is prompted for verification to continue.
- X */
- X if (force_commit_no_rcsid == 0) {
- X (void) strcpy(line, Mlist);
- X (void) strcat(line, Alist);
- X for (first = 1, cp = strtok(line, " \t"); cp;
- X cp = strtok((char *)NULL, " \t")) {
- X (void) sprintf(prog, "%s -s %s %s", GREP, RCSID_PAT, cp);
- X if (system(prog) != 0) {
- X if (first) {
- X printf("%s %s: WARNING!\n", progname, command);
- X printf("\tThe following file(s) do not contain an RCS $Id keyword:\n");
- X first = 0;
- X }
- X printf("\t\t%s\n", cp);
- X }
- X }
- X if (first == 0) {
- X FILE *fptty = open_file("/dev/tty", "r");
- X printf("\tAre you sure you want to continue (y/n) [n] ? ");
- X (void) fflush(stdout);
- X if (fgets(line, sizeof(line), fptty) == NULL ||
- X (line[0] != 'y' && line[0] != 'Y')) {
- X error(0, "commit aborted");
- X }
- X (void) fclose(fptty);
- X }
- X }
- X if (use_editor)
- X do_editor(message);
- X /*
- X * Mlist is the "modified, needs committing" list
- X */
- X (void) strcpy(line, Mlist);
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X if (lock_RCS(rev) != 0)
- X err++;
- X }
- X /*
- X * Rlist is the "to be removed" list
- X */
- X (void) strcpy(line, Rlist);
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X if (lock_RCS(rev) != 0)
- X err++;
- X }
- X /*
- X * Alist is the "to be added" list
- X */
- X (void) strcpy(line, Alist);
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X (void) sprintf(prog, "%s/%s -i -t%s/%s%s", Rcsbin, RCS, CVSADM,
- X User, CVSEXT_LOG);
- X (void) sprintf(fname, "%s/%s%s", CVSADM, User, CVSEXT_OPT);
- X fp = open_file(fname, "r");
- X while (fgets(fname, sizeof(fname), fp) != NULL) {
- X if ((cp = rindex(fname, '\n')) != NULL)
- X *cp = '\0';
- X (void) strcat(prog, " ");
- X (void) strcat(prog, fname);
- X }
- X (void) fclose(fp);
- X (void) strcat(prog, " ");
- X (void) strcat(prog, Rcs);
- X if (system(prog) == 0) {
- X fix_rcs_modes(Rcs, User);
- X } else {
- X warn(0, "could not create %s", Rcs);
- X err++;
- X }
- X }
- X /*
- X * If something failed, release all locks and restore the default
- X * branches
- X */
- X if (err) {
- X int didllist = 0;
- X char *branch;
- X
- X for (cp = strtok(Llist, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X didllist = 1;
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X (void) sprintf(prog, "%s/%s -q -u %s", Rcsbin, RCS, Rcs);
- X if (system(prog) != 0)
- X warn(0, "could not UNlock %s", Rcs);
- X }
- X if (didllist) {
- X for (cp=strtok(Blist, " \t"); cp; cp=strtok((char *)NULL, " \t")) {
- X if ((branch = rindex(cp, ':')) == NULL)
- X continue;
- X *branch++ = '\0';
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X (void) sprintf(prog, "%s/%s -q -b%s %s", Rcsbin, RCS,
- X branch, Rcs);
- X if (system(prog) != 0)
- X warn(0, "could not restore branch %s to %s", branch, Rcs);
- X }
- X }
- X for (cp = strtok(Alist, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X (void) unlink(Rcs);
- X }
- X Lock_Cleanup(0);
- X exit(1);
- X }
- X /*
- X * Got them all, now go ahead;
- X * First, add the files in the Alist
- X */
- X if (Alist[0] != '\0') {
- X int maxrev, rev;
- X
- X /* scan the entries file looking for the max revision number */
- X fp = open_file(CVSADM_ENT, "r");
- X maxrev = 0;
- X while (fgets(line, sizeof(line), fp) != NULL) {
- X rev = atoi(line);
- X if (rev > maxrev)
- X maxrev = rev;
- X }
- X if (maxrev == 0)
- X maxrev = 1;
- X (void) fclose(fp);
- X (void) sprintf(revision, "-r%d", maxrev);
- X (void) strcpy(line, Alist);
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X (void) strcpy(User, cp);
- X if (Checkin(revision, message) != 0)
- X err++;
- X (void) sprintf(fname, "%s/%s%s", CVSADM, User, CVSEXT_OPT);
- X (void) unlink(fname);
- X (void) sprintf(fname, "%s/%s%s", CVSADM, User, CVSEXT_LOG);
- X (void) unlink(fname);
- X }
- X }
- X /*
- X * Everyone else uses the head as it is set in the RCS file,
- X * or the revision that was specified on the command line.
- X */
- X if (rev[0] != '\0')
- X (void) sprintf(revision, "-r%s", rev);
- X else
- X revision[0] = '\0';
- X /*
- X * Commit the user modified files in Mlist
- X */
- X (void) strcpy(line, Mlist);
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X (void) strcpy(User, cp);
- X if (Checkin(revision, message) != 0)
- X err++;
- X }
- X /*
- X * And remove the RCS files in Rlist, by placing it in the Attic
- X */
- X (void) strcpy(line, Rlist);
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X int omask;
- X
- X (void) strcpy(User, cp);
- X (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
- X (void) sprintf(fname, "%s/%s", Repository, CVSATTIC);
- X omask = umask(2);
- X (void) mkdir(fname, 0777);
- X (void) umask(omask);
- X (void) sprintf(fname, "%s/%s/%s%s", Repository, CVSATTIC,
- X User, RCSEXT);
- X (void) sprintf(prog, "%s/%s -u -q %s", Rcsbin, RCS, Rcs);
- X if ((system(prog) == 0 && rename(Rcs, fname) != -1) ||
- X (!isreadable(Rcs) && isreadable(fname)))
- X Scratch_Entry(User);
- X else
- X err++;
- X }
- X return (err);
- X}
- X
- X/*
- X * Attempt to place a lock on the RCS file; returns 0 if it could and
- X * 1 if it couldn't. If the RCS file currently has a branch as the head,
- X * we must move the head back to the trunk before locking the file, and
- X * be sure to put the branch back as the head if there are any errors.
- X */
- Xstatic
- Xlock_RCS(rev)
- X char *rev;
- X{
- X char branch[50];
- X int err = 0;
- X
- X branch[0] = '\0';
- X /*
- X * For a specified, numeric revision of the form "1" or "1.1",
- X * (or when no revision is specified ""), definitely move the
- X * branch to the trunk before locking the RCS file.
- X *
- X * The assumption is that if there is more than one revision
- X * on the trunk, the head points to the trunk, not a branch...
- X * and as such, it's not necessary to move the head in this case.
- X */
- X if (numdots(rev) < 2) {
- X branch_number(Rcs, branch);
- X if (branch[0] != '\0') {
- X (void) sprintf(prog, "%s/%s -q -b %s", Rcsbin, RCS, Rcs);
- X if (system(prog) != 0) {
- X warn(0, "cannot change branch to default for %s", Rcs);
- X return (1);
- X }
- X }
- X (void) sprintf(prog, "%s/%s -q -l %s", Rcsbin, RCS, Rcs);
- X err = system(prog);
- X } else {
- X (void) sprintf(prog, "%s/%s -q -l%s %s 2>%s",
- X Rcsbin, RCS, rev, Rcs, DEVNULL);
- X (void) system(prog);
- X }
- X if (err == 0) {
- X (void) strcat(Llist, " ");
- X (void) strcat(Llist, User);
- X (void) strcat(Blist, " ");
- X (void) strcat(Blist, User);
- X if (branch[0] != '\0') {
- X (void) strcat(Blist, ":");
- X (void) strcat(Blist, branch);
- X }
- X return (0);
- X }
- X if (branch[0] != '\0') {
- X (void) sprintf(prog, "%s/%s -q -b%s %s", Rcsbin, RCS, branch, Rcs);
- X if (system(prog) != 0)
- X warn(0, "cannot restore branch to %s for %s", branch, Rcs);
- X }
- X return (1);
- X}
- X
- X/*
- X * A special function used only by lock_RCS() to determine if the current
- X * head is pointed at a branch. Returns the result in "branch" as a null
- X * string if the trunk is the head, or as the branch number if the branch
- X * is the head.
- X */
- Xstatic
- Xbranch_number(rcs, branch)
- X char *rcs;
- X char *branch;
- X{
- X char line[MAXLINELEN];
- X FILE *fp;
- X char *cp;
- X
- X branch[0] = '\0'; /* Assume trunk is head */
- X fp = open_file(rcs, "r");
- X if (fgets(line, sizeof(line), fp) == NULL) {
- X (void) fclose(fp);
- X return;
- X }
- X if (fgets(line, sizeof(line), fp) == NULL) {
- X (void) fclose(fp);
- X return;
- X }
- X (void) fclose(fp);
- X if (strncmp(line, RCSBRANCH, sizeof(RCSBRANCH) - 1) != 0 ||
- X (cp = rindex(line, ';')) == NULL)
- X return;
- X *cp = '\0'; /* strip the ';' */
- X if ((cp = rindex(line, ' ')) == NULL &&
- X (cp = rindex(line, '\t')) == NULL)
- X return;
- X cp++;
- X if (*cp == NULL)
- X return;
- X (void) strcpy(branch, cp);
- X}
- X
- X/*
- X * Puts a standard header on the output which is either being prepared for
- X * an editor session, or being sent to a logfile program. The modified, added,
- X * and removed files are included (if any) and formatted to look pretty.
- X */
- Xstatic
- Xsetup_tmpfile(fp, prefix)
- X FILE *fp;
- X char *prefix;
- X{
- X if (Mlist[0] != '\0') {
- X (void) fprintf(fp, "%sModified Files:\n", prefix);
- X fmt(fp, Mlist, prefix);
- X }
- X if (Alist[0] != '\0') {
- X (void) fprintf(fp, "%sAdded Files:\n", prefix);
- X fmt(fp, Alist, prefix);
- X }
- X if (Rlist[0] != '\0') {
- X (void) fprintf(fp, "%sRemoved Files:\n", prefix);
- X fmt(fp, Rlist, prefix);
- X }
- X}
- X
- X/*
- X * Breaks the files list into reasonable sized lines to avoid line
- X * wrap... all in the name of pretty output.
- X */
- Xstatic
- Xfmt(fp, instring, prefix)
- X FILE *fp;
- X char *instring;
- X char *prefix;
- X{
- X char line[MAXLINELEN];
- X char *cp;
- X int col;
- X
- X (void) strcpy(line, instring); /* since strtok() is destructive */
- X (void) fprintf(fp, "%s\t", prefix);
- X col = 8; /* assumes that prefix is < 8 chars */
- X for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
- X if ((col + strlen(cp)) > 70) {
- X (void) fprintf(fp, "\n%s\t", prefix);
- X col = 8;
- X }
- X (void) fprintf(fp, "%s ", cp);
- X col += strlen(cp) + 1;
- X }
- X (void) fprintf(fp, "\n%s\n", prefix);
- X}
- X
- X/*
- X * Builds a temporary file using setup_tmpfile() and invokes the user's
- X * editor on the file. The header garbage in the resultant file is then
- X * stripped and the log message is stored in the "message" argument.
- X */
- Xstatic
- Xdo_editor(message)
- X char *message;
- X{
- X FILE *fp;
- X char line[MAXLINELEN], fname[MAXPATHLEN];
- X int fd;
- X
- X message[0] = '\0';
- X (void) strcpy(fname, CVSTEMP);
- X if ((fd = mkstemp(fname)) < 0)
- X error(0, "cannot create temporary file %s", fname);
- X if ((fp = fdopen(fd, "w+")) == NULL)
- X error(0, "cannot create FILE * to %s", fname);
- X setup_tmpfile(fp, CVSEDITPREFIX);
- X (void) fprintf(fp, "%sEnter Log. Lines beginning with '%s' are removed automatically\n",
- X CVSEDITPREFIX, CVSEDITPREFIX);
- X (void) fprintf(fp, "%s----------------------------------------------------------------------\n");
- X (void) fclose(fp);
- X (void) sprintf(prog, "%s %s", Editor, fname);
- X if (system(prog) != 0) {
- X (void) unlink(fname);
- X warn(0, "warning: editor session failed");
- X }
- X fp = open_file(fname, "r");
- X while (fgets(line, sizeof(line), fp) != NULL) {
- X if (strncmp(line, CVSEDITPREFIX, sizeof(CVSEDITPREFIX)-1) == 0)
- X continue;
- X if ((strlen(message) + strlen(line)) >= MAXMESGLEN) {
- X warn(0, "warning: log message truncated!");
- X break;
- X }
- X (void) strcat(message, line);
- X }
- X (void) fclose(fp);
- X (void) unlink(fname);
- X}
- X
- X/*
- X * Uses setup_tmpfile() to pass the updated message on directly to
- X * any logfile programs that have a regular expression match for the
- X * checked in directory in the source repository. The log information
- X * is fed into the specified program as standard input.
- X */
- XUpdate_Logfile(repository, message)
- X char *repository;
- X char *message;
- X{
- X FILE *fp_info;
- X char logfile[MAXPATHLEN], title[MAXLISTLEN+MAXPATHLEN], line[MAXLINELEN];
- X char path[MAXPATHLEN], default_filter[MAXLINELEN];
- X char *exp, *filter, *cp, *short_repository;
- X int filter_run, line_number;
- X
- X if (CVSroot == NULL) {
- X warn(0, "CVSROOT variable not set; no log message will be sent");
- X return;
- X }
- X (void) sprintf(logfile, "%s/%s", CVSroot, CVSROOTADM_LOGINFO);
- X if ((fp_info = fopen(logfile, "r")) == NULL) {
- X warn(0, "warning: cannot open %s", logfile);
- X return;
- X }
- X if (CVSroot != NULL)
- X (void) sprintf(path, "%s/", CVSroot);
- X else
- X (void) strcpy(path, REPOS_STRIP);
- X if (strncmp(repository, path, strlen(path)) == 0)
- X short_repository = repository + strlen(path);
- X else
- X short_repository = repository;
- X (void) sprintf(title, "'%s%s'", short_repository, Llist);
- X default_filter[0] = '\0';
- X filter_run = line_number = 0;
- X while (fgets(line, sizeof(line), fp_info) != NULL) {
- X line_number++;
- X if (line[0] == '#')
- X continue;
- X for (cp = line; *cp && isspace(*cp); cp++)
- X ;
- X if (*cp == '\0')
- X continue; /* blank line */
- X for (exp = cp; *cp && !isspace(*cp); cp++)
- X ;
- X if (*cp != '\0')
- X *cp++ = '\0';
- X while (*cp && isspace(*cp))
- X cp++;
- X if (*cp == '\0') {
- X warn(0, "syntax error at line %d file %s; ignored",
- X line_number, logfile);
- X continue;
- X }
- X filter = cp;
- X if ((cp = rindex(filter, '\n')) != NULL)
- X *cp = '\0'; /* strip the newline */
- X /*
- X * At this point, exp points to the regular expression, and
- X * filter points to the program to exec. Evaluate the regular
- X * expression against short_repository and exec the filter
- X * if it matches.
- X */
- X if (strcmp(exp, "DEFAULT") == 0) {
- X (void) strcpy(default_filter, filter);
- X continue;
- X }
- X /*
- X * For a regular expression of "ALL", send the log message
- X * to the requested filter *without* noting that a filter was run.
- X * This allows the "DEFAULT" regular expression to be more
- X * meaningful with all updates going to a master log file.
- X */
- X if (strcmp(exp, "ALL") == 0) {
- X (void) logfile_write(repository, filter, title, message);
- X continue;
- X }
- X if ((cp = re_comp(exp)) != NULL) {
- X warn(0, "bad regular expression at line %d file %s: %s",
- X line_number, logfile, cp);
- X continue;
- X }
- X if (re_exec(short_repository) == 0)
- X continue; /* no match */
- X if (logfile_write(repository, filter, title, message) == 0)
- X filter_run = 1;
- X }
- X if (filter_run == 0 && default_filter[0] != '\0')
- X (void) logfile_write(repository, default_filter, title, message);
- X}
- X
- X/*
- X * Since some systems don't define this...
- X */
- X#ifndef MAXHOSTNAMELEN
- X#define MAXHOSTNAMELEN 64
- X#endif !MAXHOSTNAMELEN
- X
- X/*
- X * Writes some stuff to the logfile "filter" and returns the status of the
- X * filter program.
- X */
- Xstatic
- Xlogfile_write(repository, filter, title, message)
- X char *repository;
- X char *filter;
- X char *title;
- X char *message;
- X{
- X char cwd[MAXPATHLEN], host[MAXHOSTNAMELEN];
- X FILE *fp;
- X char *cp;
- X
- X /*
- X * A maximum of 6 %s arguments are supported in the filter
- X */
- X (void) sprintf(prog, filter, title, title, title, title, title, title);
- X if ((fp = popen(prog, "w")) == NULL) {
- X warn(0, "cannot write entry to log filter: %s", prog);
- X return (1);
- X }
- X if (gethostname(host, sizeof(host)) < 0)
- X (void) strcpy(host, "(unknown)");
- X (void) fprintf(fp, "Update of %s\n", repository);
- X (void) fprintf(fp, "In directory %s:%s\n\n", host,
- X (cp = getwd(cwd)) ? cp : cwd);
- X setup_tmpfile(fp, "");
- X (void) fprintf(fp, "Log Message:\n%s\n", message);
- X return (pclose(fp));
- X}
- X
- X/*
- X * Called when "add"ing files to the RCS respository, as it is necessary
- X * to preserve the file modes in the same fashion that RCS does. This would
- X * be automatic except that we are placing the RCS ,v file very far away from
- X * the user file, and I can't seem to convince RCS of the location of the
- X * user file. So we munge it here, after the ,v file has been successfully
- X * initialized with "rcs -i".
- X */
- Xstatic
- Xfix_rcs_modes(rcs, user)
- X char *rcs;
- X char *user;
- X{
- X struct stat sb;
- X
- X if (stat(user, &sb) != -1) {
- X (void) chmod(rcs, (int) sb.st_mode & ~0222);
- X }
- X}
- X
- Xstatic
- Xcommit_usage()
- X{
- X (void) fprintf(stderr,
- X "%s %s [-fn] [-a] [-m 'message'] [-r revision] [files...]\n",
- X progname, command);
- X exit(1);
- X}
- END_OF_FILE
- if test 21136 -ne `wc -c <'src/commit.c'`; then
- echo shar: \"'src/commit.c'\" unpacked with wrong size!
- fi
- # end of 'src/commit.c'
- fi
- if test -f 'src/partime.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/partime.c'\"
- else
- echo shar: Extracting \"'src/partime.c'\" \(14739 characters\)
- sed "s/^X//" >'src/partime.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char rcsid[] = "$Id: partime.c,v 1.1 89/05/09 11:51:02 berliner Exp $";
- X#endif
- X
- X/*
- X * PARTIME parse date/time string into a TM structure
- X *
- X * Usage:
- X * #include "time.h" -- expanded tm structure
- X * char *str; struct tm *tp;
- X * partime(str,tp);
- X * Returns:
- X * 0 if parsing failed
- X * else time values in specified TM structure (unspecified values
- X * set to TMNULL)
- X * Notes:
- X * This code is quasi-public; it may be used freely in like software.
- X * It is not to be sold, nor used in licensed software without
- X * permission of the author.
- X * For everyone's benefit, please report bugs and improvements!
- X * Copyright 1980 by Ken Harrenstien, SRI International.
- X * (ARPANET: KLH @ SRI)
- X */
- X
- X/* Hacknotes:
- X * If parsing changed so that no backup needed, could perhaps modify
- X * to use a FILE input stream. Need terminator, though.
- X * Perhaps should return 0 on success, else a non-zero error val?
- X * Flush AMPM from TM structure and handle locally within PARTIME,
- X * like midnight/noon?
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "rcstime.h"
- X
- X#ifndef lint
- Xstatic char timeid[] = TIMEID;
- X#endif
- X
- Xstruct tmwent {
- X char *went;
- X long wval; /* must be big enough to hold pointer or integer */
- X char wflgs;
- X char wtype;
- X};
- X /* wflgs */
- X#define TWSPEC 01 /* Word wants special processing */
- X#define TWTIME 02 /* Word is a time value (absence implies date) */
- X#define TWDST 04 /* Word is a DST-type timezone */
- X#define TW1200 010 /* Word is NOON or MIDNIGHT (sigh) */
- X
- Xint pt12hack();
- Xint ptnoise();
- Xstruct tmwent tmwords [] = {
- X {"january", 0, 0, TM_MON},
- X {"february", 1, 0, TM_MON},
- X {"march", 2, 0, TM_MON},
- X {"april", 3, 0, TM_MON},
- X {"may", 4, 0, TM_MON},
- X {"june", 5, 0, TM_MON},
- X {"july", 6, 0, TM_MON},
- X {"august", 7, 0, TM_MON},
- X {"september", 8, 0, TM_MON},
- X {"october", 9, 0, TM_MON},
- X {"november", 10, 0, TM_MON},
- X {"december", 11, 0, TM_MON},
- X
- X {"sunday", 0, 0, TM_WDAY},
- X {"monday", 1, 0, TM_WDAY},
- X {"tuesday", 2, 0, TM_WDAY},
- X {"wednesday", 3, 0, TM_WDAY},
- X {"thursday", 4, 0, TM_WDAY},
- X {"friday", 5, 0, TM_WDAY},
- X {"saturday", 6, 0, TM_WDAY},
- X
- X {"gmt", 0*60, TWTIME, TM_ZON}, /* Greenwich */
- X {"gst", 0*60, TWTIME, TM_ZON},
- X {"gdt", 0*60, TWTIME+TWDST, TM_ZON}, /* ?? */
- X
- X {"ast", 4*60, TWTIME, TM_ZON}, /* Atlantic */
- X {"est", 5*60, TWTIME, TM_ZON}, /* Eastern */
- X {"cst", 6*60, TWTIME, TM_ZON}, /* Central */
- X {"mst", 7*60, TWTIME, TM_ZON}, /* Mountain */
- X {"pst", 8*60, TWTIME, TM_ZON}, /* Pacific */
- X {"yst", 9*60, TWTIME, TM_ZON}, /* Yukon */
- X {"hst", 10*60, TWTIME, TM_ZON}, /* Hawaii */
- X {"bst", 11*60, TWTIME, TM_ZON}, /* Bering */
- X
- X {"adt", 4*60, TWTIME+TWDST, TM_ZON}, /* Atlantic */
- X {"edt", 5*60, TWTIME+TWDST, TM_ZON}, /* Eastern */
- X {"cdt", 6*60, TWTIME+TWDST, TM_ZON}, /* Central */
- X {"mdt", 7*60, TWTIME+TWDST, TM_ZON}, /* Mountain */
- X {"pdt", 8*60, TWTIME+TWDST, TM_ZON}, /* Pacific */
- X {"ydt", 9*60, TWTIME+TWDST, TM_ZON}, /* Yukon */
- X {"hdt", 10*60, TWTIME+TWDST, TM_ZON}, /* Hawaii */
- X {"bdt", 11*60, TWTIME+TWDST, TM_ZON}, /* Bering */
- X
- X {"daylight", 1, TWTIME+TWDST, TM_ZON}, /* Local Daylight */
- X {"standard", 1, TWTIME, TM_ZON}, /* Local Standard */
- X {"std", 1, TWTIME, TM_ZON}, /* " " */
- X
- X {"am", 1, TWTIME, TM_AMPM},
- X {"pm", 2, TWTIME, TM_AMPM},
- X {"noon", 12,TWTIME+TW1200, 0}, /* Special frobs */
- X {"midnight", 0, TWTIME+TW1200, 0},
- X {"at", (long)ptnoise, TWSPEC, 0}, /* Noise word */
- X
- X {0, 0, 0, 0}, /* Zero entry to terminate searches */
- X};
- X
- X#define TMWILD (-2) /* Value meaning item specified as wild-card */
- X /* (May use someday...) */
- X
- Xstruct token {
- X char *tcp; /* pointer to string */
- X int tcnt; /* # chars */
- X char tbrk; /* "break" char */
- X char tbrkl; /* last break char */
- X char tflg; /* 0 = alpha, 1 = numeric */
- X union { /* Resulting value; */
- X int tnum;/* either a #, or */
- X struct tmwent *ttmw;/* ptr to a tmwent. */
- X } tval;
- X};
- X
- Xpartime(astr, atm)
- Xchar *astr;
- Xstruct tm *atm;
- X{ register int *tp;
- X register struct tmwent *twp;
- X register int i;
- X struct token btoken, atoken;
- X char *cp, ch;
- X int ord, midnoon;
- X int (*aproc)();
- X
- X tp = (int *)atm;
- X zaptime(tp); /* Initialize the TM structure */
- X midnoon = TMNULL; /* and our own temp stuff */
- X btoken.tcnt = btoken.tbrkl = 0;
- X btoken.tcp = astr;
- X
- Xdomore:
- X if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken)) /* Get a token */
- X { if(btoken.tval.tnum) return(0); /* Read error? */
- X if(midnoon != TMNULL) /* EOF, wrap up */
- X return(pt12hack(tp, midnoon));
- X return(1); /* Win return! */
- X }
- X if(btoken.tflg == 0) /* Alpha? */
- X { twp = btoken.tval.ttmw; /* Yes, get ptr to entry */
- X if(twp->wflgs&TWSPEC) /* Special alpha crock */
- X { aproc = (int (*) ()) (twp->wval);
- X if(!(*aproc)(tp, twp, &btoken))
- X return(0); /* ERR: special word err */
- X goto domore;
- X }
- X if(twp->wflgs&TW1200)
- X if(ptstash(&midnoon,(int)twp->wval))
- X return(0); /* ERR: noon/midnite clash */
- X else goto domore;
- X if(ptstash(&tp[twp->wtype],(int)twp->wval))
- X return(0); /* ERR: val already set */
- X if(twp->wtype == TM_ZON) /* If was zone, hack DST */
- X if(ptstash(&tp[TM_ISDST],(twp->wflgs&TWDST)))
- X return(0); /* ERR: DST conflict */
- X goto domore;
- X }
- X
- X /* Token is number. Lots of hairy heuristics. */
- X if(btoken.tcnt >= 7) /* More than 6 digits in string? */
- X return(0); /* ERR: number too big */
- X if(btoken.tcnt == 6) /* 6 digits = HHMMSS. Needs special crock */
- X { /* since 6 digits are too big for integer! */
- X i = (btoken.tcp[0]-'0')*10 /* Gobble 1st 2 digits */
- X + btoken.tcp[1]-'0';
- X btoken.tcnt = 2; /* re-read last 4 chars */
- X goto coltime;
- X }
- X
- X i = btoken.tval.tnum; /* Value now known to be valid; get it. */
- X if( btoken.tcnt == 5 /* 5 digits = HMMSS */
- X || btoken.tcnt == 3) /* 3 digits = HMM */
- X { if(btoken.tcnt != 3)
- X if(ptstash(&tp[TM_SEC], i%100))
- X return(0); /* ERR: sec conflict */
- X else i /= 100;
- Xhhmm4: if(ptstash(&tp[TM_MIN], i%100))
- X return(0); /* ERR: min conflict */
- X i /= 100;
- Xhh2: if(ptstash(&tp[TM_HOUR], i))
- X return(0); /* ERR: hour conflict */
- X goto domore;
- X }
- X
- X if(btoken.tcnt == 4) /* 4 digits = YEAR or HHMM */
- X { if(tp[TM_YEAR] != TMNULL) goto hhmm4; /* Already got yr? */
- X if(tp[TM_HOUR] != TMNULL) goto year4; /* Already got hr? */
- X if((i%100) > 59) goto year4; /* MM >= 60? */
- X if(btoken.tbrk == ':') /* HHMM:SS ? */
- X if( ptstash(&tp[TM_HOUR],i/100)
- X || ptstash(&tp[TM_MIN], i%100))
- X return(0); /* ERR: hr/min clash */
- X else goto coltm2; /* Go handle SS */
- X if(btoken.tbrk != ',' && btoken.tbrk != '/'
- X && ptitoken(btoken.tcp+btoken.tcnt,&atoken) /* Peek */
- X && atoken.tflg == 0 /* alpha */
- X && (atoken.tval.ttmw->wflgs&TWTIME)) /* HHMM-ZON */
- X goto hhmm4;
- X if(btoken.tbrkl == '-' /* DD-Mon-YYYY */
- X || btoken.tbrkl == ',' /* Mon DD, YYYY */
- X || btoken.tbrkl == '/' /* MM/DD/YYYY */
- X || btoken.tbrkl == '.' /* DD.MM.YYYY */
- X || btoken.tbrk == '-' /* YYYY-MM-DD */
- X ) goto year4;
- X goto hhmm4; /* Give up, assume HHMM. */
- X }
- X
- X /* From this point on, assume tcnt == 1 or 2 */
- X /* 2 digits = YY, MM, DD, or HH (MM and SS caught at coltime) */
- X if(btoken.tbrk == ':') /* HH:MM[:SS] */
- X goto coltime; /* must be part of time. */
- X if(i > 31) goto yy2; /* If >= 32, only YY poss. */
- X
- X /* Check for numerical-format date */
- X for (cp = "/-."; ch = *cp++;)
- X { ord = (ch == '.' ? 0 : 1); /* n/m = D/M or M/D */
- X if(btoken.tbrk == ch) /* "NN-" */
- X { if(btoken.tbrkl != ch)
- X { if(ptitoken(btoken.tcp+btoken.tcnt,&atoken)
- X && atoken.tflg == 0
- X && atoken.tval.ttmw->wtype == TM_MON)
- X goto dd2;
- X if(ord)goto mm2; else goto dd2; /* "NN-" */
- X } /* "-NN-" */
- X if(tp[TM_DAY] == TMNULL
- X && tp[TM_YEAR] != TMNULL) /* If "YY-NN-" */
- X goto mm2; /* then always MM */
- X if(ord)goto dd2; else goto mm2;
- X }
- X if(btoken.tbrkl == ch /* "-NN" */
- X && tp[ord ? TM_MON : TM_DAY] != TMNULL)
- X if(tp[ord ? TM_DAY : TM_MON] == TMNULL) /* MM/DD */
- X if(ord)goto dd2; else goto mm2;
- X else goto yy2; /* "-YY" */
- X }
- X
- X /* At this point only YY, DD, and HH are left.
- X * YY is very unlikely since value is <= 32 and there was
- X * no numerical format date. Make one last try at YY
- X * before dropping through to DD vs HH code.
- X */
- X if(btoken.tcnt == 2 /* If 2 digits */
- X && tp[TM_HOUR] != TMNULL /* and already have hour */
- X && tp[TM_DAY] != TMNULL /* and day, but */
- X && tp[TM_YEAR] == TMNULL) /* no year, then assume */
- X goto yy2; /* that's what we have. */
- X
- X /* Now reduced to choice between HH and DD */
- X if(tp[TM_HOUR] != TMNULL) goto dd2; /* Have hour? Assume day. */
- X if(tp[TM_DAY] != TMNULL) goto hh2; /* Have day? Assume hour. */
- X if(i > 24) goto dd2; /* Impossible HH means DD */
- X if(!ptitoken(btoken.tcp+btoken.tcnt, &atoken)) /* Read ahead! */
- X if(atoken.tval.tnum) return(0); /* ERR: bad token */
- X else goto dd2; /* EOF, assume day. */
- X if( atoken.tflg == 0 /* If next token is an alpha */
- X && atoken.tval.ttmw->wflgs&TWTIME) /* time-spec, assume hour */
- X goto hh2; /* e.g. "3 PM", "11-EDT" */
- X
- Xdd2: if(ptstash(&tp[TM_DAY],i)) /* Store day (1 based) */
- X return(0);
- X goto domore;
- X
- Xmm2: if(ptstash(&tp[TM_MON], i-1)) /* Store month (make zero based) */
- X return(0);
- X goto domore;
- X
- Xyy2: i += 1900;
- Xyear4: if(ptstash(&tp[TM_YEAR],i)) /* Store year (full number) */
- X return(0); /* ERR: year conflict */
- X goto domore;
- X
- X /* Hack HH:MM[[:]SS] */
- Xcoltime:
- X if(ptstash(&tp[TM_HOUR],i)) return(0);
- X if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
- X return(!btoken.tval.tnum);
- X if(!btoken.tflg) return(0); /* ERR: HH:<alpha> */
- X if(btoken.tcnt == 4) /* MMSS */
- X if(ptstash(&tp[TM_MIN],btoken.tval.tnum/100)
- X || ptstash(&tp[TM_SEC],btoken.tval.tnum%100))
- X return(0);
- X else goto domore;
- X if(btoken.tcnt != 2
- X || ptstash(&tp[TM_MIN],btoken.tval.tnum))
- X return(0); /* ERR: MM bad */
- X if(btoken.tbrk != ':') goto domore; /* Seconds follow? */
- Xcoltm2: if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
- X return(!btoken.tval.tnum);
- X if(!btoken.tflg || btoken.tcnt != 2 /* Verify SS */
- X || ptstash(&tp[TM_SEC], btoken.tval.tnum))
- X return(0); /* ERR: SS bad */
- X goto domore;
- X}
- X
- X/* Store date/time value, return 0 if successful.
- X * Fails if entry already set to a different value.
- X */
- Xptstash(adr,val)
- Xint *adr;
- X{ register int *a;
- X if( *(a=adr) != TMNULL)
- X return(*a != val);
- X *a = val;
- X return(0);
- X}
- X
- X/* This subroutine is invoked for NOON or MIDNIGHT when wrapping up
- X * just prior to returning from partime.
- X */
- Xpt12hack(atp, aval)
- Xint *atp, aval;
- X{ register int *tp, i, h;
- X tp = atp;
- X if (((i=tp[TM_MIN]) && i != TMNULL) /* Ensure mins, secs */
- X || ((i=tp[TM_SEC]) && i != TMNULL)) /* are 0 or unspec'd */
- X return(0); /* ERR: MM:SS not 00:00 */
- X i = aval; /* Get 0 or 12 (midnite or noon) */
- X if ((h = tp[TM_HOUR]) == TMNULL /* If hour unspec'd, win */
- X || h == 12) /* or if 12:00 (matches either) */
- X tp[TM_HOUR] = i; /* Then set time */
- X else if(!(i == 0 /* Nope, but if midnight and */
- X &&(h == 0 || h == 24))) /* time matches, can pass. */
- X return(0); /* ERR: HH conflicts */
- X tp[TM_AMPM] = TMNULL; /* Always reset this value if won */
- X return(1);
- X}
- X
- X/* Null routine for no-op tokens */
- X
- Xptnoise() { return(1); }
- X
- X/* Get a token and identify it to some degree.
- X * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
- X * hit error of some sort
- X */
- X
- Xptitoken(astr, tkp)
- Xregister struct token *tkp;
- Xchar *astr;
- X{
- X register char *cp;
- X register int i;
- X
- X tkp->tval.tnum = 0;
- X if(pttoken(astr,tkp) == 0)
- X#ifdef DEBUG
- X VOID printf("EOF\n");
- X#endif DEBUG
- X return(0);
- X cp = tkp->tcp;
- X
- X#ifdef DEBUG
- X i = cp[tkp->tcnt];
- X cp[tkp->tcnt] = 0;
- X VOID printf("Token: \"%s\" ",cp);
- X cp[tkp->tcnt] = i;
- X#endif DEBUG
- X
- X if(tkp->tflg)
- X for(i = tkp->tcnt; i > 0; i--)
- X tkp->tval.tnum = (int)tkp->tval.tnum*10 + ((*cp++)-'0');
- X else
- X { i = ptmatchstr(cp, tkp->tcnt, tmwords);
- X tkp->tval.tnum = i ? i : -1; /* Set -1 for error */
- X
- X#ifdef DEBUG
- X if(!i) VOID printf("Not found!\n");
- X#endif DEBUG
- X
- X if(!i) return(0);
- X }
- X
- X#ifdef DEBUG
- X if(tkp->tflg)
- X VOID printf("Val: %d.\n",tkp->tval.tnum);
- X else VOID printf("Found: \"%s\", val: %d., type %d\n",
- X tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
- X#endif DEBUG
- X
- X return(1);
- X}
- X
- X/* Read token from input string into token structure */
- Xpttoken(astr,tkp)
- Xregister struct token *tkp;
- Xchar *astr;
- X{
- X register char *cp;
- X register int c;
- X
- X tkp->tcp = cp = astr;
- X tkp->tbrkl = tkp->tbrk; /* Set "last break" */
- X tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
- X
- X while(c = *cp++)
- X { switch(c)
- X { case ' ': case '\t': /* Flush all whitespace */
- X while((c = *cp++) && isspace(c));
- X cp--; /* Drop thru to handle brk */
- X case '(': case ')': /* Perhaps any non-alphanum */
- X case '-': case ',': /* shd qualify as break? */
- X case '/': case ':': case '.': /* Break chars */
- X if(tkp->tcnt == 0) /* If no token yet */
- X { tkp->tcp = cp; /* ignore the brk */
- X tkp->tbrkl = c;
- X continue; /* and go on. */
- X }
- X tkp->tbrk = c;
- X return(tkp->tcnt);
- X }
- X if(tkp->tcnt == 0) /* If first char of token, */
- X tkp->tflg = isdigit(c); /* determine type */
- X if(( isdigit(c) && tkp->tflg) /* If not first, make sure */
- X ||(!isdigit(c) && !tkp->tflg)) /* char matches type */
- X tkp->tcnt++; /* Win, add to token. */
- X else {
- X cp--; /* Wrong type, back up */
- X tkp->tbrk = c;
- X return(tkp->tcnt);
- X }
- X }
- X return(tkp->tcnt); /* When hit EOF */
- X}
- X
- X
- Xptmatchstr(astr,cnt,astruc)
- Xchar *astr;
- Xint cnt;
- Xstruct tmwent *astruc;
- X{ register char *cp, *mp;
- X register int c;
- X struct tmwent *lastptr;
- X struct integ { int word; }; /* For getting at array ptr */
- X int i;
- X
- X lastptr = 0;
- X for(;mp = (char *)((struct integ *)astruc)->word; astruc += 1)
- X { cp = astr;
- X for(i = cnt; i > 0; i--)
- X { switch((c = *cp++) ^ *mp++) /* XOR the chars */
- X { case 0: continue; /* Exact match */
- X case 040: if(isalpha(c))
- X continue;
- X }
- X break;
- X }
- X if(i==0)
- X if(*mp == 0) return((unsigned int)astruc); /* Exact match */
- X else if(lastptr) return(0); /* Ambiguous */
- X else lastptr = astruc; /* 1st ambig */
- X }
- X return((unsigned int)lastptr);
- X}
- X
- X
- X
- Xzaptime(tp)
- Xregister int *tp;
- X/* clears tm structure pointed to by tp */
- X{ register int i;
- X i = (sizeof (struct tm))/(sizeof (int));
- X do *tp++ = TMNULL; /* Set entry to "unspecified" */
- X while(--i); /* Faster than FOR */
- X}
- END_OF_FILE
- if test 14739 -ne `wc -c <'src/partime.c'`; then
- echo shar: \"'src/partime.c'\" unpacked with wrong size!
- fi
- # end of 'src/partime.c'
- fi
- echo shar: End of archive 5 \(of 7\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- exit 0 # Just in case...
-