Newsgroups: comp.sources.unix
From: pmiller@bmr.gov.au (Peter Miller)
Subject: v27i048: aegis - project change supervisor (V2.1), Part13/19
References: <1.748951883.12788@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com

Submitted-By: pmiller@bmr.gov.au (Peter Miller)
Posting-Number: Volume 27, Issue 48
Archive-Name: aegis-2.1/part13

#! /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 13 (of 19)."
# Contents:  CHANGES aegis/aed.c aegis/aeib.c aegis/os.c
#   aux/CHANGES.1.2
# Wrapped by vixie@gw.home.vix.com on Sat Sep 25 03:00:49 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CHANGES'\"
else
echo shar: Extracting \"'CHANGES'\" \(26959 characters\)
sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
X
X
X
XProject "aegis.2.1"						 Page 1
XList of Changes				       Fri Aug 20 22:56:36 1993
X
XChange	State		Description
X------- -------		-------------
X   1	completed	New release derived from aegis.2.0.
X   2	completed	additional support for generating patches
X   3	completed	bug in list
X   4	completed	keep old change logs
X   5	completed	rename some source files
X   6	being_		fix version in readme
X	integrated
X
X
X
XProject "aegis.2.1", Change 1					 Page 1
XChange Details				       Fri Aug 20 22:56:40 1993
X
XNAME
X	Project "aegis.2.1", Delta 1, Change 1.
X
XSUMMARY
X	New release derived from aegis.2.0.
X
XDESCRIPTION
X	New release derived from aegis.2.0.
X
X	This change is exempt from testing against the development
X	directory.  This change is exempt from testing against the
X	baseline.
X
XCAUSE
X	This change was caused by internal_enhancement.
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	LICENSE
X	source	create	1	aegis/administ.c
X	source	create	1	aegis/administ.h
X	source	create	1	aegis/arglex2.h
X	source	create	1	aegis/build.c
X	source	create	1	aegis/build.h
X	source	create	1	aegis/cattr.def
X	source	create	1	aegis/cattr_ed.c
X	source	create	1	aegis/cattr_ed.h
X	source	create	1	aegis/change.c
X	source	create	1	aegis/change.h
X	source	create	1	aegis/chdir.c
X	source	create	1	aegis/chdir.h
X	source	create	1	aegis/col.c
X	source	create	1	aegis/col.h
X	source	create	1	aegis/commit.c
X	source	create	1	aegis/commit.h
X	source	create	1	aegis/common.def
X	source	create	1	aegis/copyfile.c
X	source	create	1	aegis/copyfile.h
X	source	create	1	aegis/cstate.def
X	source	create	1	aegis/develop1.c
X	source	create	1	aegis/develop1.h
X	source	create	1	aegis/develop2.c
X	source	create	1	aegis/develop2.h
X	source	create	1	aegis/diff.c
X	source	create	1	aegis/diff.h
X	source	create	1	aegis/dir.c
X	source	create	1	aegis/dir.h
X	source	create	1	aegis/file.c
X	source	create	1	aegis/file.h
X	source	create	1	aegis/glue.c
X	source	create	1	aegis/glue.h
X	source	create	1	aegis/gonzo.c
X	source	create	1	aegis/gonzo.h
X	source	create	1	aegis/gram.h
X	source	create	1	aegis/gram.y
X	source	create	1	aegis/gstate.def
X
X
X
XProject "aegis.2.1", Change 1					 Page 2
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	aegis/help.c
X	source	create	1	aegis/help.h
X	source	create	1	aegis/indent.c
X	source	create	1	aegis/indent.h
X	source	create	1	aegis/integra1.c
X	source	create	1	aegis/integra1.h
X	source	create	1	aegis/integra2.c
X	source	create	1	aegis/integra2.h
X	source	create	1	aegis/io.c
X	source	create	1	aegis/io.h
X	source	create	1	aegis/lex.c
X	source	create	1	aegis/lex.h
X	source	create	1	aegis/list.c
X	source	create	1	aegis/list.h
X	source	create	1	aegis/lock.c
X	source	create	1	aegis/lock.h
X	source	create	1	aegis/log.c
X	source	create	1	aegis/log.h
X	source	create	1	aegis/main.c
X	source	create	1	aegis/mv.c
X	source	create	1	aegis/mv.h
X	source	create	1	aegis/new_chan.c
X	source	create	1	aegis/new_chan.h
X	source	create	1	aegis/new_file.c
X	source	create	1	aegis/new_file.h
X	source	create	1	aegis/new_proj.c
X	source	create	1	aegis/new_proj.h
X	source	create	1	aegis/new_rele.c
X	source	create	1	aegis/new_rele.h
X	source	create	1	aegis/new_test.c
X	source	create	1	aegis/new_test.h
X	source	create	1	aegis/os.c
X	source	create	1	aegis/os.h
X	source	create	1	aegis/pager.c
X	source	create	1	aegis/pager.h
X	source	create	1	aegis/parse.c
X	source	create	1	aegis/parse.h
X	source	create	1	aegis/pattr.def
X	source	create	1	aegis/pattr_ed.c
X	source	create	1	aegis/pattr_ed.h
X	source	create	1	aegis/pconf.def
X	source	create	1	aegis/project.c
X	source	create	1	aegis/project.h
X	source	create	1	aegis/pstate.def
X	source	create	1	aegis/rem_file.c
X	source	create	1	aegis/rem_file.h
X	source	create	1	aegis/rem_proj.c
X	source	create	1	aegis/rem_proj.h
X	source	create	1	aegis/review.c
X	source	create	1	aegis/review.h
X	source	create	1	aegis/reviewer.c
X	source	create	1	aegis/reviewer.h
X	source	create	1	aegis/sub.c
X	source	create	1	aegis/sub.h
X	source	create	1	aegis/test.c
X
X
X
XProject "aegis.2.1", Change 1					 Page 3
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	aegis/test.h
X	source	create	1	aegis/type.c
X	source	create	1	aegis/type.h
X	source	create	1	aegis/uconf.def
X	source	create	1	aegis/undo.c
X	source	create	1	aegis/undo.h
X	source	create	1	aegis/user.c
X	source	create	1	aegis/user.h
X	source	create	1	aegis/ustate.def
X	source	create	1	aegis/version.c
X	source	create	1	aegis/version.h
X	source	create	1	aux/BUILDING.man
X	source	create	1	aux/CHANGES.sh
X	source	create	1	aux/Howto.cook
X	source	create	1	aux/MANIFEST.sh
X	source	create	1	aux/Makefile.awk
X	source	create	1	aux/Makefile.sh
X	source	create	1	aux/README.man
X	source	create	1	aux/new.1.4.so
X	source	create	1	aux/new.2.0.so
X	source	create	1	aux/patches.sh
X	source	create	1	common/ansi.c
X	source	create	1	common/arglex.c
X	source	create	1	common/arglex.h
X	source	create	1	common/error.c
X	source	create	1	common/error.h
X	source	create	1	common/main.h
X	source	create	1	common/mem.c
X	source	create	1	common/mem.h
X	source	create	1	common/option.c
X	source	create	1	common/option.h
X	source	create	1	common/s-v-arg.h
X	source	create	1	common/str.c
X	source	create	1	common/str.h
X	source	create	1	common/trace.c
X	source	create	1	common/trace.h
X	source	create	1	common/word.c
X	source	create	1	common/word.h
X	source	create	1	conf/AIX-3.2
X	source	create	1	conf/ConvexOS-10
X	source	create	1	conf/IRIX-4.0
X	source	create	1	conf/Linux-0.99
X	source	create	1	conf/SCO-2.4
X	source	create	1	conf/SunOS-4.1.1
X	source	create	1	conf/SunOS-4.1.2
X	source	create	1	conf/SunOS-4.1.3
X	source	create	1	conf/SunOS-5.1
X	source	create	1	conf/SysV-4.0
X	source	create	1	conf/ULTRIX-4.2
X	source	create	1	conf/apollo
X	source	create	1	conf/dcosx
X	source	create	1	conf/dgux-5.4.1
X	source	create	1	conf/hpux-8.07
X	source	create	1	config
X	source	create	1	doc/aegis.ms
X
X
X
XProject "aegis.2.1", Change 1					 Page 4
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	doc/c1.0.so
X	source	create	1	doc/c1.1.so
X	source	create	1	doc/c1.2.so
X	source	create	1	doc/c1.3.so
X	source	create	1	doc/c1.4.so
X	source	create	1	doc/c2.0.so
X	source	create	1	doc/c2.1.so
X	source	create	1	doc/c2.2.so
X	source	create	1	doc/c2.3.so
X	source	create	1	doc/c2.4.so
X	source	create	1	doc/c2.5.so
X	source	create	1	doc/c3.0.so
X	source	create	1	doc/c3.1.so
X	source	create	1	doc/c3.2.so
X	source	create	1	doc/c3.3.so
X	source	create	1	doc/c4.0.so
X	source	create	1	doc/c4.1.so
X	source	create	1	doc/c4.2.so
X	source	create	1	doc/c4.3.so
X	source	create	1	doc/c5.0.so
X	source	create	1	doc/c6.0.so
X	source	create	1	doc/c7.0.so
X	source	create	1	doc/c7.1.so
X	source	create	1	doc/c7.2.so
X	source	create	1	doc/c7.4.so
X	source	create	1	doc/c7.5.so
X	source	create	1	doc/c8.0.so
X	source	create	1	doc/c8.1.so
X	source	create	1	doc/c8.2.so
X	source	create	1	doc/c8.3.so
X	source	create	1	doc/cA.0.so
X	source	create	1	doc/cB.0.so
X	source	create	1	doc/cC.0.so
X	source	create	1	fmtgen/id.c
X	source	create	1	fmtgen/id.h
X	source	create	1	fmtgen/indent.c
X	source	create	1	fmtgen/indent.h
X	source	create	1	fmtgen/lex.c
X	source	create	1	fmtgen/lex.h
X	source	create	1	fmtgen/main.c
X	source	create	1	fmtgen/parse.h
X	source	create	1	fmtgen/parse.y
X	source	create	1	fmtgen/type.c
X	source	create	1	fmtgen/type.h
X	source	create	1	fmtgen/type_enum.c
X	source	create	1	fmtgen/type_integ.c
X	source	create	1	fmtgen/type_list.c
X	source	create	1	fmtgen/type_ref.c
X	source	create	1	fmtgen/type_strin.c
X	source	create	1	fmtgen/type_struc.c
X	source	create	1	h/dirent.h
X	source	create	1	h/stdarg.h-min
X	source	create	1	h/stddef.h
X	source	create	1	h/stdlib.h
X	source	create	1	h/unistd.h
X
X
X
XProject "aegis.2.1", Change 1					 Page 5
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	h/utime.h
X	source	create	1	lib/aegis.icon
X	source	create	1	lib/aegis.mask
X	source	create	1	lib/aegis.pgm
X	source	create	1	lib/cshrc
X	source	create	1	lib/de.inews.sh
X	source	create	1	lib/de.sh
X	source	create	1	lib/deu.inews.sh
X	source	create	1	lib/deu.sh
X	source	create	1	lib/if.inews.sh
X	source	create	1	lib/if.sh
X	source	create	1	lib/ip.inews.sh
X	source	create	1	lib/ip.sh
X	source	create	1	lib/profile
X	source	create	1	lib/rf.inews.sh
X	source	create	1	lib/rf.sh
X	source	create	1	lib/rp.inews.sh
X	source	create	1	lib/rp.sh
X	source	create	1	lib/rpu.inews.sh
X	source	create	1	lib/rpu.sh
X	source	create	1	man1/aeb.1
X	source	create	1	man1/aeca.1
X	source	create	1	man1/aecd.1
X	source	create	1	man1/aecp.1
X	source	create	1	man1/aecpu.1
X	source	create	1	man1/aed.1
X	source	create	1	man1/aedb.1
X	source	create	1	man1/aedbu.1
X	source	create	1	man1/aede.1
X	source	create	1	man1/aedeu.1
X	source	create	1	man1/aegis.1
X	source	create	1	man1/aeib.1
X	source	create	1	man1/aeibu.1
X	source	create	1	man1/aeif.1
X	source	create	1	man1/aeip.1
X	source	create	1	man1/ael.1
X	source	create	1	man1/aemv.1
X	source	create	1	man1/aena.1
X	source	create	1	man1/aenc.1
X	source	create	1	man1/aencu.1
X	source	create	1	man1/aend.1
X	source	create	1	man1/aenf.1
X	source	create	1	man1/aenfu.1
X	source	create	1	man1/aeni.1
X	source	create	1	man1/aenpr.1
X	source	create	1	man1/aenrls.1
X	source	create	1	man1/aenrv.1
X	source	create	1	man1/aent.1
X	source	create	1	man1/aentu.1
X	source	create	1	man1/aepa.1
X	source	create	1	man1/aera.1
X	source	create	1	man1/aerd.1
X	source	create	1	man1/aerf.1
X	source	create	1	man1/aeri.1
X	source	create	1	man1/aerm.1
X
X
X
XProject "aegis.2.1", Change 1					 Page 6
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	man1/aermpr.1
X	source	create	1	man1/aermu.1
X	source	create	1	man1/aerp.1
X	source	create	1	man1/aerpu.1
X	source	create	1	man1/aerrv.1
X	source	create	1	man1/aet.1
X	source	create	1	man1/aev.1
X	source	create	1	man1/install.sh
X	source	create	1	man1/o__rules.so
X	source	create	1	man1/o_anticip.so
X	source	create	1	man1/o_auto.so
X	source	create	1	man1/o_baselin.so
X	source	create	1	man1/o_bld_lk.so
X	source	create	1	man1/o_change.so
X	source	create	1	man1/o_devdir.so
X	source	create	1	man1/o_dir.so
X	source	create	1	man1/o_edit.so
X	source	create	1	man1/o_help.so
X	source	create	1	man1/o_indep.so
X	source	create	1	man1/o_keep.so
X	source	create	1	man1/o_lib.so
X	source	create	1	man1/o_list.so
X	source	create	1	man1/o_major.so
X	source	create	1	man1/o_manual.so
X	source	create	1	man1/o_min.so
X	source	create	1	man1/o_minor.so
X	source	create	1	man1/o_nolog.so
X	source	create	1	man1/o_overw.so
X	source	create	1	man1/o_page.so
X	source	create	1	man1/o_project.so
X	source	create	1	man1/o_terse.so
X	source	create	1	man1/o_unforma.so
X	source	create	1	man1/o_verbose.so
X	source	create	1	man1/z_cr.so
X	source	create	1	man1/z_exit.so
X	source	create	1	man1/z_intuit.so
X	source	create	1	man1/z_name.so
X	source	create	1	man5/aecattr.5
X	source	create	1	man5/aecattr.so
X	source	create	1	man5/aecstate.5
X	source	create	1	man5/aedir.5
X	source	create	1	man5/aegis.5
X	source	create	1	man5/aegstate.5
X	source	create	1	man5/aepattr.5
X	source	create	1	man5/aepattr.so
X	source	create	1	man5/aepconf.5
X	source	create	1	man5/aepstate.5
X	source	create	1	man5/aesub.5
X	source	create	1	man5/aeuconf.5
X	source	create	1	man5/aeustate.5
X	source	create	1	man5/install.sh
X	source	create	1	man5/z_cr.so
X	source	create	1	man5/z_name.so
X	source	create	1	script/aegis.synpic
X	source	create	1	script/xaegis.tcl
X
X
X
XProject "aegis.2.1", Change 1					 Page 7
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	test	create	1	test/00/t0001a.sh
X	test	create	1	test/00/t0002a.sh
X	test	create	1	test/00/t0003a.sh
X	test	create	1	test/00/t0004a.sh
X	test	create	1	test/00/t0005a.sh
X	test	create	1	test/00/t0006a.sh
X	test	create	1	test/00/t0007a.sh
X	test	create	1	test/00/t0008a.sh
X	test	create	1	test/00/t0009a.sh
X	test	create	1	test/00/t0010a.sh
X	test	create	1	test/00/t0011a.sh
X	test	create	1	test/00/t0012a.sh
X	test	create	1	test/00/t0013a.sh
X	test	create	1	test/00/t0014a.sh
X	test	create	1	test/00/t0015a.sh
X	test	create	1	test/00/t0016a.sh
X	test	create	1	test/00/t0017a.sh
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Wed Aug 18	pmiller
X			13:47:59 1993
X	develop_begin	Wed Aug 18	pmiller
X			13:47:59 1993
X	develop_end	Wed Aug 18	pmiller
X			13:47:59 1993
X	review_pass	Wed Aug 18	pmiller
X			13:47:59 1993
X	integrate_begin Wed Aug 18	pmiller Elapsed time: 0.031
X			13:47:59 1993		days.
X	integrate_pass	Wed Aug 18	pmiller
X			14:01:55 1993
X
X
X
XProject "aegis.2.1", Change 2					 Page 1
XChange Details				       Fri Aug 20 22:56:40 1993
X
XNAME
X	Project "aegis.2.1", Delta 3, Change 2.
X
XSUMMARY
X	additional support for generating patches
X
XDESCRIPTION
X	Aegis now supports the concept of source files automatically
X	update by the integration build, even if they are not part of
X	a change.  This results in them automatically being added to a
X	change at integrate pass time, so that their histories may be
X	updated.	 Updating the histories then allows patches to
X	be generated, and earlier version reconstructed.
X
XCAUSE
X	This change was caused by internal_enhancement.
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	aegis/aecp.c
X				Moved from aegis/copyfile.c
X	source	create	1	aegis/aecp.h
X				Moved from aegis/copyfile.h
X	source	create	1	aegis/aecpu.c
X				Moved from aegis/copyfile.c
X	source	create	1	aegis/aecpu.h
X				Moved from aegis/copyfile.h
X	source	create	1	aegis/aed.c
X				Moved from aegis/diff.c
X	source	create	1	aegis/aed.h
X				Moved from aegis/diff.h
X	source	create	1	aegis/aedb.c
X				Moved from aegis/develop2.c
X	source	create	1	aegis/aedb.h
X				Moved from aegis/develop2.h
X	source	create	1	aegis/aedbu.c
X				Moved from aegis/develop2.c
X	source	create	1	aegis/aedbu.h
X				Moved from aegis/develop2.h
X	source	create	1	aegis/aede.c
X				Moved from aegis/develop2.c
X	source	create	1	aegis/aede.h
X				Moved from aegis/develop2.h
X	source	create	1	aegis/aedeu.c
X				Moved from aegis/develop2.c
X	source	create	1	aegis/aedeu.h
X				Moved from aegis/develop2.h
X	source	create	1	aegis/aeib.c
X				Moved from aegis/integra2.c
X	source	create	1	aegis/aeib.h
X				Moved from aegis/integra2.h
X	source	create	1	aegis/aeibu.c
X				Moved from aegis/integra2.c
X	source	create	1	aegis/aeibu.h
X				Moved from aegis/integra2.h
X	source	create	1	aegis/aeif.c
X
X
X
XProject "aegis.2.1", Change 2					 Page 2
XChange Details				       Fri Aug 20 22:56:40 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X				Moved from aegis/integra2.c
X	source	create	1	aegis/aeif.h
X				Moved from aegis/integra2.h
X	source	create	1	aegis/aeip.c
X				Moved from aegis/integra2.c
X	source	create	1	aegis/aeip.h
X				Moved from aegis/integra2.h
X	source	create	1	aegis/aemv.c
X				Moved from aegis/mv.c
X	source	create	1	aegis/aemv.h
X				Moved from aegis/mv.h
X	source	create	1	aegis/aenf.c
X				Moved from aegis/new_file.c
X	source	create	1	aegis/aenf.h
X				Moved from aegis/new_file.h
X	source	create	1	aegis/aenfu.c
X				Moved from aegis/new_file.c
X	source	create	1	aegis/aenfu.h
X				Moved from aegis/new_file.h
X	source	modify	2	aegis/common.def
X	source	remove	1	aegis/copyfile.c
X	source	remove	1	aegis/copyfile.h
X	source	remove	1	aegis/develop2.c
X	source	remove	1	aegis/develop2.h
X	source	remove	1	aegis/diff.c
X	source	remove	1	aegis/diff.h
X	source	remove	1	aegis/integra2.c
X	source	remove	1	aegis/integra2.h
X	source	modify	2	aegis/main.c
X	source	remove	1	aegis/mv.c
X	source	remove	1	aegis/mv.h
X	source	remove	1	aegis/new_file.c
X	source	remove	1	aegis/new_file.h
X	source	modify	2	aux/new.2.1.so
X	source	modify	2	man1/aenf.1
X	test	create	1	test/00/t0018a.sh
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Wed Aug 18	pmiller
X			14:09:50 1993
X	develop_begin	Wed Aug 18	pmiller Elapsed time: 0.748
X			14:10:14 1993		days.
X	develop_end	Thu Aug 19	pmiller Elapsed time: 0.631
X			12:16:43 1993		days.
X	review_pass	Thu Aug 19	pmiller
X			17:00:42 1993
X	integrate_begin Thu Aug 19	pmiller Elapsed time: 0.729
X			17:02:07 1993		days.
X	integrate_pass	Thu Aug 19	pmiller
X			22:30:18 1993
X
X
X
XProject "aegis.2.1", Change 3					 Page 1
XChange Details				       Fri Aug 20 22:56:41 1993
X
XNAME
X	Project "aegis.2.1", Delta 2, Change 3.
X
XSUMMARY
X	bug in list
X
XDESCRIPTION
X	terse flavour of cf anf pf not meant to mention nonexistent
X	files
X
X	This change is exempt from testing against the development
X	directory.  This change is exempt from testing against the
X	baseline.
X
XCAUSE
X	This change was caused by internal_bug.
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	2	aegis/list.c
X	source	create	1	aux/new.2.1.so
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Wed Aug 18	pmiller
X			16:01:12 1993
X	develop_begin	Wed Aug 18	pmiller Elapsed time: 0.082
X			16:01:19 1993		days.
X	develop_end	Wed Aug 18	pmiller
X			16:38:05 1993
X	review_pass	Wed Aug 18	pmiller
X			16:38:15 1993
X	integrate_begin Wed Aug 18	pmiller Elapsed time: 0.674
X			16:39:35 1993		days.
X	integrate_pass	Wed Aug 18	pmiller
X			21:42:46 1993
X
X
X
XProject "aegis.2.1", Change 4					 Page 1
XChange Details				       Fri Aug 20 22:56:42 1993
X
XNAME
X	Project "aegis.2.1", Delta 5, Change 4.
X
XSUMMARY
X	keep old change logs
X
XDESCRIPTION
X	keep old change logs
X
X	This change is exempt from testing against the development
X	directory.  This change is exempt from testing against the
X	baseline.
X
XCAUSE
X	This change was caused by internal_improvement.
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	build	create	1	BUILDING
X	build	create	1	CHANGES
X	build	create	1	MANIFEST
X	build	create	1	Makefile
X	build	create	1	README
X	source	modify	2	aegis/aede.c
X	source	create	1	aux/CHANGES.1.0
X	source	create	1	aux/CHANGES.1.1
X	source	create	1	aux/CHANGES.1.2
X	source	create	1	aux/CHANGES.1.3
X	source	create	1	aux/CHANGES.1.4
X	source	create	1	aux/CHANGES.2.0
X	source	modify	2	aux/Howto.cook
X	build	create	1	aux/new.so
X	build	create	1	common/patchlevel.h
X	build	create	1	doc/version.so
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Wed Aug 18	pmiller
X			22:21:55 1993
X	develop_begin	Wed Aug 18	pmiller Elapsed time: 1.099
X			22:22:02 1993		days.
X	develop_end	Thu Aug 19	pmiller
X			23:06:41 1993
X	review_pass	Thu Aug 19	pmiller
X			23:06:51 1993
X	integrate_begin Thu Aug 19	pmiller
X			23:09:06 1993
X	integrate_fail	Thu Aug 19	pmiller need to bang on
X			23:16:52 1993		Howto.cook
X						Elapsed time: 0.038
X						days.
X	develop_end	Thu Aug 19	pmiller
X			23:34:03 1993
X	review_pass	Thu Aug 19	pmiller
X			23:34:14 1993
X
X
X
XProject "aegis.2.1", Change 4					 Page 2
XChange Details				       Fri Aug 20 22:56:42 1993
X
X	What		When		Who	Comment
X	------		------		-----	---------
X	integrate_begin Thu Aug 19	pmiller Elapsed time: 0.000
X			23:36:29 1993		days.
X	integrate_pass	Fri Aug 20	pmiller
X			08:45:17 1993
X
X
X
XProject "aegis.2.1", Change 5					 Page 1
XChange Details				       Fri Aug 20 22:56:43 1993
X
XNAME
X	Project "aegis.2.1", Delta 7, Change 5.
X
XSUMMARY
X	rename some source files
X
XDESCRIPTION
X	Rename some of the source files to be more intuitavely named.
X
X	This change is exempt from testing against the development
X	directory.  This change is exempt from testing against the
X	baseline.
X
XCAUSE
X	This change was caused by internal_improvement.
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	build	modify	2	BUILDING
X	build	modify	2	CHANGES
X	build	modify	2	MANIFEST
X	build	modify	2	Makefile
X	build	modify	2	README
X	source	remove	1	aegis/administ.c
X	source	remove	1	aegis/administ.h
X	source	create	1	aegis/aeb.c
X				Moved from aegis/build.c
X	source	create	1	aegis/aeb.h
X				Moved from aegis/build.h
X	source	create	1	aegis/aeca.c
X				Moved from aegis/cattr_ed.c
X	source	create	1	aegis/aeca.h
X				Moved from aegis/cattr_ed.h
X	source	create	1	aegis/aecd.c
X				Moved from aegis/chdir.c
X	source	create	1	aegis/aecd.h
X				Moved from aegis/chdir.h
X	source	modify	2	aegis/aecp.c
X	source	modify	2	aegis/aecpu.c
X	source	modify	2	aegis/aed.c
X	source	modify	2	aegis/aedb.c
X	source	modify	2	aegis/aedbu.c
X	source	modify	3	aegis/aede.c
X	source	modify	2	aegis/aedeu.c
X	source	modify	2	aegis/aeib.c
X	source	modify	2	aegis/aeibu.c
X	source	modify	2	aegis/aeif.c
X	source	modify	2	aegis/aeip.c
X	source	create	1	aegis/ael.c
X				Moved from aegis/list.c
X	source	create	1	aegis/ael.h
X				Moved from aegis/list.h
X	source	modify	2	aegis/aemv.c
X	source	create	1	aegis/aena.c
X				Moved from aegis/administ.c
X	source	create	1	aegis/aena.h
X
X
X
XProject "aegis.2.1", Change 5					 Page 2
XChange Details				       Fri Aug 20 22:56:43 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X				Moved from aegis/administ.h
X	source	create	1	aegis/aenc.c
X				Moved from aegis/new_chan.c
X	source	create	1	aegis/aenc.h
X				Moved from aegis/new_chan.h
X	source	create	1	aegis/aencu.c
X				Moved from aegis/new_chan.c
X	source	create	1	aegis/aencu.h
X				Moved from aegis/new_chan.h
X	source	create	1	aegis/aend.c
X				Moved from aegis/develop1.c
X	source	create	1	aegis/aend.h
X				Moved from aegis/develop1.h
X	source	modify	2	aegis/aenf.c
X	source	modify	2	aegis/aenfu.c
X	source	create	1	aegis/aeni.c
X				Moved from aegis/integra1.c
X	source	create	1	aegis/aeni.h
X				Moved from aegis/integra1.h
X	source	create	1	aegis/aenpr.c
X				Moved from aegis/new_proj.c
X	source	create	1	aegis/aenpr.h
X				Moved from aegis/new_proj.h
X	source	create	1	aegis/aenrls.c
X				Moved from aegis/new_rele.c
X	source	create	1	aegis/aenrls.h
X				Moved from aegis/new_rele.h
X	source	create	1	aegis/aenrv.c
X				Moved from aegis/reviewer.c
X	source	create	1	aegis/aenrv.h
X				Moved from aegis/reviewer.h
X	source	create	1	aegis/aent.c
X				Moved from aegis/new_test.c
X	source	create	1	aegis/aent.h
X				Moved from aegis/new_test.h
X	source	create	1	aegis/aentu.c
X				Moved from aegis/new_test.c
X	source	create	1	aegis/aentu.h
X				Moved from aegis/new_test.h
X	source	create	1	aegis/aepa.c
X				Moved from aegis/pattr_ed.c
X	source	create	1	aegis/aepa.h
X				Moved from aegis/pattr_ed.h
X	source	create	1	aegis/aera.c
X				Moved from aegis/administ.c
X	source	create	1	aegis/aera.h
X				Moved from aegis/administ.h
X	source	create	1	aegis/aerd.c
X				Moved from aegis/develop1.c
X	source	create	1	aegis/aerd.h
X				Moved from aegis/develop1.h
X	source	create	1	aegis/aerf.c
X				Moved from aegis/review.c
X	source	create	1	aegis/aerf.h
X				Moved from aegis/review.h
X
X
X
XProject "aegis.2.1", Change 5					 Page 3
XChange Details				       Fri Aug 20 22:56:43 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	aegis/aeri.c
X				Moved from aegis/integra1.c
X	source	create	1	aegis/aeri.h
X				Moved from aegis/integra1.h
X	source	create	1	aegis/aerm.c
X				Moved from aegis/rem_file.c
X	source	create	1	aegis/aerm.h
X				Moved from aegis/rem_file.h
X	source	create	1	aegis/aermpr.c
X				Moved from aegis/rem_proj.c
X	source	create	1	aegis/aermpr.h
X				Moved from aegis/rem_proj.h
X	source	create	1	aegis/aermu.c
X				Moved from aegis/rem_file.c
X	source	create	1	aegis/aermu.h
X				Moved from aegis/rem_file.h
X	source	create	1	aegis/aerp.c
X				Moved from aegis/review.c
X	source	create	1	aegis/aerp.h
X				Moved from aegis/review.h
X	source	create	1	aegis/aerpu.c
X				Moved from aegis/review.c
X	source	create	1	aegis/aerpu.h
X				Moved from aegis/review.h
X	source	create	1	aegis/aerrv.c
X				Moved from aegis/reviewer.c
X	source	create	1	aegis/aerrv.h
X				Moved from aegis/reviewer.h
X	source	create	1	aegis/aet.c
X				Moved from aegis/test.c
X	source	create	1	aegis/aet.h
X				Moved from aegis/test.h
X	source	remove	1	aegis/build.c
X	source	remove	1	aegis/build.h
X	source	remove	1	aegis/cattr_ed.c
X	source	remove	1	aegis/cattr_ed.h
X	source	remove	1	aegis/chdir.c
X	source	remove	1	aegis/chdir.h
X	source	remove	1	aegis/develop1.c
X	source	remove	1	aegis/develop1.h
X	source	remove	1	aegis/integra1.c
X	source	remove	1	aegis/integra1.h
X	source	remove	2	aegis/list.c
X	source	remove	1	aegis/list.h
X	source	modify	3	aegis/main.c
X	source	remove	1	aegis/new_chan.c
X	source	remove	1	aegis/new_chan.h
X	source	remove	1	aegis/new_proj.c
X	source	remove	1	aegis/new_proj.h
X	source	remove	1	aegis/new_rele.c
X	source	remove	1	aegis/new_rele.h
X	source	remove	1	aegis/new_test.c
X	source	remove	1	aegis/new_test.h
X	source	remove	1	aegis/pattr_ed.c
X	source	remove	1	aegis/pattr_ed.h
X
X
X
XProject "aegis.2.1", Change 5					 Page 4
XChange Details				       Fri Aug 20 22:56:43 1993
X
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	remove	1	aegis/rem_file.c
X	source	remove	1	aegis/rem_file.h
X	source	remove	1	aegis/rem_proj.c
X	source	remove	1	aegis/rem_proj.h
X	source	remove	1	aegis/review.c
X	source	remove	1	aegis/review.h
X	source	remove	1	aegis/reviewer.c
X	source	remove	1	aegis/reviewer.h
X	source	modify	2	aegis/sub.c
X	source	remove	1	aegis/test.c
X	source	remove	1	aegis/test.h
X	build	modify	2	aux/new.so
X	source	modify	2	aux/patches.sh
X	build	modify	2	common/patchlevel.h
X	build	modify	2	doc/version.so
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Fri Aug 20	pmiller
X			08:49:47 1993
X	develop_begin	Fri Aug 20	pmiller Elapsed time: 0.685
X			08:49:53 1993		days.
X	develop_end	Fri Aug 20	pmiller
X			13:58:14 1993
X	review_pass	Fri Aug 20	pmiller
X			13:59:57 1993
X	integrate_begin Fri Aug 20	pmiller Elapsed time: 0.058
X			14:01:40 1993		days.
X	integrate_fail	Fri Aug 20	pmiller need to copy with
X			14:27:57 1993		output case for build-
X						type files
X						Elapsed time: 0.037
X						days.
X	develop_end	Fri Aug 20	pmiller
X			14:44:33 1993
X	review_pass	Fri Aug 20	pmiller
X			14:47:14 1993
X	integrate_begin Fri Aug 20	pmiller Elapsed time: 0.304
X			14:48:40 1993		days.
X	integrate_pass	Fri Aug 20	pmiller
X			17:05:37 1993
X
X
X
XProject "aegis.2.1", Change 6					 Page 1
XChange Details				       Fri Aug 20 22:56:44 1993
X
XNAME
X	Project "aegis.2.1", Delta 8, Change 6.
X
XSUMMARY
X	fix version in readme
X
XDESCRIPTION
X	The README file has the aegis version number in it, automat
X	this.
X
X	This change is exempt from testing against the development
X	directory.  This change is exempt from testing against the
X	baseline.
X
XCAUSE
X	This change was caused by internal_bug.
X
XSTATE
X	This change is in 'being_integrated' state.
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	2	aegis/aeib.c
X	source	modify	2	aux/Howto.cook
X	source	modify	1	aux/README.man
X	source	modify	1	doc/c1.0.so
X	source	modify	1	man1/z_cr.so
X	source	modify	1	man5/z_cr.so
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Fri Aug 20	pmiller
X			21:25:12 1993
X	develop_begin	Fri Aug 20	pmiller Elapsed time: 0.134
X			21:25:17 1993		days.
X	develop_end	Fri Aug 20	pmiller
X			22:25:27 1993
X	develop_end_	Fri Aug 20	pmiller Elapsed time: 0.040
X	undo		22:26:16 1993		days.
X	develop_end	Fri Aug 20	pmiller
X			22:44:13 1993
X	review_pass	Fri Aug 20	pmiller
X			22:46:45 1993
X	integrate_begin Fri Aug 20	pmiller
X			22:49:03 1993
END_OF_FILE
if test 26959 -ne `wc -c <'CHANGES'`; then
    echo shar: \"'CHANGES'\" unpacked with wrong size!
fi
# end of 'CHANGES'
fi
if test -f 'aegis/aed.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'aegis/aed.c'\"
else
echo shar: Extracting \"'aegis/aed.c'\" \(26542 characters\)
sed "s/^X//" >'aegis/aed.c' <<'END_OF_FILE'
X/*
X *	aegis - project change supervisor
X *	Copyright (C) 1991, 1992, 1993 Peter Miller.
X *	All rights reserved.
X *
X *	This program is free software; you can redistribute it and/or modify
X *	it under the terms of the GNU General Public License as published by
X *	the Free Software Foundation; either version 2 of the License, or
X *	(at your option) any later version.
X *
X *	This program is distributed in the hope that it will be useful,
X *	but WITHOUT ANY WARRANTY; without even the implied warranty of
X *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X *	GNU General Public License for more details.
X *
X *	You should have received a copy of the GNU General Public License
X *	along with this program; if not, write to the Free Software
X *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: difference a change
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <time.h>
X#include <unistd.h>
X
X#include <aed.h>
X#include <ael.h>
X#include <arglex2.h>
X#include <change.h>
X#include <col.h>
X#include <commit.h>
X#include <error.h>
X#include <help.h>
X#include <lock.h>
X#include <log.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <sub.h>
X#include <trace.h>
X#include <undo.h>
X#include <user.h>
X#include <word.h>
X
X
Xstatic void difference_usage _((void));
X
Xstatic void
Xdifference_usage()
X{
X	char		*progname;
X
X	progname = option_progname_get();
X	fprintf(stderr, "usage: %s -DIFFerence [ <option>... ][ <filename>... ]\n", progname);
X	fprintf(stderr, "       %s -DIFFerence -List [ <option>... ]\n", progname);
X	fprintf(stderr, "       %s -DIFFerence -Help\n", progname);
X	quit(1);
X}
X
X
Xstatic void difference_help _((void));
X
Xstatic void
Xdifference_help()
X{
X	static char *text[] =
X	{
X"NAME",
X"	%s -DIFFerence - find differences between development",
X"	directory and baseline",
X"",
X"SYNOPSIS",
X"	%s -DIFFerence [ <option>... ][ <filename>... ]",
X"	%s -DIFFerence -List [ <option>... ]",
X"	%s -DIFFerence -Help",
X"",
X"DESCRIPTION",
X"	The %s -DIFFerence command is used to find differences",
X"	between the development directory and the baseline.  The",
X"	differences will be in files with a \",D\" suffix.  The",
X"	command used to perform the differences is in the project",
X"	config file (see aepconf(5) for more information).",
X"",
X"	If no files are named on the command line, all files in",
X"	the change will be differenced.",
X"",
X"	The %s program will attempt to determine the project",
X"	file names from the file names given on the command line.",
X"	All file names are stored within %s projects as",
X"	relative to the root of the baseline directory tree.  The",
X"	development directory and the integration directory are",
X"	shadows of this baseline directory, and so these relative",
X"	names apply here, too.  Files named on the command line",
X"	are first converted to absolute paths if necessary.  They",
X"	are then compared with the baseline path, the development",
X"	directory path, and the integration directory path, to",
X"	determine a baseline-relative name.  It is an error if",
X"	the file named is outside one of these directory trees.",
X"",
X"CONFLICT RESOLUTION",
X"	If the version of a file in the change is not the same as",
X"	the verion of the file in the baseline, it is out-of-",
X"	date; some other change has altered the file while this",
X"	change was being developed.",
X"",
X"	When a difference is requested for an out-of-date file, a",
X"	merge is performed between the common ancestor, the",
X"	verion in the baseline, and the version in the",
X"	development directory.  The command used to perform the",
X"	merge is in the project config file (see aepconf(5) for",
X"	more information).",
X"",
X"	After the merge is performed the version of the file will",
X"	be changed to be the current version, and a new build",
X"	will be required.",
X"",
X"	The difference output in the ,D files contains the result",
X"	of the merge.  You should edit them, to make sure the",
X"	automatic merge has produced sensible results, and then",
X"	rename them to be the corresponding source file.",
X"",
X"	This merge process works most of the time.  Usually two",
X"	changes to two logically separate areas of functionality",
X"	will alter two logically separate parts of any files they",
X"	may have in common.  There are pathological cases where",
X"	this merge process is spectacularly useless, but these",
X"	are surprizingly rare in practice.",
X"",
X"OPTIONS",
X"	The following options are understood:",
X"",
X"	-ANticipate <change-number>",
X"		This option is used to nominate a source for the",
X"		reference files, rather than the baseline.  This",
X"		may be used to synchronize with a change without",
X"		having to wait for it to arrive in the baseline.",
X"		It is an error if the anticipated change is not",
X"		in one of the 'being reviewed' or 'awaiting",
X"		integration' or 'being integrated' states.  A",
X"		merge is always performed, because the",
X"		anticipated change is \"about\" to make any common",
X"		file out-of-date.  You will still have to perform",
X"		a \"real\" merge later.",
X"",
X"	-Change <number>",
X"		This option may be used to specify a particular",
X"		change within a project.  When no -Change option is",
X"		specified, the AEGIS_CHANGE environment variable is",
X"		consulted.  If that does not exist, the user's",
X"		$HOME/.aegisrc file is examined for a default change",
X"		field (see aeuconf(5) for more information).  If",
X"		that does not exist, when the user is only working",
X"		on one change within a project, that is the default",
X"		change number.  Otherwise, it is an error.",
X"",
X"	-Help",
X"		This option may be used to obtain more",
X"		information about how to use the %s program.",
X"",
X"	-List",
X"		This option may be used to obtain a list of",
X"		suitable subjects for this command.  The list may",
X"		be more general than expected.",
X"",
X"	-Project <name>",
X"		This option may be used to select the project of",
X"		interest.  When no -Project option is specified, the",
X"		AEGIS_PROJECT environment variable is consulted.  If",
X"		that does not exist, the user's $HOME/.aegisrc file",
X"		is examined for a default project field (see",
X"		aeuconf(5) for more information).  If that does not",
X"		exist, when the user is only working on changes",
X"		within a single project, the project name defaults",
X"		to that project.  Otherwise, it is an error.",
X"",
X"	-TERse",
X"		This option may be used to cause listings to",
X"		produce the bare minimum of information.  It is",
X"		usually useful for shell scripts.",
X"",
X"	-Verbose",
X"		This option may be used to cause %s to produce",
X"		more output.  By default %s only produces",
X"		output on errors.  When used with the -List",
X"		option this option causes column headings to be",
X"		added.",
X"",
X"	All options may be abbreviated; the abbreviation is",
X"	documented as the upper case letters, all lower case",
X"	letters and underscores (_) are optional.  You must use",
X"	consecutive sequences of optional letters.",
X"",
X"	All options are case insensitive, you may type them in",
X"	upper case or lower case or a combination of both, case",
X"	is not important.",
X"",
X"	For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X"	are all interpreted to mean the -Project option.  The",
X"	argument \"-prj\" will not be understood, because",
X"	consecutive optional characters were not supplied.",
X"",
X"	Options and other command line arguments may be mixed",
X"	arbitrarily on the command line, after the function",
X"	selectors.",
X"",
X"	The GNU long option names are understood.  Since all",
X"	option names for aegis are long, this means ignoring the",
X"	extra leading '-'.  The \"--option=value\" convention is",
X"	also understood.",
X"",
X"RECOMMENDED ALIAS",
X"	The recommended alias for this command is",
X"	csh%%	alias aed '%s -diff \\!* -v'",
X"	sh$	aed(){%s -diff $* -v}",
X"",
X"ERRORS",
X"	It is an error if the change is not in the 'being",
X"	developed' state.",
X"",
X"EXIT STATUS",
X"	The %s command will exit with a status of 1 on any",
X"	error.	The %s command will only exit with a status of",
X"	0 if there are no errors.",
X"",
X"COPYRIGHT",
X"	%C",
X"",
X"AUTHOR",
X"	%A",
X	};
X
X	help(text, SIZEOF(text), difference_usage);
X}
X
X
Xstatic void difference_list _((void));
X
Xstatic void
Xdifference_list()
X{
X	string_ty	*project_name;
X	long		change_number;
X
X	trace(("difference_list()\n{\n"/*}*/));
X	project_name = 0;
X	change_number = 0;
X	arglex();
X	while (arglex_token != arglex_token_eoln)
X	{
X		switch (arglex_token)
X		{
X		default:
X			generic_argument(difference_usage);
X			continue;
X
X		case arglex_token_change:
X			if (arglex() != arglex_token_number)
X				difference_usage();
X			/* fall through... */
X
X		case arglex_token_number:
X			if (change_number)
X				fatal("duplicate -Change option");
X			change_number = arglex_value.alv_number;
X			if (change_number < 1)
X				fatal("change %ld out of range", change_number);
X			break;
X
X		case arglex_token_project:
X			if (arglex() != arglex_token_string)
X				difference_usage();
X			if (project_name)
X				fatal("duplicate -Project option");
X			project_name = str_from_c(arglex_value.alv_string);
X			break;
X		}
X		arglex();
X	}
X
X	list_change_files(project_name, change_number);
X	if (project_name)
X		str_free(project_name);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void anticipate _((string_ty *, long, long, int, wlist *));
X
Xstatic void
Xanticipate(project_name, change_number, acn, nolog, wl)
X	string_ty	*project_name;
X	long		change_number;
X	long		acn;
X	int		nolog;
X	wlist		*wl;
X{
X	string_ty	*dd1;
X	string_ty	*dd2;
X	string_ty	*bl;
X	pconf		pconf_data;
X	cstate		cstate_data;
X	cstate		cstate2_data;
X	size_t		j;
X	project_ty	*pp;
X	change_ty	*cp;
X	user_ty		*up;
X	change_ty	*acp;
X
X	trace(("anticipate()\n{\n"/*}*/));
X
X	/*
X	 * locate project data
X	 */
X	if (!project_name)
X		project_name = user_default_project();
X	pp = project_alloc(project_name);
X	str_free(project_name);
X	project_bind_existing(pp);
X
X	/*
X	 * locate user data
X	 */
X	up = user_executing(pp);
X
X	/*
X	 * locate change data
X	 */
X	if (!change_number)
X		change_number = user_default_change(up);
X	cp = change_alloc(pp, change_number);
X	change_bind_existing(cp);
X	acp = change_alloc(pp, acn);
X	change_bind_existing(acp);
X
X	/*
X	 * It is an error if the change is not in the in-development state.
X	 * It is an error if the change is not assigned to the current user.
X	 * It is an error if the anticipated change is not awaiting
X	 * integration or being integrated.
X	 */
X	cstate_data = change_cstate_get(cp);
X	cstate2_data = change_cstate_get(acp);
X	if (cstate_data->state != cstate_state_being_developed)
X		change_fatal(cp, "not in 'being_developed' state");
X	if
X	(
X		cstate2_data->state < cstate_state_being_reviewed
X	||
X		cstate2_data->state > cstate_state_being_integrated
X	)
X		change_fatal(acp, "not in an appropriate state");
X	if (!str_equal(change_developer_name(cp), user_name(up)))
X	{
X		change_fatal
X		(
X			cp,
X			"user \"%S\" is not the developer",
X			user_name(up)
X		);
X	}
X
X	/*
X	 * if no files were named on the command line,
X	 * then diff every file the two changes have in common.
X	 * Ignore all but the most obvious of combinations.
X	 */
X	dd1 = change_development_directory_get(cp, 1);
X	dd2 = change_development_directory_get(acp, 1);
X	bl = project_baseline_path_get(pp, 1);
X	if (!wl->wl_nwords)
X	{
X		assert(cstate_data->src);
X		for (j = 0; j < cstate_data->src->length; ++j)
X		{
X			cstate_src	src1_data;
X			cstate_src	src2_data;
X
X			src1_data = cstate_data->src->list[j];
X			if (src1_data->action != file_action_modify)
X				continue;
X			src2_data = change_src_find(acp, src1_data->file_name);
X			if (!src2_data)
X				continue;
X			if (src2_data->action != file_action_modify)
X				continue;
X			wl_append(wl, src1_data->file_name);
X		}
X		if (!wl->wl_nwords)
X			change_fatal(cp, "no suitable files in common");
X	}
X	else
X	{
X		/*
X		 * resolve the path of each file
X		 * 1.	the absolute path of the file name is obtained
X		 * 2.	if the file is inside the development directory, ok
X		 * 3.	if the file is inside the baseline, ok
X		 * 4.	if neither, error
X		 */
X		for (j = 0; j < wl->wl_nwords; ++j)
X		{
X			string_ty	*s1;
X			string_ty	*s2;
X
X			s1 = wl->wl_word[j];
X			assert(s1->str_text[0] == '/');
X			s2 = os_below_dir(dd1, s1);
X			if (!s2)
X				s2 = os_below_dir(dd2, s1);
X			if (!s2)
X				s2 = os_below_dir(bl, s1);
X			if (!s2)
X				change_fatal(cp, "path \"%S\" unrelated", s1);
X			str_free(s1);
X			wl->wl_word[j] = s2;
X		}
X
X		/*
X		 * confirm that each file is in both changes
X		 * and is sensable to compare
X		 */
X		for (j = 0; j < wl->wl_nwords; ++j)
X		{
X			cstate_src	src1_data;
X			cstate_src	src2_data;
X			string_ty	*s1;
X
X			s1 = wl->wl_word[j];
X			src1_data = change_src_find(cp, s1);
X			if (!src1_data)
X			{
X				change_fatal
X				(
X					cp,
X				       "file \"%S\" is not part of this change",
X					s1
X				);
X			}
X			if (src1_data->action != file_action_modify)
X			{
X				change_fatal
X				(
X					cp,
X		      "file \"%S\" is not suitable for anticipating difference",
X					s1
X				);
X			}
X			src2_data = change_src_find(acp, s1);
X			if (!src2_data)
X			{
X				change_fatal
X				(
X					acp,
X				"file \"%S\" is not part of anticipated change",
X					s1
X				);
X			}
X			if (src2_data->action != file_action_modify)
X			{
X				change_fatal
X				(
X					acp,
X		      "file \"%S\" is not suitable for anticipating difference",
X					s1
X				);
X			}
X		}
X	}
X
X	/*
X	 * diff each file
X	 */
X	if (!nolog)
X		log_open(change_logfile_get(cp), up);
X	pconf_data = change_pconf_get(cp);
X	for (j = 0; j < wl->wl_nwords; ++j)
X	{
X		cstate_src	src1_data;
X		cstate_src	src2_data;
X		string_ty	*original;
X		string_ty	*most_recent;
X		string_ty	*input;
X		string_ty	*output;
X		int		original_unlink;
X		time_t		when;
X		string_ty	*s1;
X
X		s1 = wl->wl_word[j];
X		src1_data = change_src_find(cp, s1);
X		assert(src1_data);
X		src2_data = change_src_find(cp, s1);
X		assert(src2_data);
X
X		most_recent = str_format("%S/%S", dd2, s1);
X		input = str_format("%S/%S", dd1, s1);
X		output = str_format("%S,D", input);
X		if (str_equal(src1_data->edit_number, src2_data->edit_number))
X		{
X			/*
X			 * if they are both based on the same version,
X			 * common ancestor is the baseline
X			 */
X			original = str_format("%S/%S", bl, s1);
X			original_unlink = 0;
X		}
X		else
X		{
X			/*
X			 * If they are based on different versions,
X			 * need to get the original out of history
X			 */
X			original = os_edit_filename();
X			original_unlink = 1;
X			user_become(up);
X			undo_unlink_errok(original);
X			user_become_undo();
X
X			change_run_history_get_command
X			(
X				cp,
X				s1,
X				src1_data->edit_number,
X				original,
X				up
X			);
X		}
X
X		/*
X		 * use the diff3-command
X		 */
X		change_run_diff3_command
X		(
X			cp,
X			up,
X			original,
X			most_recent,
X			input,
X			output
X		);
X
X		/*
X		 * remove the temporary file
X		 */
X		if (original_unlink)
X		{
X			user_become(up);
X			os_unlink(original);
X			user_become_undo();
X		}
X
X		/*
X		 * make sure the diff is out-of-date,
X		 * to force a non-anticipate diff later
X		 */
X		user_become(up);
X		when = os_mtime(output);
X		os_mtime_set(input, when + 1);
X		user_become_undo();
X
X		str_free(original);
X		str_free(most_recent);
X		str_free(input);
X		str_free(output);
X	}
X
X	/*
X	 * verbose success message
X	 */
X	change_verbose(cp, "anticipated difference complete");
X	change_free(cp);
X	change_free(acp);
X	project_free(pp);
X	user_free(up);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void difference_main _((void));
X
Xstatic void
Xdifference_main()
X{
X	string_ty	*dd;
X	string_ty	*bl;
X	wlist		wl;
X	string_ty	*s1 = 0;
X	string_ty	*s2;
X	wlist		need_new_build;
X	pstate		pstate_data;
X	pconf		pconf_data;
X	cstate		cstate_data;
X	size_t		j;
X	string_ty	*project_name;
X	project_ty	*pp;
X	long		change_number;
X	change_ty	*cp;
X	int		nolog;
X	user_ty		*up;
X	long		acn;
X
X	trace(("difference_main()\n{\n"/*}*/));
X	wl_zero(&wl);
X	wl_zero(&need_new_build);
X	project_name = 0;
X	change_number = 0;
X	nolog = 0;
X	acn = 0;
X	while (arglex_token != arglex_token_eoln)
X	{
X		switch (arglex_token)
X		{
X		default:
X			generic_argument(difference_usage);
X			continue;
X
X		case arglex_token_string:
X			s1 = str_from_c(arglex_value.alv_string);
X			os_become_orig();
X			s2 = os_pathname(s1, 1);
X			os_become_undo();
X			if (wl_member(&wl, s2))
X			{
X				fatal
X				(
X					"file \"%s\" named more than once",
X					arglex_value.alv_string
X				);
X			}
X			wl_append(&wl, s2);
X			str_free(s1);
X			str_free(s2);
X			break;
X
X		case arglex_token_change:
X			if (arglex() != arglex_token_number)
X				difference_usage();
X			/* fall through... */
X
X		case arglex_token_number:
X			if (change_number)
X				fatal("duplicate -Change option");
X			change_number = arglex_value.alv_number;
X			if (change_number < 1)
X				fatal("change %ld out of range", change_number);
X			break;
X
X		case arglex_token_project:
X			if (arglex() != arglex_token_string)
X				difference_usage();
X			if (project_name)
X				fatal("duplicate -Project option");
X			project_name = str_from_c(arglex_value.alv_string);
X			break;
X
X		case arglex_token_nolog:
X			if (nolog)
X			{
X				duplicate:
X				fatal
X				(
X					"duplicate %s option",
X					arglex_value.alv_string
X				);
X			}
X			nolog = 1;
X			break;
X
X		case arglex_token_anticipate:
X			if (acn)
X				goto duplicate;
X			if (arglex() != arglex_token_number)
X			{
X				error
X				(
X		    "the -ANticipate option must be followed by a change number"
X				);
X				difference_usage();
X			}
X			acn = arglex_value.alv_number;
X			if (acn < 1)
X			{
X				fatal
X				(
X				    "anticiptae change number %ld out of range",
X					acn
X				);
X			}
X			break;
X		}
X		arglex();
X	}
X
X	if (acn)
X	{
X		anticipate(project_name, change_number, acn, nolog, &wl);
X		trace((/*{*/"}\n"));
X		return;
X	}
X
X	/*
X	 * locate project data
X	 */
X	if (!project_name)
X		project_name = user_default_project();
X	pp = project_alloc(project_name);
X	str_free(project_name);
X	project_bind_existing(pp);
X
X	/*
X	 * locate user data
X	 */
X	up = user_executing(pp);
X
X	/*
X	 * locate change data
X	 */
X	if (!change_number)
X		change_number = user_default_change(up);
X	cp = change_alloc(pp, change_number);
X	change_bind_existing(cp);
X
X	/*
X	 * lock on the appropriate row of the change table.
X	 */
X	change_cstate_lock_prepare(cp);
X	lock_take();
X
X	/*
X	 * It is an error if the change is not in the in-development state.
X	 * It is an error if the change is not assigned to the current user.
X	 */
X	pstate_data = project_pstate_get(pp);
X	cstate_data = change_cstate_get(cp);
X	if (cstate_data->state != cstate_state_being_developed)
X		change_fatal(cp, "not in 'being_developed' state");
X	if (!str_equal(change_developer_name(cp), user_name(up)))
X	{
X		change_fatal
X		(
X			cp,
X			"user \"%S\" is not the developer",
X			user_name(up)
X		);
X	}
X
X	/*
X	 * if no files were named on the command line,
X	 * then diff every file in the change.
X	 */
X	if (!wl.wl_nwords)
X	{
X		assert(cstate_data->src);
X		if (!cstate_data->src->length)
X			change_fatal(cp, "no files");
X		for (j = 0; j < cstate_data->src->length; ++j)
X		{
X			cstate_src	src_data;
X
X			src_data = cstate_data->src->list[j];
X			wl_append(&wl, src_data->file_name);
X		}
X	}
X	else
X	{
X		/*
X		 * resolve the path of each file
X		 * 1.	the absolute path of the file name is obtained
X		 * 2.	if the file is inside the development directory, ok
X		 * 3.	if the file is inside the baseline, ok
X		 * 4.	if neither, error
X		 */
X		for (j = 0; j < wl.wl_nwords; ++j)
X		{
X			s1 = wl.wl_word[j];
X			assert(s1->str_text[0] == '/');
X			s2 = os_below_dir(change_development_directory_get(cp, 1), s1);
X			if (!s2)
X				s2 = os_below_dir(project_baseline_path_get(pp, 1), s1);
X			if (!s2)
X				change_fatal(cp, "path \"%S\" unrelated", s1);
X			str_free(s1);
X			wl.wl_word[j] = s2;
X		}
X
X		/*
X		 * confirm that each file is in the change
X		 */
X		for (j = 0; j < wl.wl_nwords; ++j)
X		{
X			s1 = wl.wl_word[j];
X			if (!change_src_find(cp, s1))
X			{
X				change_fatal
X				(
X					cp,
X				       "file \"%S\" is not part of this change",
X					s1
X				);
X			}
X		}
X	}
X
X	/*
X	 * diff each file
X	 */
X	if (!nolog)
X		log_open(change_logfile_get(cp), up);
X	pconf_data = change_pconf_get(cp);
X	dd = change_development_directory_get(cp, 1);
X	bl = project_baseline_path_get(pp, 1);
X	for (j = 0; j < wl.wl_nwords; ++j)
X	{
X		cstate_src	src1_data;
X		pstate_src	src2_data;
X		string_ty	*original;
X		string_ty	*input;
X		string_ty	*curfile;
X		string_ty	*outname;
X		int		ignore;
X
X		/*
X		 * find the relevant change src data
X		 */
X		s1 = wl.wl_word[j];
X		src1_data = change_src_find(cp, s1);
X		assert(src1_data);
X
X		/*
X		 * generated files are not differenced
X		 */
X		if (src1_data->usage == file_usage_build)
X			continue;
X
X		/*
X		 * build various paths
X		 */
X		curfile = str_format("%S/%S", dd, s1);
X		trace_string(curfile->str_text);
X		outname = str_format("%S,D", curfile);
X		trace_string(outname->str_text);
X
X		switch (src1_data->action)
X		{
X		case file_action_create:
X			/*
X			 * check if someone created it ahead of you
X			 */
X			src2_data = project_src_find(pp, s1);
X			if (src2_data)
X			{
X				change_fatal
X				(
X					cp,
X					"file \"%S\" already in baseline",
X					s1
X				);
X			}
X
X			/*
X			 * do nothing if we can
X			 */
X			user_become(up);
X			ignore =
X				(
X					src1_data->diff_time
X				&&
X					src1_data->diff_file_time
X				&&
X					os_exists(curfile)
X				&&
X					src1_data->diff_time == os_mtime(curfile)
X				&&
X					os_exists(outname)
X				&&
X					src1_data->diff_file_time == os_mtime(outname)
X				);
X			user_become_undo();
X			if (ignore)
X				break;
X
X			/*
X			 * difference the file
X			 * from nothing
X			 */
X			if
X			(
X				src1_data->move
X			&&
X				project_src_find(pp, src1_data->move)
X			)
X			{
X				original =
X					str_format
X					(
X						"%S/%S",
X						bl,
X						src1_data->move
X					);
X			}
X			else
X				original = str_from_c("/dev/null");
X			change_run_diff_command
X			(
X				cp,
X				up,
X				original,
X				curfile,
X				outname
X			);
X			str_free(original);
X			user_become(up);
X			src1_data->diff_time = os_mtime(curfile);
X			src1_data->diff_file_time = os_mtime(outname);
X			user_become_undo();
X			break;
X
X		case file_action_remove:
X			/*
X			 * check if someone deleted it ahead of you
X			 */
X			src2_data = project_src_find(pp, s1);
X			if (!src2_data)
X			{
X				change_fatal
X				(
X					cp,
X					"file \"%S\" no longer in baseline",
X					s1
X				);
X			}
X
X			/*
X			 * do nothing if we can
X			 */
X			user_become(up);
X			ignore =
X				(
X					src1_data->diff_file_time
X				&&
X					os_exists(outname)
X				&&
X					src1_data->diff_file_time == os_mtime(outname)
X				);
X			user_become_undo();
X			if (ignore)
X				break;
X
X			/*
X			 * create directory for diff file
X			 */
X			user_become(up);
X			os_mkdir_between(dd, s1, 02755);
X			user_become_undo();
X
X			/*
X			 * difference the file
X			 * to nothing
X			 */
X			original = str_format("%S/%S", bl, s1);
X			if
X			(
X				src1_data->move
X			&&
X				change_src_find(cp, src1_data->move)
X			)
X			{
X				input =
X					str_format
X					(
X						"%S/%S",
X						dd,
X						src1_data->move
X					);
X			}
X			else
X				input = str_from_c("/dev/null");
X			change_run_diff_command
X			(
X				cp,
X				up,
X				original,
X				input,
X				outname
X			);
X			str_free(original);
X			str_free(input);
X			user_become(up);
X			src1_data->diff_time = 0;
X			src1_data->diff_file_time = os_mtime(outname);
X			user_become_undo();
X			break;
X
X		case file_action_modify:
X			/*
X			 * find the relevant baseline src data
X			 * note that someone may have deleted it from under you
X			 */
X			src2_data = project_src_find(pp, s1);
X			if (!src2_data)
X			{
X				change_fatal
X				(
X					cp,
X					"file \"%S\" no longer in baseline",
X					s1
X				);
X			}
X			if (str_equal(src1_data->edit_number, src2_data->edit_number))
X			{
X				/*
X				 * do nothing if we can
X				 */
X				user_become(up);
X				ignore =
X					(
X						src1_data->diff_time
X					&&
X						src1_data->diff_file_time
X					&&
X						os_exists(curfile)
X					&&
X						src1_data->diff_time == os_mtime(curfile)
X					&&
X						os_exists(outname)
X					&&
X						src1_data->diff_file_time == os_mtime(outname)
X					);
X				user_become_undo();
X				if (ignore)
X					break;
X
X				/*
X				 * If the edit number of the file in the change
X				 * files table matches the edit number in the
X				 * baseline files table,
X				 * use the diff-command
X				 */
X				original = str_format("%S/%S", bl, s1);
X				change_run_diff_command
X				(
X					cp,
X					up,
X					original,
X					curfile,
X					outname
X				);
X				str_free(original);
X				user_become(up);
X				src1_data->diff_time = os_mtime(curfile);
X				src1_data->diff_file_time = os_mtime(outname);
X				user_become_undo();
X			}
X			else
X			{
X				string_ty	*most_recent;
X
X				/*
X				 * name for temp file
X				 */
X				original = os_edit_filename();
X				user_become(up);
X				undo_unlink_errok(original);
X				user_become_undo();
X
X				/*
X				 * get the version out of history
X				 */
X				change_run_history_get_command
X				(
X					cp,
X					s1,
X					src1_data->edit_number,
X					original,
X					up
X				);
X
X				/*
X				 * use the diff3-command
X				 */
X				most_recent = str_format("%S/%S", bl, s1);
X				change_run_diff3_command
X				(
X					cp,
X					up,
X					original,
X					most_recent,
X					curfile,
X					outname
X				);
X				str_free(most_recent);
X
X				/*
X				 * Remember to remove the temporary file when
X				 * finished.
X				 */
X				user_become(up);
X				os_unlink(original);
X				user_become_undo();
X				str_free(original);
X
X				/*
X				 * Set the edit number in the change
X				 * to the latest baseline edit number.
X				 */
X				str_free(src1_data->edit_number);
X				src1_data->edit_number =
X					str_copy(src2_data->edit_number);
X
X				/*
X				 * Invalidate the build-time field.
X				 * Invalidate the diff-time fields.
X				 * (because need new build)
X				 */
X				wl_append(&need_new_build, src1_data->file_name);
X				cstate_data->build_time = 0;
X				src1_data->diff_time = 0;
X				src1_data->diff_file_time = 0;
X			}
X			break;
X		}
X		str_free(curfile);
X		str_free(outname);
X	}
X
X	/*
X	 * If the change row (or change file table) changed,
X	 * write it out.
X	 * Release advisory lock.
X	 */
X	change_cstate_write(cp);
X	commit();
X	lock_release();
X
X	/*
X	 * verbose success message
X	 */
X	if (wl.wl_nwords == cstate_data->src->length)
X		change_verbose(cp, "difference complete");
X	else
X		change_verbose(cp, "partial difference done");
X	if (need_new_build.wl_nwords)
X	{
X		for (j = 0; j < need_new_build.wl_nwords; ++j)
X		{
X			change_error
X			(
X				cp,
X			"file \"%S\" was out of date, see \"%S,D\" for details",
X				need_new_build.wl_word[j],
X				need_new_build.wl_word[j]
X			);
X		}
X		error("new '%s -Build' required", option_progname_get());
X	}
X	change_free(cp);
X	project_free(pp);
X	user_free(up);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xdifference()
X{
X	trace(("difference()\n{\n"/*}*/));
X	switch (arglex())
X	{
X	default:
X		difference_main();
X		break;
X
X	case arglex_token_help:
X		difference_help();
X		break;
X
X	case arglex_token_list:
X		difference_list();
X		break;
X	}
X	trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 26542 -ne `wc -c <'aegis/aed.c'`; then
    echo shar: \"'aegis/aed.c'\" unpacked with wrong size!
fi
# end of 'aegis/aed.c'
fi
if test -f 'aegis/aeib.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'aegis/aeib.c'\"
else
echo shar: Extracting \"'aegis/aeib.c'\" \(23895 characters\)
sed "s/^X//" >'aegis/aeib.c' <<'END_OF_FILE'
X/*
X *	aegis - project change supervisor
X *	Copyright (C) 1991, 1992, 1993 Peter Miller.
X *	All rights reserved.
X *
X *	This program is free software; you can redistribute it and/or modify
X *	it under the terms of the GNU General Public License as published by
X *	the Free Software Foundation; either version 2 of the License, or
X *	(at your option) any later version.
X *
X *	This program is distributed in the hope that it will be useful,
X *	but WITHOUT ANY WARRANTY; without even the implied warranty of
X *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X *	GNU General Public License for more details.
X *
X *	You should have received a copy of the GNU General Public License
X *	along with this program; if not, write to the Free Software
X *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions for implementing integrate begin
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <aeib.h>
X#include <ael.h>
X#include <arglex2.h>
X#include <commit.h>
X#include <change.h>
X#include <dir.h>
X#include <error.h>
X#include <file.h>
X#include <help.h>
X#include <lock.h>
X#include <log.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <sub.h>
X#include <trace.h>
X#include <undo.h>
X#include <user.h>
X
X
Xstatic void integrate_begin_usage _((void));
X
Xstatic void
Xintegrate_begin_usage()
X{
X	char		*progname;
X
X	progname = option_progname_get();
X	fprintf(stderr, "usage: %s -Integrate_Begin [ <option>... ]\n", progname);
X	fprintf(stderr, "       %s -Integrate_Begin -List [ <option>... ]\n", progname);
X	fprintf(stderr, "       %s -Integrate_Begin -Help\n", progname);
X	quit(1);
X}
X
X
Xstatic void integrate_begin_help _((void));
X
Xstatic void
Xintegrate_begin_help()
X{
X	static char *text[] =
X	{
X"NAME",
X"	%s -Integrate_Begin - begin integrating a change",
X"",
X"SYNOPSIS",
X"	%s -Integrate_Begin <change-number> [ <option>... ]",
X"	%s -Integrate_Begin -List [ <option>... ]",
X"	%s -Integrate_Begin -Help",
X"",
X"DESCRIPTION",
X"	The %s -Integrate_Begin command is used to begin the",
X"	integration of a change into the baseline of a project.",
X"",
X"	The change will advance from the 'awaiting_integration'",
X"	state to the 'being_integrated' state.",
X"",
X"	A copy of the baseline is created in an integration",
X"	directory and the the files of the change are added to",
X"	the integration directory; time stamps on the files are",
X"	preserved.  The '%s -Change_Directory' command may be",
X"	used to locate this directory.	The change will be",
X"	assigned to the current user.",
X"",
X"	The change will be assigned a delta number.  Delta",
X"	numbers are incrimented once for each %s",
X"	-Intgerate_Begin command for the project.  If an",
X"	integration is subsequently aborted with either the %s",
X"	-Integrate_Begin_Undo or %s -Integrate_FAIL command,",
X"	the delta number will not be re-used.",
X"",
X"	It is not possible to choose the integration directory,",
X"	as there are many constraints upon it, including the fact",
X"	that it must be on the same device as the baseline",
X"	directory, and that many UNIX implementations don't allow",
X"	renaming directories up and down the trees.  The",
X"	integration directory will be in the project directory,",
X"	and named for the delta number.",
X"",
X"OPTIONS",
X"	The following options are understood:",
X"",
X"	-Change <number>",
X"		This option may be used to specify a particular",
X"		change within a project.  When no -Change option is",
X"		specified, the AEGIS_CHANGE environment variable is",
X"		consulted.  If that does not exist, the user's",
X"		$HOME/.aegisrc file is examined for a default change",
X"		field (see aeuconf(5) for more information).  If",
X"		that does not exist, when the user is only working",
X"		on one change within a project, that is the default",
X"		change number.  Otherwise, it is an error.",
X"",
X"	-Help",
X"		This option may be used to obtain more",
X"		information about how to use the %s program.",
X"",
X"	-List",
X"		This option may be used to obtain a list of",
X"		suitable subjects for this command.  The list may",
X"		be more general than expected.",
X"",
X"	-MINimum",
X"		This option may be used to cause only the source",
X"		files to be copied into the integration",
X"		directory.  The default is to copy all files,",
X"		unless the change requires the deletion of a",
X"		file.",
X"",
X"	-Project <name>",
X"		This option may be used to select the project of",
X"		interest.  When no -Project option is specified, the",
X"		AEGIS_PROJECT environment variable is consulted.  If",
X"		that does not exist, the user's $HOME/.aegisrc file",
X"		is examined for a default project field (see",
X"		aeuconf(5) for more information).  If that does not",
X"		exist, when the user is only working on changes",
X"		within a single project, the project name defaults",
X"		to that project.  Otherwise, it is an error.",
X"",
X"	-TERse",
X"		This option may be used to cause listings to",
X"		produce the bare minimum of information.  It is",
X"		usually useful for shell scripts.",
X"",
X"	-Verbose",
X"		This option may be used to cause %s to produce",
X"		more output.  By default %s only produces",
X"		output on errors.  When used with the -List",
X"		option this option causes column headings to be",
X"		added.",
X"",
X"	All options may be abbreviated; the abbreviation is",
X"	documented as the upper case letters, all lower case",
X"	letters and underscores (_) are optional.  You must use",
X"	consecutive sequences of optional letters.",
X"",
X"	All options are case insensitive, you may type them in",
X"	upper case or lower case or a combination of both, case",
X"	is not important.",
X"",
X"	For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X"	are all interpreted to mean the -Project option.  The",
X"	argument \"-prj\" will not be understood, because",
X"	consecutive optional characters were not supplied.",
X"",
X"	Options and other command line arguments may be mixed",
X"	arbitrarily on the command line, after the function",
X"	selectors.",
X"",
X"	The GNU long option names are understood.  Since all",
X"	option names for aegis are long, this means ignoring the",
X"	extra leading '-'.  The \"--option=value\" convention is",
X"	also understood.",
X"",
X"RECOMMENDED ALIAS",
X"	The recommended alias for this command is",
X"	csh%%	alias aeib '%s -ib \\!* -v'",
X"	sh$	aeib(){%s -ib $* -v}",
X"",
X"ERRORS",
X"	It is an error if the change is not in the",
X"	'awaiting_integration' state.",
X"	It is an error if the current user is not an integrator",
X"	of the project.",
X"	It is an error if there is an integration in progress for",
X"	the project.",
X"	It is an error if the current user developed the change",
X"	and the project is configured to disallow developers to",
X"	integrate their own changes (default).",
X"	It is an error if the current user reviewed the change",
X"	and the project is configured to disallow reviewers to",
X"	integrate their such changes (default).",
X"",
X"EXIT STATUS",
X"	The %s command will exit with a status of 1 on any",
X"	error.	The %s command will only exit with a status of",
X"	0 if there are no errors.",
X"",
X"COPYRIGHT",
X"	%C",
X"",
X"AUTHOR",
X"	%A",
X	};
X
X	help(text, SIZEOF(text), integrate_begin_usage);
X}
X
X
Xstatic void integrate_begin_list _((void));
X
Xstatic void
Xintegrate_begin_list()
X{
X	string_ty	*project_name;
X
X	trace(("integrate_begin_list()\n{\n"/*}*/));
X	arglex();
X	project_name = 0;
X	while (arglex_token != arglex_token_eoln)
X	{
X		switch (arglex_token)
X		{
X		default:
X			generic_argument(integrate_begin_usage);
X			continue;
X
X		case arglex_token_project:
X			if (arglex() != arglex_token_string)
X				integrate_begin_usage();
X			if (project_name)
X				fatal("duplicate -Project option");
X			project_name = str_from_c(arglex_value.alv_string);
X			break;
X		}
X		arglex();
X	}
X	list_changes_in_state_mask
X	(
X		project_name,
X		1 << cstate_state_awaiting_integration
X	);
X	if (project_name)
X		str_free(project_name);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void link_tree_callback_minimum _((void *, dir_walk_message_ty,
X	string_ty *, struct stat *));
X
Xstatic void
Xlink_tree_callback_minimum(arg, message, path, st)
X	void		*arg;
X	dir_walk_message_ty message;
X	string_ty	*path;
X	struct stat	*st;
X{
X	string_ty	*s1;
X	string_ty	*s2;
X	change_ty	*cp;
X	pstate_src	src;
X
X	trace(("link_tree_callback_minimum(message = %d, path = %08lX, \
Xst = %08lX)\n{\n"/*}*/, message, path, st));
X	cp = (change_ty *)arg;
X	assert(cp);
X	trace_string(path->str_text);
X	s1 = os_below_dir(project_baseline_path_get(cp->pp, 1), path);
X	assert(s1);
X	trace_string(s1->str_text);
X	if (!s1->str_length)
X		s2 = str_copy(change_integration_directory_get(cp, 1));
X	else
X		s2 = str_format("%S/%S", change_integration_directory_get(cp, 1), s1);
X	trace_string(s2->str_text);
X	switch (message)
X	{
X	case dir_walk_dir_before:
X		if (!s1->str_length)
X		{
X			assert(!os_exists(s2));
X			os_mkdir(s2, 02755);
X			undo_rmdir_errok(s2);
X		}
X		break;
X
X	case dir_walk_file:
X		if (st->st_mode & 07000)
X		{
X			/*
X			 * Don't link files with horrible modes.
X			 * They shouldn't be source, anyway.
X			 */
X			if (!project_src_find(cp->pp, s1))
X				break;
X		}
X
X		/*
X		 * don't link it if it's not a source file
X		 */
X		src = project_src_find(cp->pp, s1);
X		if
X		(
X			!src
X		||
X			src->deleted_by
X		||
X			src->about_to_be_created_by
X		||
X			src->usage == file_usage_build
X		)
X			break;
X
X		/*
X		 * make sure the directory is there
X		 */
X		os_mkdir_between
X		(
X			change_integration_directory_get(cp, 1),
X			s1,
X			02755
X		);
X
X		/*
X		 * don't link file if in change
X		 */
X		if (change_src_find(cp, s1))
X			break;
X
X		/*
X		 * link the file and make sure it is a suitable mode
X		 */
X		os_link(path, s2);
X		undo_unlink_errok(s2);
X		os_chmod(s2, (st->st_mode | 0444) & ~0222 & ~change_umask(cp));
X		break;
X
X	case dir_walk_dir_after:
X		break;
X
X	case dir_walk_special:
X	case dir_walk_symlink:
X		/*
X		 * ignore special files
X		 *
X		 * They could never be source files,
X		 * so they must be created by the build.
X		 * These ones must always be created at build time, that's all.
X		 */
X		break;
X	}
X	str_free(s2);
X	str_free(s1);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void link_tree_callback _((void *, dir_walk_message_ty, string_ty *,
X	struct stat *));
X
Xstatic void
Xlink_tree_callback(arg, message, path, st)
X	void		*arg;
X	dir_walk_message_ty message;
X	string_ty	*path;
X	struct stat	*st;
X{
X	string_ty	*s1;
X	string_ty	*s2;
X	change_ty	*cp;
X	pstate_src	src;
X
X	trace(("link_tree_callback(message = %d, path = %08lX, \
Xst = %08lX)\n{\n"/*}*/, message, path, st));
X	cp = (change_ty *)arg;
X	assert(cp);
X	trace_string(path->str_text);
X	s1 = os_below_dir(project_baseline_path_get(cp->pp, 1), path);
X	assert(s1);
X	trace_string(s1->str_text);
X	if (!s1->str_length)
X		s2 = str_copy(change_integration_directory_get(cp, 1));
X	else
X		s2 = str_format("%S/%S", change_integration_directory_get(cp, 1), s1);
X	trace_string(s2->str_text);
X	switch (message)
X	{
X	case dir_walk_dir_before:
X		assert(!os_exists(s2));
X		os_mkdir(s2, 02755);
X		undo_rmdir_errok(s2);
X		break;
X
X	case dir_walk_file:
X		src = project_src_find(cp->pp, s1);
X		if (st->st_mode & 07000)
X		{
X			/*
X			 * Don't link files with horrible modes.
X			 * They shouldn't be source, anyway.
X			 */
X			if (!src)
X				break;
X		}
X		if (src && src->usage == file_usage_build)
X			break;
X
X		/*
X		 * don't link change files
X		 */
X		if (change_src_find(cp, s1))
X			break;
X
X		/*
X		 * link the file and make sure it is a suitable mode
X		 */
X		os_link(path, s2);
X		undo_unlink_errok(s2);
X		if (!src)
X			os_chmod(s2, (st->st_mode | 0644) & ~0022 & ~change_umask(cp));
X		else
X			os_chmod(s2, (st->st_mode | 0444) & ~0222 & ~change_umask(cp));
X		break;
X
X	case dir_walk_dir_after:
X		break;
X
X	case dir_walk_special:
X	case dir_walk_symlink:
X		/*
X		 * ignore special files
X		 *
X		 * They could never be source files,
X		 * so they must be created by the build.
X		 * These ones must always be created at build time, that's all.
X		 */
X		break;
X	}
X	str_free(s2);
X	str_free(s1);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void copy_tree_callback_minimum _((void *, dir_walk_message_ty,
X	string_ty *, struct stat *));
X
Xstatic void
Xcopy_tree_callback_minimum(arg, message, path, st)
X	void		*arg;
X	dir_walk_message_ty message;
X	string_ty	*path;
X	struct stat	*st;
X{
X	string_ty	*s1;
X	string_ty	*s2;
X	change_ty	*cp;
X	pstate_src	src;
X	int		uid;
X
X	trace(("copy_tree_callback(message = %d, path = %08lX, \
Xst = %08lX)\n{\n"/*}*/, message, path, st));
X	cp = (change_ty *)arg;
X	assert(cp);
X	trace_string(path->str_text);
X	s1 = os_below_dir(project_baseline_path_get(cp->pp, 1), path);
X	assert(s1);
X	trace_string(s1->str_text);
X	if (!s1->str_length)
X		s2 = str_copy(change_integration_directory_get(cp, 1));
X	else
X	{
X		s2 =
X			str_format
X			(
X				"%S/%S",
X				change_integration_directory_get(cp, 1),
X				s1
X			);
X	}
X	trace_string(s2->str_text);
X	switch (message)
X	{
X	case dir_walk_dir_before:
X		if (!s1->str_length)
X		{
X			assert(!os_exists(s2));
X			os_mkdir(s2, 02755);
X			undo_rmdir_errok(s2);
X		}
X		break;
X
X	case dir_walk_file:
X		if (st->st_mode & 07000)
X		{
X			/*
X			 * Don't copy files with horrible modes.
X			 * They shouldn't be source, anyway.
X			 */
X			if (!project_src_find(cp->pp, s1))
X				break;
X		}
X
X		/*
X		 * Don't copy files which don't belong to us.
X		 * They shouldn't be source, anyway.
X		 */
X		os_become_query(&uid, (int *)0, (int *)0);
X		src = project_src_find(cp->pp, s1);
X		if (st->st_uid != uid && !src)
X			break;
X
X		/*
X		 * don't copy it if it's not a source file
X		 */
X		if
X		(
X			!src
X		||
X			src->deleted_by
X		||
X			src->about_to_be_created_by
X		||
X			src->usage == file_usage_build
X		)
X			break;
X
X		/*
X		 * make sure the directory is there
X		 */
X		os_mkdir_between
X		(
X			change_integration_directory_get(cp, 1),
X			s1,
X			02755
X		);
X
X		/*
X		 * don't copy change files
X		 */
X		if (change_src_find(cp, s1))
X			break;
X
X		/*
X		 * copy the file
X		 */
X		copy_whole_file(path, s2, 0);
X		undo_unlink_errok(s2);
X		os_chmod(s2, (st->st_mode | 0444) & ~0222 & ~change_umask(cp));
X		break;
X
X	case dir_walk_dir_after:
X		break;
X
X	case dir_walk_special:
X	case dir_walk_symlink:
X		/*
X		 * ignore special files
X		 *
X		 * They could never be source files,
X		 * so they must be created by the build.
X		 * These ones must always be created at build time, that's all.
X		 */
X		break;
X	}
X	str_free(s2);
X	str_free(s1);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void copy_tree_callback _((void *, dir_walk_message_ty, string_ty *,
X	struct stat *));
X
Xstatic void
Xcopy_tree_callback(arg, message, path, st)
X	void		*arg;
X	dir_walk_message_ty message;
X	string_ty	*path;
X	struct stat	*st;
X{
X	string_ty	*s1;
X	string_ty	*s2;
X	change_ty	*cp;
X	pstate_src	src;
X	int		uid;
X
X	trace(("copy_tree_callback(message = %d, path = %08lX, st = %08lX)\n{\n"/*}*/, message, path, st));
X	cp = (change_ty *)arg;
X	assert(cp);
X	trace_string(path->str_text);
X	s1 = os_below_dir(project_baseline_path_get(cp->pp, 1), path);
X	assert(s1);
X	trace_string(s1->str_text);
X	if (!s1->str_length)
X		s2 = str_copy(change_integration_directory_get(cp, 1));
X	else
X	{
X		s2 =
X			str_format
X			(
X				"%S/%S",
X				change_integration_directory_get(cp, 1),
X				s1
X			);
X	}
X	trace_string(s2->str_text);
X	switch (message)
X	{
X	case dir_walk_dir_before:
X		assert(!os_exists(s2));
X		os_mkdir(s2, 02755);
X		undo_rmdir_errok(s2);
X		break;
X
X	case dir_walk_file:
X		/*
X		 * Don't copy files with horrible modes.
X		 * They shouldn't be source, anyway.
X		 */
X		src = project_src_find(cp->pp, s1);
X		if ((st->st_mode & 07000) && !src)
X			break;
X		if (src && src->usage == file_usage_build)
X			break;
X
X		/*
X		 * Don't copy files which don't belong to us.
X		 * They shouldn't be source, anyway.
X		 */
X		os_become_query(&uid, (int *)0, (int *)0);
X		if (st->st_uid != uid && !src)
X			break;
X
X		/*
X		 * don't copy change files
X		 */
X		if (change_src_find(cp, s1))
X			break;
X
X		/*
X		 * copy the file
X		 */
X		copy_whole_file(path, s2, 0);
X		undo_unlink_errok(s2);
X		if (!src)
X			os_chmod(s2, (st->st_mode | 0644) & ~0022 & ~change_umask(cp));
X		else
X			os_chmod(s2, (st->st_mode | 0444) & ~0222 & ~change_umask(cp));
X		break;
X
X	case dir_walk_dir_after:
X		break;
X
X	case dir_walk_special:
X	case dir_walk_symlink:
X		/*
X		 * ignore special files
X		 *
X		 * They could never be source files,
X		 * so they must be created by the build.
X		 * These ones must always be created at build time, that's all.
X		 */
X		break;
X	}
X	str_free(s2);
X	str_free(s1);
X	trace((/*{*/"}\n"));
X}
X
X
Xstatic void integrate_begin_main _((void));
X
Xstatic void
Xintegrate_begin_main()
X{
X	string_ty	*bl;
X	string_ty	*dd;
X	string_ty	*id;
X	pconf		pconf_data;
X	pstate		pstate_data;
X	cstate		cstate_data;
X	int		j;
X	cstate_history	history_data;
X	int		minimum;
X	string_ty	*project_name;
X	project_ty	*pp;
X	long		change_number;
X	change_ty	*cp;
X	user_ty		*up;
X	int		errs;
X	string_ty	*s;
X
X	trace(("integrate_begin_main()\n{\n"/*}*/));
X	minimum = 0;
X	project_name = 0;
X	change_number = 0;
X	while (arglex_token != arglex_token_eoln)
X	{
X		switch (arglex_token)
X		{
X		default:
X			generic_argument(integrate_begin_usage);
X			continue;
X
X		case arglex_token_change:
X			if (arglex() != arglex_token_number)
X				integrate_begin_usage();
X			/* fall through... */
X
X		case arglex_token_number:
X			if (change_number)
X				fatal("duplicate -Change option");
X			change_number = arglex_value.alv_number;
X			if (change_number < 1)
X				fatal("change %ld out of range", change_number);
X			break;
X
X		case arglex_token_minimum:
X			if (minimum)
X			{
X				fatal
X				(
X					"duplicate %s option",
X					arglex_value.alv_string
X				);
X			}
X			minimum = 1;
X			break;
X
X		case arglex_token_project:
X			if (arglex() != arglex_token_string)
X				integrate_begin_usage();
X			/* fall through... */
X
X		case arglex_token_string:
X			if (project_name)
X				fatal("duplicate -Project option");
X			project_name = str_from_c(arglex_value.alv_string);
X			break;
X		}
X		arglex();
X	}
X
X	/*
X	 * locate project data
X	 */
X	if (!project_name)
X		project_name = user_default_project();
X	pp = project_alloc(project_name);
X	str_free(project_name);
X	project_bind_existing(pp);
X
X	/*
X	 * locate user data
X	 */
X	up = user_executing(pp);
X
X	/*
X	 * locate change data
X	 */
X	if (!change_number)
X		change_number = user_default_change(up);
X	cp = change_alloc(pp, change_number);
X	change_bind_existing(cp);
X
X	/*
X	 * lock the project, the change and the user
X	 */
X	project_pstate_lock_prepare(pp);
X	change_cstate_lock_prepare(cp);
X	user_ustate_lock_prepare(up);
X	lock_take();
X	pstate_data = project_pstate_get(pp);
X	cstate_data = change_cstate_get(cp);
X	pconf_data = change_pconf_get(cp);
X
X	/*
X	 * make sure they are allowed to
X	 */
X	if (!project_integrator_query(pp, user_name(up)))
X	{
X		project_fatal
X		(
X			pp,
X			"user \"%S\" is not an integrator",
X			user_name(up)
X		);
X	}
X	if (cstate_data->state != cstate_state_awaiting_integration)
X		change_fatal(cp, "not in 'awaiting_integration' state");
X
X	/*
X	 * make sure only one integration at a time
X	 * for each project
X	 */
X	if (pstate_data->currently_integrating_change)
X	{
X		project_fatal
X		(
X			pp,
X			"change %ld: currently active integration",
X			pstate_data->currently_integrating_change
X		);
X	}
X	pstate_data->currently_integrating_change = change_number;
X
X	/*
X	 * grab a delta number
X	 * and advance the project's delta counter
X	 */
X	cstate_data->delta_number = pstate_data->next_delta_number;
X	pstate_data->next_delta_number++;
X
X	/*
X	 * Create the integration directory.
X	 */
X	s =
X		str_format
X		(
X			"%S/delta.%3.3ld",
X			project_home_path_get(pp),
X			cstate_data->delta_number
X		);
X	change_integration_directory_set(cp, s);
X	str_free(s);
X
X	/*
X	 * There will be many files in the baseline in addition
X	 * to the sources files.
X	 *
X	 * If any files are being deleted, only copy the source files
X	 * from the baseline to the integration directory.
X	 * This way the additional files relating to the removed sources file
X	 * are also removed (eg remove a .c file and you need to get rid of the
X	 * .o file).  It also shows when dependencies have become out-of-date.
X	 *
X	 * It is possible to ask for this from the command line, too.
X	 */
X	for (j = 0; j < cstate_data->src->length; ++j)
X	{
X		if (cstate_data->src->list[j]->action == file_action_remove)
X		{
X			minimum = 1;
X			break;
X		}
X	}
X
X	/*
X	 * before creating the integration directory,
X	 * make sure none of the change files have been tampered with.
X	 *
X	 * (a) the project owner must have access
X	 * (b) the changed file must exist and not have been modified
X	 * (c) the difference file must exist and not have been modified
X	 */
X	dd = change_development_directory_get(cp, 1);
X	id = change_integration_directory_get(cp, 1);
X	bl = project_baseline_path_get(pp, 1);
X	project_become(pp);
X	errs = 0;
X	for (j = 0; j < cstate_data->src->length; ++j)
X	{
X		cstate_src	src_data;
X		string_ty	*s1;
X		string_ty	*s2;
X
X		src_data = cstate_data->src->list[j];
X		if (src_data->usage == file_usage_build)
X			continue;
X		s1 = str_format("%S/%S", dd, src_data->file_name);
X		s2 = str_format("%S,D", s1);
X		switch (src_data->action)
X		{
X		case file_action_remove:
X			break;
X
X		case file_action_modify:
X		case file_action_create:
X			if
X			(
X				!os_exists(s1)
X			||
X				os_mtime(s1) != src_data->diff_time
X			)
X			{
X				change_error
X				(
X					cp,
X					"file \"%S\" has been altered",
X					s1
X				);
X				errs++;
X			}
X			break;
X		}
X		if (!os_exists(s2) || os_mtime(s2) != src_data->diff_file_time)
X		{
X			change_error(cp, "file \"%S\" has been altered", s2);
X			errs++;
X		}
X	}
X	if (errs)
X		quit(1);
X
X	/*
X	 * create the integration directory
X	 * copy everything from baseline to integration directory
X	 * except things from the change
X	 * and change owner to the project's owner.
X	 */
X	if (pconf_data->link_integration_directory)
X	{
X		change_verbose(cp, "link baseline to integration directory");
X		dir_walk
X		(
X			bl,
X			(
X				minimum
X			?
X				link_tree_callback_minimum
X			:
X				link_tree_callback
X			),
X			cp
X		);
X	}
X	else
X	{
X		change_verbose(cp, "copy baseline to integration directory");
X		dir_walk
X		(
X			bl,
X			(
X				minimum
X			?
X				copy_tree_callback_minimum
X			:
X				copy_tree_callback
X			),
X			cp
X		);
X	}
X
X	/*
X	 * apply the changes to the integration directory
X	 */
X	change_verbose(cp, "apply change to integration directory");
X	for (j = 0; j < cstate_data->src->length; ++j)
X	{
X		cstate_src	src_data;
X		string_ty	*s1;
X		string_ty	*s2;
X
X		src_data = cstate_data->src->list[j];
X		s1 = str_format("%S/%S", dd, src_data->file_name);
X		s2 = str_format("%S/%S", id, src_data->file_name);
X		if (os_exists(s2))
X		{
X			/*
X			 * this is defensive,
X			 * and should never need to be executed
X			 */
X			os_unlink(s2);
X		}
X		switch (src_data->action)
X		{
X		case file_action_remove:
X			break;
X
X		case file_action_modify:
X		case file_action_create:
X			if (src_data->usage == file_usage_build)
X				break;
X			/*
X			 * New files do not exist in the baseline,
X			 * and old files may not be copied under -MINimum,
X			 * so we may need to create directories.
X			 */
X			os_mkdir_between(id, src_data->file_name, 02755);
X			copy_whole_file(s1, s2, 0);
X			os_chmod(s2, 0444 & ~change_umask(cp));
X			break;
X		}
X		str_free(s1);
X		str_free(s2);
X	}
X	project_become_undo();
X
X	/*
X	 * add the change to the user's list
X	 */
X	user_own_add(up, project_name_get(pp), change_number);
X	cstate_data->state = cstate_state_being_integrated;
X	history_data = change_history_new(cp, up);
X	history_data->what = cstate_history_what_integrate_begin;
X
X	/*
X	 * write the data out
X	 * and release the locks
X	 */
X	project_pstate_write(pp);
X	change_cstate_write(cp);
X	user_ustate_write(up);
X	commit();
X	lock_release();
X
X	/*
X	 * run the integrate begin command
X	 */
X	change_run_integrate_begin_command(cp);
X
X	/*
X	 * verbose success message
X	 */
X	change_verbose(cp, "integration has begun");
X	change_free(cp);
X	project_free(pp);
X	user_free(up);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xintegrate_begin()
X{
X	trace(("integrate_begin()\n{\n"/*}*/));
X	switch (arglex())
X	{
X	default:
X		integrate_begin_main();
X		break;
X
X	case arglex_token_help:
X		integrate_begin_help();
X		break;
X
X	case arglex_token_list:
X		integrate_begin_list();
X		break;
X	}
X	trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 23895 -ne `wc -c <'aegis/aeib.c'`; then
    echo shar: \"'aegis/aeib.c'\" unpacked with wrong size!
fi
# end of 'aegis/aeib.c'
fi
if test -f 'aegis/os.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'aegis/os.c'\"
else
echo shar: Extracting \"'aegis/os.c'\" \(27024 characters\)
sed "s/^X//" >'aegis/os.c' <<'END_OF_FILE'
X/*
X *	aegis - project change supervisor
X *	Copyright (C) 1991, 1992, 1993 Peter Miller.
X *	All rights reserved.
X *
X *	This program is free software; you can redistribute it and/or modify
X *	it under the terms of the GNU General Public License as published by
X *	the Free Software Foundation; either version 2 of the License, or
X *	(at your option) any later version.
X *
X *	This program is distributed in the hope that it will be useful,
X *	but WITHOUT ANY WARRANTY; without even the implied warranty of
X *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X *	GNU General Public License for more details.
X *
X *	You should have received a copy of the GNU General Public License
X *	along with this program; if not, write to the Free Software
X *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: wrappers around operating system functions
X */
X
X#include <stdlib.h>
X#include <errno.h>
X#include <stdio.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <signal.h>
X#include <unistd.h>
X#include <utime.h>
X
X#include <conf.h>
X#include <dir.h>
X#include <error.h>
X#include <file.h>
X#include <glue.h>
X#include <mem.h>
X#include <option.h>
X#include <os.h>
X#include <trace.h>
X#include <undo.h>
X#include <word.h>
X
X#define MAX_CMD_RPT 36
X
X
Xstatic int interrupted;
X
X
Xstatic void interrupt _((int));
X
Xstatic void
Xinterrupt(n)
X	int	n;
X{
X	interrupted++;
X	signal(n, interrupt);
X}
X
X
Xint
Xos_waitpid_status(child, cmd)
X	int		child;
X	char		*cmd;
X{
X	int		result;
X	void		(*hold)_((int));
X	int		a, b, c;
X	int		status;
X
X	trace(("os_waitpid_status(child = %d, cmd = \"%s\")\n{\n"/*}*/, child, cmd));
X	interrupted = 0;
X	hold = signal(SIGINT, SIG_IGN);
X	if (hold != SIG_IGN)
X		signal(SIGINT, interrupt);
X	result = 0;
X	if (os_waitpid(child, &status))
X		nfatal("wait");
X	a = (status >> 8) & 0xFF;
X	b = (status >> 7) & 1;
X	c = status & 0x7F;
X	switch (c)
X	{
X	case 0x7F:
X		/*
X		 * process was stopped,
X		 * since we didn't do it, treat it as an error
X		 */
X		fatal("command \"%s\" stopped", cmd);
X
X	case 0:
X		/* normal termination */
X		result = a;
X		break;
X
X	default:
X		/*
X		 * process dies from unhandled condition
X		 */
X		fatal
X		(
X			"command \"%s\" terminated by %s%s",
X			cmd,
X			signal_name(c),
X			(b ? " (core dumped)" : "")
X		);
X	}
X	if (hold != SIG_IGN)
X		signal(SIGINT, hold);
X	if (interrupted)
X		fatal("interrupted");
X	trace(("return %d;\n", result));
X	trace((/*{*/"}\n"));
X	return result;
X}
X
X
Xint
Xos_exists(path)
X	string_ty	*path;
X{
X	struct stat	st;
X
X	os_become_must_be_active();
X	if (glue_stat(path->str_text, &st))
X	{
X		if (errno != ENOENT)
X			nfatal("stat(\"%s\")", path->str_text);
X		return 0;
X	}
X	return 1;
X}
X
X
Xvoid
Xos_mkdir(path, mode)
X	string_ty	*path;
X	int		mode;
X{
X	int		uid;
X	int		gid;
X	int		um;
X
X	trace(("os_mkdir(path = \"%s\", mode = 0%o)\n{\n"/*}*/,
X		path->str_text, mode));
X	os_become_must_be_active();
X	if (glue_mkdir(path->str_text, mode))
X		nfatal("mkdir(\"%s\", 0%o)", path->str_text, mode);
X
X	/*
X	 * There could be Berkeley semantics about the group
X	 * of the newly created directory, so make sure it is
X	 * the one intended (egid).
X	 */
X	os_become_query(&uid, &gid, &um);
X	if (glue_chown(path->str_text, -1, gid))
X		nfatal("chgrp(\"%s\", %d)", path->str_text, gid);
X
X	/*
X	 * The set-group-id bit is ignored by a Berkeley semantics mkdir
X	 * (and it would be nuked the the chgrp, anyway)
X	 * so set it explicitly.
X	 */
X	mode &= ~um;
X	if (glue_chmod(path->str_text, mode))
X		nfatal("chmod(\"%s\", 0%0)", path->str_text, mode);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_rmdir(path)
X	string_ty	*path;
X{
X	trace(("os_rmdir(path = \"%s\")\n{\n"/*}*/, path->str_text));
X	os_become_must_be_active();
X	if (glue_rmdir(path->str_text))
X		nfatal("rmdir(\"%s\")", path->str_text);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_rmdir_errok(path)
X	string_ty	*path;
X{
X	trace(("os_rmdir_errok(path = \"%s\")\n{\n"/*}*/, path->str_text));
X	os_become_must_be_active();
X	if (glue_rmdir(path->str_text))
X		nerror("warning: rmdir(\"%s\")", path->str_text);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_mkdir_between(top, extn, mode)
X	string_ty	*top;
X	string_ty	*extn;
X	int		mode;
X{
X	char		*cp;
X	string_ty	*s1;
X	string_ty	*s2;
X
X	trace(("os_mkdir_between(top = %08lX, extn = %08lX, \
Xmode = 0%o)\n{\n"/*}*/, top, extn, mode));
X	trace_string(top->str_text);
X	trace_string(extn->str_text);
X	assert(top->str_text[0] == '/');
X	assert(extn->str_text[0] != '/');
X	assert(extn->str_text[extn->str_length - 1] != '/');
X	assert(extn->str_length);
X	for (cp = extn->str_text; *cp; ++cp)
X	{
X		if (*cp != '/')
X			continue;
X		s1 = str_n_from_c(extn->str_text, cp - extn->str_text);
X		s2 = str_format("%S/%S", top, s1);
X		if (!os_exists(s2))
X		{
X			os_mkdir(s2, mode);
X			undo_rmdir_errok(s2);
X		}
X		str_free(s1);
X		str_free(s2);
X	}
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_rename(a, b)
X	string_ty	*a;
X	string_ty	*b;
X{
X	trace(("os_rename(a = %08lX, b = %08lX)\n{\n"/*}*/, a, b));
X	os_become_must_be_active();
X	trace_string(a->str_text);
X	trace_string(b->str_text);
X	if (glue_rename(a->str_text, b->str_text))
X		nfatal("rename(\"%s\", \"%s\")", a->str_text, b->str_text);
X	trace((/*{*/"}\n"));
X}
X
Xvoid
Xos_unlink(path)
X	string_ty	*path;
X{
X	struct stat	st;
X
X	trace(("os_unlink(path = %08lX)\n{\n"/*}*/, path));
X	os_become_must_be_active();
X	trace_string(path->str_text);
X
X	/*
X	 * We must check that we are not unlinking a directory,
X	 * because we are set-uid-root, and root can unlink directories!
X	 */
X#ifdef S_IFLNK
X	if (glue_lstat(path->str_text, &st))
X		nfatal("lstat(\"%s\")", path->str_text);
X#else
X	if (glue_stat(path->str_text, &st))
X		nfatal("stat(\"%s\")", path->str_text);
X#endif
X	if ((st.st_mode & S_IFMT) == S_IFDIR)
X		fatal("unlink(\"%s\"): is a directory", path->str_text);
X	if (glue_unlink(path->str_text))
X		nfatal("unlink(\"%s\")", path->str_text);
X	trace((/*{*/"}\n"));
X}
X
Xvoid
Xos_unlink_errok(path)
X	string_ty	*path;
X{
X	struct stat	st;
X
X	trace(("os_unlink_errok(path = %08lX)\n{\n"/*}*/, path));
X	os_become_must_be_active();
X	trace_string(path->str_text);
X
X	/*
X	 * We must check that we are not unlinking a directory,
X	 * because we are set-uid-root, and root can unlink directories!
X	 */
X#ifdef S_IFLNK
X	if (glue_lstat(path->str_text, &st))
X	{
X		if (errno != ENOENT)
X			nfatal("lstat(\"%s\")", path->str_text);
X		nerror("warning: lstat(\"%s\")", path->str_text);
X		goto done;
X	}
X#else
X	if (glue_stat(path->str_text, &st))
X	{
X		if (errno != ENOENT)
X			nfatal("stat(\"%s\")", path->str_text);
X		nerror("warning: stat(\"%s\")", path->str_text);
X		goto done;
X	}
X#endif
X	if ((st.st_mode & S_IFMT) == S_IFDIR)
X	{
X		error
X		(
X		 "warning: unlink(\"%s\"): is a directory, no action performed",
X			path->str_text
X		);
X		goto done;
X	}
X	if (glue_unlink(path->str_text))
X		nerror("warning: unlink(\"%s\")", path->str_text);
X
X	/*
X	 * here for all exits
X	 */
X	done:
X	trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X *	os_curdir_sub - get current directory
X *
X * SYNOPSIS
X *	string_ty *os_curdir_sub(void);
X *
X * DESCRIPTION
X *	The os_curdir_sub function is used to determine the system's idea
X *	of the current directory.
X *
X * RETURNS
X *	A pointer to a string in dynamic memory is returned.
X *	A null pointer is returned on error.
X *
X * CAVEAT
X *	DO NOT use str_free() on the value returned.
X */
X
Xstatic string_ty *os_curdir_sub _((void));
X
Xstatic string_ty *
Xos_curdir_sub()
X{
X	static string_ty	*s;
X
X	os_become_must_be_active();
X	if (!s)
X	{
X		char	buffer[2000];
X
X		if (!glue_getcwd(buffer, sizeof(buffer)))
X			nfatal("getcwd");
X		assert(buffer[0] == '/');
X		s = str_from_c(buffer);
X	}
X	return s;
X}
X
X
X/*
X * NAME
X *	os_curdir - full current directory path
X *
X * SYNOPSIS
X *	string_ty *os_curdir(void);
X *
X * DESCRIPTION
X *	Os_curdir is used to determine the pathname
X *	of the current directory.  Automounter vaguaries will be elided.
X *
X * RETURNS
X *	A pointer to a string in dynamic memory is returned.
X *	A null pointer is returned on error.
X *
X * CAVEAT
X *	Use str_free() when you are done with the value returned.
X */
X
Xstring_ty *
Xos_curdir()
X{
X	static string_ty	*result;
X
X	os_become_must_be_active();
X	if (!result)
X	{
X		string_ty	*dot;
X		
X		dot = str_from_c(".");
X		result = os_pathname(dot, 1);
X		str_free(dot);
X	}
X	return str_copy(result);
X}
X
X
X/*
X * NAME
X *	os_pathname - determine full file name
X *
X * SYNOPSIS
X *	string_ty *os_pathname(string_ty *path, int resolve);
X *
X * DESCRIPTION
X *	Os_pathname is used to determine the full path name
X *	of a partial path given.
X *
X * ARGUMENTS
X *	path	- path to canonicalize
X *	resolve	- non-zero if should resolve symlinks, 0 if not
X *
X * RETURNS
X *	pointer to dynamically allocated string.
X *
X * CAVEAT
X *	Use str_free() when you are done with the value returned.
X */
X
Xstring_ty *
Xos_pathname(path, resolve)
X	string_ty	*path;
X	int		resolve;
X{
X	static char	*tmp;
X	static size_t	tmplen;
X	static size_t	ipos;
X	static size_t	opos;
X	int		c;
X	int		found;
X#ifdef S_IFLNK
X	wlist		loop;
X#endif
X
X	/*
X	 * Change relative pathnames to absolute
X	 */
X	trace(("os_pathname(path = %08lX)\n{\n"/*}*/, path));
X	if (resolve)
X		os_become_must_be_active();
X	trace_string(path->str_text);
X	if (path->str_text[0] != '/')
X		path = str_format("%S/%S", os_curdir_sub(), path);
X	else
X		path = str_copy(path);
X	if (!tmp)
X	{
X		tmplen = 200;
X		tmp = mem_alloc(tmplen);
X	}
X
X	/*
X	 * Take kinks out of the pathname
X	 */
X	ipos = 0;
X	opos = 0;
X	found = 0;
X#ifdef S_IFLNK
X	wl_zero(&loop);
X#endif
X	while (!found)
X	{
X		/*
X		 * get the next character
X		 */
X		c = path->str_text[ipos];
X		if (c)
X			ipos++;
X		else
X		{
X			found = 1;
X			c = '/';
X		}
X
X		/*
X		 * remember the normal characters
X		 * until get to slash
X		 */
X		if (c != '/')
X			goto remember;
X
X		/*
X		 * leave root alone
X		 */
X		if (!opos)
X			goto remember;
X
X		/*
X		 * "/.." -> "/"
X		 */
X		if (opos == 3 && tmp[1] == '.' && tmp[2] == '.')
X		{
X			opos = 1;
X			continue;
X		}
X
X		/*
X		 * "a//" -> "a/"
X		 */
X		if (tmp[opos - 1] == '/')
X			continue;
X
X		/*
X		 * "a/./" -> "a/"
X		 */
X		if (opos >= 2 && tmp[opos - 1] == '.' && tmp[opos - 2] == '/')
X		{
X			opos--;
X			continue;
X		}
X
X		/*
X		 * "a/b/../" -> "a/"
X		 */
X		if
X		(
X			opos > 3
X		&&
X			tmp[opos - 1] == '.'
X		&&
X			tmp[opos - 2] == '.'
X		&&
X			tmp[opos - 3] == '/'
X		)
X		{
X			opos -= 4;
X			assert(opos > 0);
X			while (tmp[opos - 1] != '/')
X				opos--;
X			continue;
X		}
X
X		/*
X		 * see if the path so far is a symbolic link
X		 */
X#ifdef S_IFLNK
X		if (resolve)
X		{
X			char		link[2000];
X			int		nbytes;
X			string_ty	*s;
X
X			s = str_n_from_c(tmp, opos);
X			if (wl_member(&loop, s))
X			{
X				fatal
X				(
X					"symbolic link loop \"%s\" detected",
X					s->str_text
X				);
X			}
X			nbytes = glue_readlink(s->str_text, link, sizeof(link) - 1);
X			if (nbytes < 0)
X			{
X				/*
X				 * probably not a symbolic link
X				 */
X				if
X				(
X					errno != ENXIO
X				&&
X					errno != EINVAL
X				&& 
X					errno != ENOENT
X				)
X					nfatal("readlink(\"%s\")", s->str_text);
X				str_free(s);
X			}
X			else
X			{
X				string_ty	*newpath;
X	
X				if (nbytes == 0)
X				{
X					fatal
X					(
X					       "readlink(\"%s\") returned \"\"",
X						s->str_text
X					);
X				}
X				link[nbytes] = 0;
X	
X				wl_append(&loop, s);
X				str_free(s);
X				if (link[0] == '/')
X					tmp[1] = 0;
X				else
X				{
X					while (tmp[opos - 1] != '/')
X						opos--;
X					tmp[opos] = 0;
X				}
X				newpath =
X					str_format
X					(
X						"%s/%s/%s",
X						tmp,
X						link,
X						path->str_text + ipos
X					);
X				str_free(path);
X				path = newpath;
X				ipos = 0;
X				opos = 0;
X				found = 0;
X				continue;
X			}
X		}
X#endif
X	
X		/*
X		 * keep the slash
X		 */
X		remember:
X		if (opos >= tmplen)
X		{
X			tmplen += 100;
X			mem_change_size(&tmp, tmplen);
X		}
X		tmp[opos++] = c;
X	}
X#ifdef S_IFLNK
X	wl_free(&loop);
X#endif
X	str_free(path);
X	assert(opos >= 1);
X	assert(tmp[0] == '/');
X	assert(tmp[opos - 1] == '/');
X	if (opos >= 2)
X		opos--;
X	path = str_n_from_c(tmp, opos);
X	trace_string(path->str_text);
X	trace((/*{*/"}\n"));
X	return path;
X}
X
X
X/*
X * NAME
X *	os_entryname - take path apart
X *
X * SYNOPSIS
X *	string_ty *os_entryname(string_ty *path);
X *
X * DESCRIPTION
X *	Os_entryname is used to extract the entry part
X *	from a pathname.
X *
X * RETURNS
X *	pointer to dynamically allocated string.
X *
X * CAVEAT
X *	Use str_free() when you are done with the return value.
X */
X
Xstring_ty *
Xos_entryname(path)
X	string_ty	*path;
X{
X	string_ty	*s;
X	char		*cp;
X
X	trace(("os_entryname(path = %08lX)\n{\n"/*}*/, path));
X	trace_string(path->str_text);
X	s = os_pathname(path, 1);
X	cp = strrchr(s->str_text, '/');
X	if (cp && s->str_length > 1)
X		path = str_from_c(cp + 1);
X	else
X		path = str_copy(s);
X	str_free(s);
X	trace_string(path->str_text);
X	trace((/*{*/"}\n"));
X	return path;
X}
X
X
X/*
X * NAME
X *	os_dirname - take path apart
X *
X * SYNOPSIS
X *	string_ty *os_dirname(string_ty *path);
X *
X * DESCRIPTION
X *	Os_dirname is used to extract the directory part
X *	of a pathname.
X *
X * RETURNS
X *	pointer to dynamically allocated string.
X *
X * CAVEAT
X *	Use str_free() when you are done with the value returned.
X */
X
Xstring_ty *
Xos_dirname(path)
X	string_ty	*path;
X{
X	string_ty	*s;
X	char		*cp;
X
X	trace(("os_dirname(path = %08lX)\n{\n"/*}*/, path));
X	trace_string(path->str_text);
X	s = os_pathname(path, 1);
X	cp = strrchr(s->str_text, '/');
X	assert(cp);
X	if (cp > s->str_text)
X	{
X		path = str_n_from_c(s->str_text, cp - s->str_text);
X		str_free(s);
X	}
X	else
X		path = s;
X	trace_string(path->str_text);
X	trace((/*{*/"}\n"));
X	return path;
X}
X
X
Xstring_ty *
Xos_below_dir(higher, lower)
X	string_ty	*higher;
X	string_ty	*lower;
X{
X	char		*s1;
X	char		*s2;
X
X	s1 = higher->str_text;
X	s2 = lower->str_text;
X	while (*s1 == *s2 && *s1)
X		s1++, s2++;
X	if (*s1)
X		return 0;
X	if (!*s2)
X		return str_from_c("");
X	if (*s2 != '/')
X		return 0;
X	return str_from_c(s2 + 1);
X}
X
X
Xvoid
Xos_chdir(path)
X	string_ty	*path;
X{
X	os_become_must_not_be_active();
X	if (chdir(path->str_text))
X		nfatal("chdir(\"%s\")", path->str_text);
X}
X
X
Xvoid
Xos_setuid(uid)
X	int		uid;
X{
X	os_become_must_not_be_active();
X	if (setuid(uid))
X		nfatal("setuid(%d)", uid);
X}
X
X
Xvoid
Xos_setgid(gid)
X	int		gid;
X{
X	os_become_must_not_be_active();
X	if (setgid(gid))
X		nfatal("setgid(%d)", gid);
X}
X
X
Xvoid
Xos_execute(cmd, flags, dir)
X	string_ty	*cmd;
X	int		flags;
X	string_ty	*dir;
X{
X	int		result;
X
X	trace(("os_execute()\n{\n"/*}*/));
X	result = os_execute_retcode(cmd, flags, dir);
X	if (result)
X	{
X		string_ty	*s;
X
X		if (cmd->str_length > MAX_CMD_RPT)
X			s = str_format("%.*S...", MAX_CMD_RPT - 3, cmd);
X		else
X			s = str_copy(cmd);
X		fatal("command \"%s\" exit status: %d", s->str_text, result);
X		str_free(s);
X	}
X	trace((/*{*/"}\n"));
X}
X
X
Xint
Xos_execute_retcode(cmd, flags, dir)
X	string_ty	*cmd;
X	int		flags;
X	string_ty	*dir;
X{
X	int		uid;
X	int		gid;
X	int		um;
X	int		child;
X	int		result = 0;
X	static char	dev_null[] = "/dev/null";
X	void		(*hold)_((int));
X	string_ty	*cmd2;
X	char		*shell;
X
X	trace(("os_execute_retcode()\n{\n"/*}*/));
X	os_become_must_be_active();
X	os_become_query(&uid, &gid, &um);
X	if (cmd->str_length > MAX_CMD_RPT)
X		cmd2 = str_format("%.*S...", MAX_CMD_RPT - 3, cmd);
X	else
X		cmd2 = str_copy(cmd);
X
X	/*
X	 * fork to get a process to do the command
X	 */
X	switch (child = fork())
X	{
X	case -1:
X		nfatal("fork");
X
X	default:
X		/*
X		 * The parent process waits
X		 */
X		interrupted = 0;
X		hold = signal(SIGINT, SIG_IGN);
X		if (hold != SIG_IGN)
X			signal(SIGINT, interrupt);
X		result = os_waitpid_status(child, cmd2->str_text);
X		break;
X
X	case 0:
X		/*
X		 * become the user for real
X		 */
X		while (os_become_active())
X			os_become_undo();
X		undo_cancel();
X		os_setgid(gid);
X		os_setuid(uid);
X		umask(um);
X
X		/*
X		 * change directory to the appropriate directory.
X		 */
X		os_chdir(dir);
X
X		/*
X		 * Redirect stdin from /dev/null.
X		 * (Don't redirect stdin if not logging, for manual tests.)
X		 */
X		if
X		(
X			!(flags & OS_EXEC_FLAG_INPUT)
X		&&
X			!freopen(dev_null, "r", stdin)
X		)
X			nfatal("open(\"%s\")", dev_null);
X
X		/*
X		 * let the log file (user) know what we did
X		 */
X		error("%s", cmd->str_text);
X
X		/*
X		 * invoke the command through sh(1)
X		 */
X		shell = os_shell();
X		execl(shell, shell, "-ec", cmd->str_text, (char *)0);
X		nfatal("exec(\"%s\")", shell);
X	}
X	if (result && (flags & OS_EXEC_FLAG_ERROK))
X	{
X		error
X		(
X			"warning: command \"%s\" exit status %d",
X			cmd2->str_text,
X			result
X		);
X		result = 0;
X	}
X	str_free(cmd2);
X	trace(("return %d;\n", result));
X	trace((/*{*/"}\n"));
X	return result;
X}
X
X
Xtime_t
Xos_mtime(path)
X	string_ty	*path;
X{
X	struct stat	statbuf;
X	time_t		result;
X
X	trace(("os_mtime(path = %08lX)\n{\n"/*}*/, path));
X	os_become_must_be_active();
X	trace_string(path->str_text);
X
X	if (glue_stat(path->str_text, &statbuf))
X		nfatal("stat(\"%s\")", path->str_text);
X
X	/*
X	 * Return the last modified time.
X	 * They may try to fake us out by using utime,
X	 * so check the inode change time, too.
X	 */
X	if (statbuf.st_ctime > statbuf.st_mtime)
X		result = statbuf.st_ctime;
X	else
X		result = statbuf.st_mtime;
X	trace(("return %s", ctime(&result)));
X	trace((/*{*/"}\n"));
X	return result;
X}
X
X
Xvoid
Xos_mtime_set(path, when)
X	string_ty	*path;
X	time_t		when;
X{
X	struct utimbuf	utb;
X
X	trace(("os_mtime_set(path = %08lX, when = %ld)\n{\n"/*}*/, path, when));
X	os_become_must_be_active();
X	trace_string(path->str_text);
X	trace(("when = %s", ctime(&when)));
X	utb.actime = when;
X	utb.modtime = when;
X	if (glue_utime(path->str_text, &utb))
X		nfatal("utime(\"%s\")", path->str_text);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_chown_check(path, mode, uid, gid)
X	string_ty	*path;
X	int		mode;
X	int		uid;
X	int		gid;
X{
X	struct stat	st;
X	int		nerrs;
X
X	trace(("os_chown_check(path = \"%s\")\n{\n"/*}*/, path->str_text));
X	os_become_must_be_active();
X	nerrs = 0;
X	if (glue_stat(path->str_text, &st))
X		nfatal("stat(\"%s\")", path->str_text);
X	if (os_testing_mode())
X	{
X		if ((st.st_mode & 07777) != mode)
X		{
X			error
X			(
X				"%s: mode is %05o, should be %05o",
X				path->str_text,
X				st.st_mode & 07777,
X				mode
X			);
X			++nerrs;
X		}
X		if (st.st_uid != geteuid())
X		{
X			error
X			(
X				"%s: owner is %d, should be %d",
X				path->str_text,
X				st.st_uid,
X				geteuid()
X			);
X			++nerrs;
X		}
X	}
X	else
X	{
X		if ((st.st_mode & 07777) != mode)
X		{
X			error
X			(
X				"%s: mode is %05o, should be %05o",
X				path->str_text,
X				st.st_mode & 07777,
X				mode
X			);
X			++nerrs;
X		}
X		if (st.st_uid != uid)
X		{
X			error
X			(
X				"%s: owner is %d, should be %d",
X				path->str_text,
X				st.st_uid,
X				uid
X			);
X			++nerrs;
X		}
X		if (st.st_gid != gid)
X		{
X			error
X			(
X				"%s: group is %d, should be %d",
X				path->str_text,
X				st.st_gid,
X				gid
X			);
X			++nerrs;
X		}
X	}
X	if (nerrs)
X		fatal("%s: has been tampered with (fatal)", path->str_text);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_chmod(path, mode)
X	string_ty	*path;
X	int		mode;
X{
X	trace(("os_chmod(path = \"%s\", mode = 0%o)\n{\n"/*}*/,
X		path->str_text, mode));
X	mode &= 07777;
X	os_become_must_be_active();
X	if (glue_chmod(path->str_text, mode))
X		nfatal("chmod(\"%s\", 0%o)", path->str_text, mode);
X	trace((/*{*/"}\n"));
X}
X
X
Xint
Xos_chmod_query(path)
X	string_ty	*path;
X{
X	int		mode;
X	struct stat	st;
X
X	trace(("os_chmod_query(path = \"%s\")\n{\n"/*}*/, path->str_text));
X	os_become_must_be_active();
X	if (glue_stat(path->str_text, &st))
X		nfatal("stat(\"%s\")", path->str_text);
X	mode = st.st_mode & 07777;
X	trace(("return %05o;\n", mode));
X	trace((/*{*/"}\n"));
X	return mode;
X}
X
X
Xvoid
Xos_chmod_errok(path, mode)
X	string_ty	*path;
X	int		mode;
X{
X	trace(("os_chmod_errok(path = \"%s\", mode = 0%o)\n{\n"/*}*/,
X		path->str_text, mode));
X	os_become_must_be_active();
X	mode &= 07777;
X	if (glue_chmod(path->str_text, mode))
X		nerror("warning: chmod(\"%s\", 0%o)", path->str_text, mode);
X	trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xos_link(from, to)
X	string_ty	*from;
X	string_ty	*to;
X{
X	trace(("os_link(from = %08lX, to = %08lX)\n{\n"/*}*/, from, to));
X	os_become_must_be_active();
X	trace_string(from->str_text);
X	trace_string(to->str_text);
X	if (glue_link(from->str_text, to->str_text))
X		nfatal("link(\"%s\", \"%s\")", from->str_text, to->str_text);
X	trace((/*{*/"}\n"));
X}
X
X
Xstring_ty *
Xos_execute_slurp(cmd, flags, dir)
X	string_ty	*cmd;
X	int		flags;
X	string_ty	*dir;
X{
X	string_ty	*s1;
X	string_ty	*s2;
X
X	trace(("os_execute_slurp()\n{\n"/*}*/));
X	s1 = os_edit_filename();
X	trace_string(s1->str_text);
X	s2 = str_format("( %S ) > %S", cmd, s1);
X	os_execute(s2, flags, dir);
X	str_free(s2);
X	s2 = read_whole_file(s1->str_text);
X	os_unlink(s1);
X	str_free(s1);
X	trace_string(s2->str_text);
X	trace((/*{*/"}\n"));
X	return s2;
X}
X
X
Xstatic	int	become_orig_uid;
Xstatic	int	become_orig_gid;
Xstatic	int	become_orig_umask;
Xstatic	int	become_inited;
Xstatic	int	become_testing;
Xstatic	int	become_active;
Xstatic	int	become_active_uid;
Xstatic	int	become_active_gid;
Xstatic	int	become_active_umask;
X
X
Xstatic void whoami _((int *, int *));
X
Xstatic void
Xwhoami(uid, gid)
X	int	*uid;
X	int	*gid;
X{
X	*uid = become_active_uid;
X	*gid = become_active_gid;
X}
X
X
Xvoid
Xos_become_init()
X{
X	assert(!become_inited);
X	error_set_id_func(whoami);
X	become_active_umask = DEFAULT_UMASK;
X	become_orig_umask = umask(DEFAULT_UMASK);
X	become_orig_uid = getuid();
X	become_orig_gid = getgid();
X	if (setuid(0))
X	{
X		become_testing = 1;
X		become_active_uid = become_orig_uid;
X		become_active_gid = become_orig_gid;
X	}
X	else
X		setgid(0);
X	become_inited = 1;
X}
X
X
Xint
Xos_testing_mode()
X{
X	static int warned;
X
X	assert(become_inited);
X	if (!become_testing)
X		return 0;
X	if (!warned)
X	{
X		warned = 1;
X		verbose
X		(
X"warning: \
XThis copy is running in \"test\" mode.  \
XIt has reduced capabilities due to reduced privileges.  \
XThis mode is provided solely for testing, \
Xand is not a recommended operating mode."
X		);
X	}
X	return 1;
X}
X
X
Xvoid
Xos_become(uid, gid, um)
X	int	uid;
X	int	gid;
X	int	um;
X{
X	if (become_active)
X		fatal("multiple user permissions set (bug)");
X	become_active = 1;
X	if (os_testing_mode())
X		return;
X	become_active_uid = uid;
X	become_active_gid = gid;
X	become_active_umask = um;
X#ifndef CONF_NO_seteuid
X	if (setegid(gid))
X		nfatal("setegid(%d)", gid);
X	if (seteuid(uid))
X		nfatal("seteuid(%d)", uid);
X	umask(um);
X#endif
X}
X
X
Xvoid
Xos_become_undo()
X{
X	os_become_must_be_active();
X	assert(become_inited);
X	become_active = 0;
X	if (become_testing)
X		return;
X#ifndef CONF_NO_seteuid
X	if (seteuid(0))
X		nfatal("seteuid(0)");
X	if (setegid(0))
X		nfatal("setegid(0)");
X#endif
X	become_active_uid = 0;
X	become_active_gid = 0;
X}
X
X
Xvoid
Xos_become_orig()
X{
X	os_become(become_orig_uid, become_orig_gid, become_orig_umask);
X}
X
X
Xvoid
Xos_become_query(uid, gid, umask)
X	int	*uid;
X	int	*gid;
X	int	*umask;
X{
X	os_become_must_be_active();
X	*uid = become_active_uid;
X	if (gid)
X		*gid = become_active_gid;
X	if (umask)
X		*umask = become_active_umask;
X}
X
X
Xvoid
Xos_become_orig_query(uid, gid, umask)
X	int	*uid;
X	int	*gid;
X	int	*umask;
X{
X	*uid = become_orig_uid;
X	if (gid)
X		*gid = become_orig_gid;
X	if (umask)
X		*umask = become_orig_umask;
X}
X
X
Xint
Xos_become_active()
X{
X	return become_active;
X}
X
X
Xvoid
Xos_become_must_be_active_gizzards(file, line)
X	char	*file;
X	int	line;
X{
X	if (!os_become_active())
X		fatal("%s: %d: user permissions not set (bug)", file, line);
X}
X
X
Xvoid
Xos_become_must_not_be_active_gizzards(file, line)
X	char	*file;
X	int	line;
X{
X	if (os_become_active())
X	{
X		fatal
X		(
X			"%s: %d: user permissions set when aught not (bug)",
X			file,
X			line
X		);
X	}
X}
X
X
X#ifdef SIGSTOP
X#ifdef CONF_NO_tcgetpgrp
X
X#include <sys/termio.h>
X
Xint
Xtcgetpgrp(fd)
X	int		fd;
X{
X	int		result;
X
X#ifdef TIOCGETPGRP
X	if (ioctl(fd, TIOCGETPGRP, &result))
X		result = -1;
X#else
X#ifdef TIOCGPGRP
X        if (ioctl(fd, TIOCGPGRP, &result))
X		result = -1;
X#else
X	result = -1;
X#endif
X#endif
X	return result;
X}
X
X#endif /* CONF_NO_tcgetpgrp */
X#endif /* SIGSTOP */
X
X
X/*
X *  NAME
X *	  background - test for backgroundness
X *
X *  SYNOPSIS
X *	  int background(void);
X *
X *  DESCRIPTION
X *	  The background function is used to determin e if the curent process is
X *	  in the background.
X *
X *  RETURNS
X *	  int: zero if process is not in the background, nonzero if the process
X *	  is in the background.
X *
X * CAVEAT:
X *	This function has a huge chance of being wrong for your system.
X *	If you need to modify this function, please let the author know.
X */
X
Xint
Xos_background()
X{
X	void	(*x)_((int));
X
X	/*
X	 * C shell
X	 *	puts its children in a different process group.
X	 *	The process group the terminal in is the forground.
X	 *
X	 * Only available on systems with job control.
X	 */
X#ifdef SIGSTOP
X	if (getpgrp(CONF_getpgrp_arg) != tcgetpgrp(0))
X		return 1;
X#endif
X
X	/*
X	 * Bourne shell
X	 *	sets its children to ignore SIGINT
X	 */
X	x = signal(SIGINT, SIG_IGN);
X	if (x == SIG_IGN)
X		return 1;
X	signal(SIGINT, x);
X
X	/*
X	 * probably forground
X	 */
X	return 0;
X}
X
X
Xint
Xos_readable(path)
X	string_ty	*path;
X{
X	os_become_must_be_active();
X	if (glue_access(path->str_text, R_OK))
X		return errno;
X	return 0;
X}
X
X
Xint
Xos_waitpid(child, status_p)
X	int		child;
X	int		*status_p;
X{
X	typedef struct ret_ty ret_ty;
X	struct ret_ty
X	{
X		int	pid;
X		int	status;
X	};
X
X	static long	nret;
X	static long	nret_max;
X	static ret_ty	*ret;
X	int		pid;
X	int		status;
X	int		j;
X	int		result;
X
X	/*
X	 * see if we already have it
X	 */
X	trace(("os_waitpid(child = %d)\n{\n"/*}*/, child));
X	assert(child > 0);
X	result = 0;
X	for (j = 0; j < nret; ++j)
X	{
X		if (ret[j].pid != child)
X			continue;
X		*status_p = ret[j].status;
X		ret[j] = ret[--nret];
X		goto done;
X	}
X
X	/*
X	 * new one, go hunting
X	 */
X	for (;;)
X	{
X		/*
X		 * block until a child terminates,
X		 * or there are no more children
X		 */
X		pid = wait(&status);
X		if (pid == -1)
X		{
X			if (errno == EINTR)
X				continue;
X			result = -1;
X			break;
X		}
X
X		/*
X		 * stop if this is the child
X		 * we are looking for
X		 */
X		if (pid == child)
X		{
X			*status_p = status;
X			break;
X		}
X
X		/*
X		 * remember and keep going
X		 */
X		if (nret >= nret_max)
X		{
X			long	nbytes;
X
X			nret_max += 11;
X			nbytes = nret_max * sizeof(ret_ty);
X			if (!ret)
X				ret = (ret_ty *)mem_alloc(nbytes);
X			else
X				mem_change_size((char **)&ret, nbytes);
X		}
X		ret[nret].pid = pid;
X		ret[nret].status = status;
X		++nret;
X	}
X
X	/*
X	 * here for all exits
X	 */
X	done:
X	trace(("return %d;\n", result));
X	trace((/*{*/"}\n"));
X	return result;
X}
X
X
Xchar *
Xos_shell()
X{
X	static char shell[] = CONF_SHELL;
X
X	assert(shell[0] == '/');
X	return shell;
X}
X
X
Xvoid
Xos_edit(filename)
X	string_ty	*filename;
X{
X	string_ty	*cmd;
X	string_ty	*cwd;
X	char		*editor;
X
X	/*
X	 * make sure we are in a position to edit
X	 */
X	if (os_background())
X		fatal("may not use -Edit in the background");
X
X	/*
X	 * find the editor to use
X	 */
X	editor = getenv("EDITOR");
X	if (!editor)
X		editor = "vi";
X
X	/*
X	 * edit the file
X	 */
X	cmd = str_format("%s %S", editor, filename);
X	cwd = os_curdir();
X	assert(cwd);
X	os_execute(cmd, OS_EXEC_FLAG_INPUT | OS_EXEC_FLAG_ERROK, cwd);
X	str_free(cmd);
X	str_free(cwd);
X}
X
X
Xstring_ty *
Xos_edit_new()
X{
X	string_ty	*filename;
X	string_ty	*result;
X	FILE		*fp;
X
X	filename = os_edit_filename();
X	os_become_orig();
X	fp = glue_fopen(filename->str_text, "w");
X	if (!fp)
X		fatal("create %s", filename->str_text);
X	glue_fclose(fp);
X	os_edit(filename);
X	result = read_whole_file(filename->str_text);
X	os_unlink(filename);
X	os_become_undo();
X	return result;
X}
X
X
Xstring_ty *
Xos_edit_filename()
X{
X	static int num;
X	char buffer[20];
X
X	sprintf(buffer, "%d-%d", getpid(), ++num);
X	return
X		str_format
X		(
X			"/tmp/%.*s-%s",
X			13 - (int)strlen(buffer),
X			option_progname_get(),
X			buffer
X		);
X}
END_OF_FILE
if test 27024 -ne `wc -c <'aegis/os.c'`; then
    echo shar: \"'aegis/os.c'\" unpacked with wrong size!
fi
# end of 'aegis/os.c'
fi
if test -f 'aux/CHANGES.1.2' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'aux/CHANGES.1.2'\"
else
echo shar: Extracting \"'aux/CHANGES.1.2'\" \(25416 characters\)
sed "s/^X//" >'aux/CHANGES.1.2' <<'END_OF_FILE'
XChange	State		Description
X------- -------		-------------
X1	completed	New release derived from aegis.1.1.
X2	completed	add more to user guide
X3	completed	change tests to use 'test' rather than '[...]'
X4	completed	add configuration for varargs
X5	completed	make it more C standard conforming
X6	completed	make os_pathname understand symbolic links
X7	completed	more tinkering for the convex
X8	completed	add new file templates
X9	being_		document file templates
X	integrated
X
XIDENTIFICATION
X	Project "aegis.1.2", change 1.
X
XSUMMARY
X	New release derived from aegis.1.1.
X
XDESCRIPTION
X	New release derived from aegis.1.1.
X
XCAUSE
X	internal_enhancement
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	create	1	ALPHA.NOTICE
X	source	create	1	CHANGES.sh
X	source	create	1	COPYING
X	source	create	1	Howto.cook
X	source	create	1	Makefile.awk
X	source	create	1	Makefile.sh
X	source	create	1	README
X	source	create	1	aegis/administ.c
X	source	create	1	aegis/administ.h
X	source	create	1	aegis/archaeol.c
X	source	create	1	aegis/archaeol.h
X	source	create	1	aegis/arglex.c
X	source	create	1	aegis/arglex.h
X	source	create	1	aegis/build.c
X	source	create	1	aegis/build.h
X	source	create	1	aegis/cattr.def
X	source	create	1	aegis/cattr_ed.c
X	source	create	1	aegis/cattr_ed.h
X	source	create	1	aegis/change.c
X	source	create	1	aegis/change.h
X	source	create	1	aegis/chdir.c
X	source	create	1	aegis/chdir.h
X	source	create	1	aegis/col.c
X	source	create	1	aegis/col.h
X	source	create	1	aegis/commit.c
X	source	create	1	aegis/commit.h
X	source	create	1	aegis/common.def
X	source	create	1	aegis/copyfile.c
X	source	create	1	aegis/copyfile.h
X	source	create	1	aegis/cstate.def
X	source	create	1	aegis/defaults.c
X	source	create	1	aegis/defaults.h
X	source	create	1	aegis/develop1.c
X	source	create	1	aegis/develop1.h
X	source	create	1	aegis/develop2.c
X	source	create	1	aegis/develop2.h
X	source	create	1	aegis/diff.c
X	source	create	1	aegis/diff.h
X	source	create	1	aegis/dir.c
X	source	create	1	aegis/dir.h
X	source	create	1	aegis/error.c
X	source	create	1	aegis/error.h
X	source	create	1	aegis/file.c
X	source	create	1	aegis/file.h
X	source	create	1	aegis/gate.h
X	source	create	1	aegis/gonzo.c
X	source	create	1	aegis/gonzo.h
X	source	create	1	aegis/gram.y
X	source	create	1	aegis/gstate.def
X	source	create	1	aegis/help.c
X	source	create	1	aegis/help.h
X	source	create	1	aegis/indent.c
X	source	create	1	aegis/indent.h
X	source	create	1	aegis/integra1.c
X	source	create	1	aegis/integra1.h
X	source	create	1	aegis/integra2.c
X	source	create	1	aegis/integra2.h
X	source	create	1	aegis/io.c
X	source	create	1	aegis/io.h
X	source	create	1	aegis/lex.c
X	source	create	1	aegis/lex.h
X	source	create	1	aegis/list.c
X	source	create	1	aegis/list.h
X	source	create	1	aegis/lock.c
X	source	create	1	aegis/lock.h
X	source	create	1	aegis/log.c
X	source	create	1	aegis/log.h
X	source	create	1	aegis/main.c
X	source	create	1	aegis/mem.c
X	source	create	1	aegis/mem.h
X	source	create	1	aegis/new_chan.c
X	source	create	1	aegis/new_chan.h
X	source	create	1	aegis/new_file.c
X	source	create	1	aegis/new_file.h
X	source	create	1	aegis/new_proj.c
X	source	create	1	aegis/new_proj.h
X	source	create	1	aegis/new_rele.c
X	source	create	1	aegis/new_rele.h
X	source	create	1	aegis/new_test.c
X	source	create	1	aegis/new_test.h
X	source	create	1	aegis/option.c
X	source	create	1	aegis/option.h
X	source	create	1	aegis/os.c
X	source	create	1	aegis/os.h
X	source	create	1	aegis/parse.c
X	source	create	1	aegis/parse.h
X	source	create	1	aegis/pattr.def
X	source	create	1	aegis/pattr_ed.c
X	source	create	1	aegis/pattr_ed.h
X	source	create	1	aegis/pconf.def
X	source	create	1	aegis/project.c
X	source	create	1	aegis/project.h
X	source	create	1	aegis/pstate.def
X	source	create	1	aegis/rem_file.c
X	source	create	1	aegis/rem_file.h
X	source	create	1	aegis/review.c
X	source	create	1	aegis/review.h
X	source	create	1	aegis/reviewer.c
X	source	create	1	aegis/reviewer.h
X	source	create	1	aegis/str.c
X	source	create	1	aegis/str.h
X	source	create	1	aegis/sub.c
X	source	create	1	aegis/sub.h
X	source	create	1	aegis/test.c
X	source	create	1	aegis/test.h
X	source	create	1	aegis/trace.c
X	source	create	1	aegis/trace.h
X	source	create	1	aegis/tree.c
X	source	create	1	aegis/tree.h
X	source	create	1	aegis/type.c
X	source	create	1	aegis/type.h
X	source	create	1	aegis/uconf.def
X	source	create	1	aegis/undo.c
X	source	create	1	aegis/undo.h
X	source	create	1	aegis/user.c
X	source	create	1	aegis/user.h
X	source	create	1	aegis/ustate.def
X	source	create	1	aegis/version.c
X	source	create	1	aegis/version.h
X	source	create	1	aegis/word.c
X	source	create	1	aegis/word.h
X	source	create	1	common/ansi.c
X	source	create	1	common/main.h
X	source	create	1	conf/SunOS-4.1.2
X	source	create	1	conf/SysV-4.0
X	source	create	1	config
X	source	create	1	doc/aegis.mm
X	source	create	1	doc/build.man
X	source	create	1	doc/c1.0.so
X	source	create	1	doc/c1.1.so
X	source	create	1	doc/c1.2.so
X	source	create	1	doc/c1.3.so
X	source	create	1	doc/c2.0.so
X	source	create	1	doc/c2.1.so
X	source	create	1	doc/c2.2.so
X	source	create	1	doc/c2.3.so
X	source	create	1	doc/c2.4.so
X	source	create	1	doc/c3.0.so
X	source	create	1	doc/c4.0.so
X	source	create	1	doc/c5.0.so
X	source	create	1	doc/c6.0.so
X	source	create	1	doc/c7.0.so
X	source	create	1	doc/c7.1.so
X	source	create	1	doc/c7.2.so
X	source	create	1	doc/cA.0.so
X	source	create	1	dot.cshrc
X	source	create	1	dot.profile
X	source	create	1	fmtgen/arglex.c
X	source	create	1	fmtgen/arglex.h
X	source	create	1	fmtgen/error.c
X	source	create	1	fmtgen/error.h
X	source	create	1	fmtgen/id.c
X	source	create	1	fmtgen/id.h
X	source	create	1	fmtgen/indent.c
X	source	create	1	fmtgen/indent.h
X	source	create	1	fmtgen/lex.c
X	source	create	1	fmtgen/lex.h
X	source	create	1	fmtgen/main.c
X	source	create	1	fmtgen/mem.c
X	source	create	1	fmtgen/mem.h
X	source	create	1	fmtgen/parse.y
X	source	create	1	fmtgen/str.c
X	source	create	1	fmtgen/str.h
X	source	create	1	fmtgen/type.c
X	source	create	1	fmtgen/type.h
X	source	create	1	fmtgen/type_enum.c
X	source	create	1	fmtgen/type_integ.c
X	source	create	1	fmtgen/type_list.c
X	source	create	1	fmtgen/type_ref.c
X	source	create	1	fmtgen/type_strin.c
X	source	create	1	fmtgen/type_struc.c
X	source	create	1	fmtgen/word.c
X	source	create	1	fmtgen/word.h
X	source	create	1	h/stdarg.h
X	source	create	1	h/stddef.h
X	source	create	1	h/stdlib.h
X	source	create	1	man1/aea.1
X	source	create	1	man1/aeb.1
X	source	create	1	man1/aeca.1
X	source	create	1	man1/aecd.1
X	source	create	1	man1/aecp.1
X	source	create	1	man1/aecpu.1
X	source	create	1	man1/aed.1
X	source	create	1	man1/aedb.1
X	source	create	1	man1/aedbu.1
X	source	create	1	man1/aede.1
X	source	create	1	man1/aedeu.1
X	source	create	1	man1/aega.1
X	source	create	1	man1/aegis.1
X	source	create	1	man1/aeib.1
X	source	create	1	man1/aeibu.1
X	source	create	1	man1/aeif.1
X	source	create	1	man1/aeip.1
X	source	create	1	man1/ael.1
X	source	create	1	man1/aena.1
X	source	create	1	man1/aenc.1
X	source	create	1	man1/aencu.1
X	source	create	1	man1/aend.1
X	source	create	1	man1/aenf.1
X	source	create	1	man1/aenfu.1
X	source	create	1	man1/aeni.1
X	source	create	1	man1/aenpr.1
X	source	create	1	man1/aenrls.1
X	source	create	1	man1/aenrv.1
X	source	create	1	man1/aent.1
X	source	create	1	man1/aentu.1
X	source	create	1	man1/aepa.1
X	source	create	1	man1/aera.1
X	source	create	1	man1/aerd.1
X	source	create	1	man1/aerf.1
X	source	create	1	man1/aeri.1
X	source	create	1	man1/aerm.1
X	source	create	1	man1/aermu.1
X	source	create	1	man1/aerp.1
X	source	create	1	man1/aerpr.1
X	source	create	1	man1/aerpu.1
X	source	create	1	man1/aerrv.1
X	source	create	1	man1/aet.1
X	source	create	1	man1/aeua.1
X	source	create	1	man1/aev.1
X	source	create	1	man1/install.sh
X	source	create	1	man1/o__rules.so
X	source	create	1	man1/o_anticip.so
X	source	create	1	man1/o_auto.so
X	source	create	1	man1/o_baselin.so
X	source	create	1	man1/o_change.so
X	source	create	1	man1/o_devdir.so
X	source	create	1	man1/o_dir.so
X	source	create	1	man1/o_help.so
X	source	create	1	man1/o_indep.so
X	source	create	1	man1/o_keep.so
X	source	create	1	man1/o_lib.so
X	source	create	1	man1/o_list.so
X	source	create	1	man1/o_major.so
X	source	create	1	man1/o_manual.so
X	source	create	1	man1/o_min.so
X	source	create	1	man1/o_minor.so
X	source	create	1	man1/o_nolog.so
X	source	create	1	man1/o_overw.so
X	source	create	1	man1/o_page.so
X	source	create	1	man1/o_project.so
X	source	create	1	man1/o_terse.so
X	source	create	1	man1/o_verbose.so
X	source	create	1	man1/z_cr.so
X	source	create	1	man1/z_exit.so
X	source	create	1	man1/z_intuit.so
X	source	create	1	man1/z_name.so
X	source	create	1	man5/aecattr.5
X	source	create	1	man5/aecstate.5
X	source	create	1	man5/aedir.5
X	source	create	1	man5/aegis.5
X	source	create	1	man5/aegstate.5
X	source	create	1	man5/aepattr.5
X	source	create	1	man5/aepconf.5
X	source	create	1	man5/aepstate.5
X	source	create	1	man5/aeuconf.5
X	source	create	1	man5/aeustate.5
X	source	create	1	man5/install.sh
X	source	create	1	man5/z_cr.so
X	source	create	1	man5/z_name.so
X	source	create	1	notify/de.sh
X	source	create	1	notify/deu.sh
X	source	create	1	notify/if.sh
X	source	create	1	notify/ip.sh
X	source	create	1	notify/rf.sh
X	source	create	1	notify/rp.sh
X	source	create	1	notify/rpu.sh
X	test	create	1	test/00/t0001a.sh
X	test	create	1	test/00/t0002a.sh
X	test	create	1	test/00/t0003a.sh
X	test	create	1	test/00/t0004a.sh
X	test	create	1	test/00/t0005a.sh
X	test	create	1	test/00/t0006a.sh
X	test	create	1	test/00/t0007a.sh
X	test	create	1	test/00/t0008a.sh
X	test	create	1	test/00/t0009a.sh
X	test	create	1	test/00/t0010a.sh
X	test	create	1	test/00/t0011a.sh
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Fri Jun 19	pmiller Elapsed time: 0.000 days.
X			22:10:18 1992
X	develop_begin	Fri Jun 19	pmiller Elapsed time: 0.000 days.
X			22:10:18 1992
X	develop_end	Fri Jun 19	pmiller Elapsed time: 0.000 days.
X			22:10:18 1992
X	review_pass	Fri Jun 19	pmiller Elapsed time: 0.000 days.
X			22:10:18 1992
X	integrate_begin Fri Jun 19	pmiller Elapsed time: 0.031 days.
X			22:10:18 1992
X	integrate_pass	Fri Jun 19	pmiller
X			22:24:18 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 2, change 2.
X
XSUMMARY
X	add more to user guide
X
XDESCRIPTION
X	add more to user guide
X
XCAUSE
X	internal_enhancement
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	remove	1	ALPHA.NOTICE
X	source	modify	2	Howto.cook
X	source	remove	1	README
X	source	create	1	doc/ALPHA.man
X	source	create	1	doc/BUILDING.man
X	source	create	1	doc/README.man
X	source	remove	1	doc/aegis.mm
X	source	create	1	doc/aegis.ms
X	source	remove	1	doc/build.man
X	source	modify	2	doc/c1.0.so
X	source	modify	2	doc/c1.1.so
X	source	modify	2	doc/c1.2.so
X	source	modify	2	doc/c1.3.so
X	source	create	1	doc/c1.4.so
X	source	modify	2	doc/c2.0.so
X	source	modify	2	doc/c2.1.so
X	source	modify	2	doc/c2.2.so
X	source	modify	2	doc/c2.3.so
X	source	modify	2	doc/c2.4.so
X	source	modify	2	doc/c3.0.so
X	source	create	1	doc/c3.1.so
X	source	create	1	doc/c3.2.so
X	source	create	1	doc/c3.3.so
X	source	modify	2	doc/c4.0.so
X	source	modify	2	doc/c5.0.so
X	source	modify	2	doc/c6.0.so
X	source	modify	2	doc/c7.0.so
X	source	modify	2	doc/c7.1.so
X	source	modify	2	doc/c7.2.so
X	source	modify	2	doc/cA.0.so
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Mon Jun 22	pmiller Elapsed time: 0.001 days.
X			22:30:57 1992
X	develop_begin	Mon Jun 22	pmiller Elapsed time: 5.237 days.
X			22:31:15 1992
X	develop_end	Sun Jun 28	pmiller Elapsed time: 0.001 days.
X			00:17:59 1992
X	review_pass	Sun Jun 28	pmiller Elapsed time: 0.001 days.
X			00:18:20 1992
X	integrate_begin Sun Jun 28	pmiller Elapsed time: 0.000 days.
X			00:19:00 1992
X	integrate_pass	Sun Jun 28	pmiller
X			14:59:40 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 6, change 3.
X
XSUMMARY
X	change tests to use 'test' rather than '[...]'
X
XDESCRIPTION
X	1. change tests to use 'test' rather than '[...]'
X	2. change tests to use #!/bin/sh rather than :
X	3. add stuff about tests to the Tips and Traps chapter of the user
X	guide.
X	4. add stuff about RCS to the History Tool chapter of th euser guide.
X	5. correct some typos in the SCCS section if the Hostoiry Tool chapter.
X
XCAUSE
X	internal_enhancement
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	4	doc/BUILDING.man
X	source	modify	2	doc/c3.1.so
X	source	modify	2	doc/c3.2.so
X	source	modify	3	doc/c6.0.so
X	test	modify	2	test/00/t0001a.sh
X	test	modify	2	test/00/t0002a.sh
X	test	modify	2	test/00/t0003a.sh
X	test	modify	2	test/00/t0004a.sh
X	test	modify	2	test/00/t0005a.sh
X	test	modify	2	test/00/t0006a.sh
X	test	modify	2	test/00/t0007a.sh
X	test	modify	2	test/00/t0008a.sh
X	test	modify	2	test/00/t0009a.sh
X	test	modify	2	test/00/t0010a.sh
X	test	modify	2	test/00/t0011a.sh
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Sat Jun 27	pmiller Elapsed time: 4.147 days.
X			23:15:07 1992
X	develop_begin	Sat Jul	 4	pmiller Elapsed time: 0.000 days.
X			16:51:15 1992
X	develop_end	Sun Jul	 5	pmiller Elapsed time: 0.001 days.
X			00:55:43 1992
X	review_pass	Sun Jul	 5	pmiller Elapsed time: 0.002 days.
X			00:55:58 1992
X	integrate_begin Sun Jul	 5	pmiller Elapsed time: 0.000 days.
X			00:57:01 1992
X	integrate_pass	Sun Jul	 5	pmiller
X			15:20:41 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 3, change 4.
X
XSUMMARY
X	add configuration for varargs
X
XDESCRIPTION
X	1. A major stumbling block is that many systems don't have stdarg.
X	Change the code to be able to use stdarg.h or varargs.h as necessary.
X	2. move common elements of aegis and fmtgen into common, as many of
X	these common elements need mods for varargs.
X	3. reflect the change to varargs in the BUILDING instructions.
X	4. other small mods so will compiler with traditional cc.
X	5. enhance the capabilities of str_vformat.
X
XCAUSE
X	internal_enhancement
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	2	Makefile.sh
X	source	modify	2	aegis/administ.c
X	source	modify	2	aegis/archaeol.c
X	source	remove	1	aegis/arglex.c
X	source	remove	1	aegis/arglex.h
X	source	create	1	aegis/arglex2.h
X	source	modify	2	aegis/build.c
X	source	modify	2	aegis/cattr_ed.c
X	source	modify	2	aegis/change.c
X	source	modify	2	aegis/chdir.c
X	source	modify	2	aegis/col.c
X	source	modify	2	aegis/copyfile.c
X	source	modify	2	aegis/develop1.c
X	source	modify	2	aegis/develop2.c
X	source	modify	2	aegis/diff.c
X	source	modify	2	aegis/dir.c
X	source	remove	1	aegis/error.c
X	source	remove	1	aegis/error.h
X	source	modify	2	aegis/help.c
X	source	remove	1	aegis/indent.c
X	source	remove	1	aegis/indent.h
X	source	modify	2	aegis/integra1.c
X	source	modify	2	aegis/integra2.c
X	source	modify	2	aegis/lex.c
X	source	modify	2	aegis/list.c
X	source	modify	2	aegis/log.c
X	source	modify	2	aegis/log.h
X	source	modify	2	aegis/main.c
X	source	remove	1	aegis/mem.c
X	source	remove	1	aegis/mem.h
X	source	modify	2	aegis/new_chan.c
X	source	modify	2	aegis/new_file.c
X	source	modify	2	aegis/new_proj.c
X	source	modify	2	aegis/new_rele.c
X	source	modify	2	aegis/new_test.c
X	source	remove	1	aegis/option.c
X	source	remove	1	aegis/option.h
X	source	modify	2	aegis/os.c
X	source	modify	2	aegis/pattr_ed.c
X	source	modify	2	aegis/project.c
X	source	modify	2	aegis/rem_file.c
X	source	modify	2	aegis/review.c
X	source	modify	2	aegis/reviewer.c
X	source	remove	1	aegis/str.c
X	source	remove	1	aegis/str.h
X	source	modify	2	aegis/sub.c
X	source	modify	2	aegis/test.c
X	source	remove	1	aegis/trace.c
X	source	remove	1	aegis/trace.h
X	source	modify	2	aegis/tree.c
X	source	modify	2	aegis/undo.c
X	source	modify	2	aegis/undo.h
X	source	modify	2	aegis/user.c
X	source	modify	2	aegis/version.c
X	source	remove	1	aegis/word.c
X	source	remove	1	aegis/word.h
X	source	create	1	common/arglex.c
X	source	create	1	common/arglex.h
X	source	create	1	common/error.c
X	source	create	1	common/error.h
X	source	create	1	common/indent.c
X	source	create	1	common/indent.h
X	source	modify	2	common/main.h
X	source	create	1	common/mem.c
X	source	create	1	common/mem.h
X	source	create	1	common/option.c
X	source	create	1	common/option.h
X	source	create	1	common/str.c
X	source	create	1	common/str.h
X	source	create	1	common/trace.c
X	source	create	1	common/trace.h
X	source	create	1	common/word.c
X	source	create	1	common/word.h
X	source	modify	2	conf/SunOS-4.1.2
X	source	modify	2	conf/SysV-4.0
X	source	modify	2	doc/BUILDING.man
X	source	remove	1	fmtgen/arglex.c
X	source	remove	1	fmtgen/arglex.h
X	source	remove	1	fmtgen/error.c
X	source	remove	1	fmtgen/error.h
X	source	modify	2	fmtgen/id.c
X	source	remove	1	fmtgen/indent.c
X	source	remove	1	fmtgen/indent.h
X	source	modify	2	fmtgen/lex.c
X	source	modify	2	fmtgen/lex.h
X	source	modify	2	fmtgen/main.c
X	source	remove	1	fmtgen/mem.c
X	source	remove	1	fmtgen/mem.h
X	source	modify	2	fmtgen/parse.y
X	source	remove	1	fmtgen/str.c
X	source	remove	1	fmtgen/str.h
X	source	modify	2	fmtgen/type_enum.c
X	source	modify	2	fmtgen/type_integ.c
X	source	modify	2	fmtgen/type_list.c
X	source	modify	2	fmtgen/type_ref.c
X	source	modify	2	fmtgen/type_strin.c
X	source	modify	2	fmtgen/type_struc.c
X	source	remove	1	fmtgen/word.c
X	source	remove	1	fmtgen/word.h
X	source	remove	1	h/stdarg.h
X	source	create	1	h/stdarg.h-min
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Sat Jun 27	pmiller Elapsed time: 0.000 days.
X			23:17:00 1992
X	develop_begin	Sun Jun 28	pmiller Elapsed time: 4.533 days.
X			15:02:39 1992
X	develop_end	Fri Jul	 3	pmiller Elapsed time: 0.001 days.
X			11:32:22 1992
X	review_pass	Fri Jul	 3	pmiller Elapsed time: 0.001 days.
X			11:32:38 1992
X	integrate_begin Fri Jul	 3	pmiller Elapsed time: 0.264 days.
X			11:33:15 1992
X	integrate_pass	Fri Jul	 3	pmiller
X			13:32:09 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 5, change 5.
X
XSUMMARY
X	make it more C standard conforming
X
XDESCRIPTION
X	1. The convex has a more strictly conforming C implementation than
X	gcc. Make changes to allow aegis to compile on the convex.
X	2. add a convex configuration file, and change the BUILDING
X	documentation to reflect this.
X	3. fix numerous typos in the BUILDING document.
X
XCAUSE
X	internal_bug
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	2	aegis/arglex2.h
X	source	modify	3	aegis/change.c
X	source	modify	2	aegis/commit.c
X	source	modify	2	aegis/dir.h
X	source	modify	2	aegis/gate.h
X	source	modify	3	aegis/help.c
X	source	modify	3	aegis/list.c
X	source	modify	2	aegis/lock.c
X	source	modify	3	aegis/project.c
X	source	modify	2	aegis/type.h
X	source	modify	3	aegis/undo.c
X	source	modify	2	common/arglex.c
X	source	modify	2	common/arglex.h
X	source	create	1	conf/ConvexOS-10
X	source	modify	3	doc/BUILDING.man
X	source	modify	2	fmtgen/id.h
X	source	modify	3	fmtgen/main.c
X	source	modify	2	fmtgen/type.h
X	source	modify	3	fmtgen/type_enum.c
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Fri Jul	 3	pmiller Elapsed time: 0.160 days.
X			15:05:25 1992
X	develop_begin	Fri Jul	 3	pmiller Elapsed time: 0.865 days.
X			16:17:25 1992
X	develop_end	Fri Jul	 3	pmiller Elapsed time: 0.000 days.
X			22:46:35 1992
X	review_pass	Fri Jul	 3	pmiller Elapsed time: 0.002 days.
X			22:46:47 1992
X	integrate_begin Fri Jul	 3	pmiller Elapsed time: 0.000 days.
X			22:47:45 1992
X	integrate_fail	Sat Jul	 4	pmiller When tried the tar file on the
X			10:34:58 1992		convex, it still failed.
X						Elapsed time: 0.668 days.
X	develop_end	Sat Jul	 4	pmiller Elapsed time: 0.000 days.
X			15:35:37 1992
X	review_pass	Sat Jul	 4	pmiller Elapsed time: 0.002 days.
X			15:35:49 1992
X	integrate_begin Sat Jul	 4	pmiller Elapsed time: 0.160 days.
X			15:36:49 1992
X	integrate_pass	Sat Jul	 4	pmiller
X			16:48:43 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 7, change 6.
X
XSUMMARY
X	make os_pathname understand symbolic links
X
XDESCRIPTION
X	1. Change os_pathname to substitute the value of symbolic links when
X	they are encountered.
X	2. make strategic use of os_pathname so that commands which use os_
X	below_dir alway behaves in an intuitive manner.
X	3. remove obsolete defaulting fields from ustate.def and manuals.
X	4. add aditional defaulting for aenpr and aenrls, and document same.
X	5. add additional defaulting for aedb, and document same.  May now
X	also have project defaults.
X	6. beef-up aepa so that can set the new defaults, and document same.
X
X	My thanks to Esa K Viitala <esa@tollpost-globe.no> for reporting these
X	problems.
X
XCAUSE
X	external_bug
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	3	aegis/administ.c
X	source	modify	3	aegis/archaeol.c
X	source	modify	3	aegis/build.c
X	source	modify	2	aegis/cattr.def
X	source	modify	3	aegis/cattr_ed.c
X	source	modify	4	aegis/change.c
X	source	modify	3	aegis/chdir.c
X	source	modify	3	aegis/copyfile.c
X	source	remove	1	aegis/defaults.c
X	source	remove	1	aegis/defaults.h
X	source	modify	3	aegis/develop1.c
X	source	modify	3	aegis/develop2.c
X	source	modify	3	aegis/diff.c
X	source	modify	3	aegis/gate.h
X	source	modify	2	aegis/gonzo.c
X	source	modify	3	aegis/integra1.c
X	source	modify	3	aegis/integra2.c
X	source	modify	4	aegis/list.c
X	source	modify	3	aegis/main.c
X	source	modify	3	aegis/new_chan.c
X	source	modify	3	aegis/new_file.c
X	source	modify	3	aegis/new_proj.c
X	source	modify	3	aegis/new_rele.c
X	source	modify	3	aegis/new_test.c
X	source	modify	3	aegis/os.c
X	source	modify	2	aegis/pattr.def
X	source	modify	3	aegis/pattr_ed.c
X	source	modify	4	aegis/project.c
X	source	modify	2	aegis/project.h
X	source	modify	3	aegis/rem_file.c
X	source	modify	3	aegis/review.c
X	source	modify	3	aegis/reviewer.c
X	source	modify	3	aegis/test.c
X	source	modify	2	aegis/uconf.def
X	source	modify	3	aegis/user.c
X	source	modify	2	aegis/ustate.def
X	source	modify	2	common/str.c
X	source	modify	2	man1/aeca.1
X	source	modify	2	man1/aecd.1
X	source	modify	2	man1/aecp.1
X	source	modify	2	man1/aecpu.1
X	source	modify	2	man1/aed.1
X	source	modify	2	man1/aedb.1
X	source	remove	1	man1/aega.1
X	source	modify	2	man1/aegis.1
X	source	modify	2	man1/ael.1
X	source	modify	2	man1/aeni.1
X	source	modify	2	man1/aenpr.1
X	source	modify	2	man1/aenrls.1
X	source	modify	2	man1/aepa.1
X	source	remove	1	man1/aeua.1
X	source	modify	2	man1/o_project.so
X	source	modify	2	man1/z_name.so
X	source	modify	2	man5/aepattr.5
X	source	modify	2	man5/aepstate.5
X	source	modify	2	man5/aeuconf.5
X	source	modify	2	man5/aeustate.5
X	source	modify	2	man5/z_name.so
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Sun Jul	 5	pmiller Elapsed time: 0.001 days.
X			15:23:26 1992
X	develop_begin	Sun Jul	 5	pmiller Elapsed time: 0.895 days.
X			15:24:00 1992
X	develop_end	Tue Jul	 7	pmiller Elapsed time: 0.001 days.
X			23:36:32 1992
X	review_pass	Tue Jul	 7	pmiller Elapsed time: 0.002 days.
X			23:36:52 1992
X	integrate_begin Tue Jul	 7	pmiller Elapsed time: 0.000 days.
X			23:37:48 1992
X	integrate_pass	Wed Jul	 8	pmiller
X			12:04:45 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 8, change 7.
X
XSUMMARY
X	more tinkering for the convex
X
XDESCRIPTION
X	more tinkering for the convex
X
XCAUSE
X	chain
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	3	aegis/log.c
X	source	modify	2	common/error.h
X	source	modify	2	common/trace.h
X	source	modify	2	conf/ConvexOS-10
X	source	modify	3	conf/SunOS-4.1.2
X	source	modify	3	conf/SysV-4.0
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Mon Jul 13	pmiller Elapsed time: 0.000 days.
X			14:19:52 1992
X	develop_begin	Mon Jul 13	pmiller Elapsed time: 0.233 days.
X			14:19:57 1992
X	develop_end	Mon Jul 13	pmiller Elapsed time: 0.000 days.
X			16:04:37 1992
X	review_pass	Mon Jul 13	pmiller Elapsed time: 0.002 days.
X			16:04:50 1992
X	integrate_begin Mon Jul 13	pmiller Elapsed time: 0.120 days.
X			16:05:56 1992
X	integrate_pass	Mon Jul 13	pmiller
X			16:59:44 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 9, change 8.
X
XSUMMARY
X	add new file templates
X
XDESCRIPTION
X	Add new file templates to the project config file, removing the
X	inadequate defaulting mechanism for test contents.
X
XCAUSE
X	internal_enhancement
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	3	Howto.cook
X	source	modify	5	aegis/change.c
X	source	modify	2	aegis/change.h
X	source	modify	4	aegis/new_file.c
X	source	modify	4	aegis/new_test.c
X	source	modify	2	aegis/pconf.def
X	source	modify	3	fmtgen/type_list.c
X	source	modify	2	man5/aepconf.5
X	test	modify	3	test/00/t0002a.sh
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Mon Jul 13	pmiller Elapsed time: 0.002 days.
X			21:57:49 1992
X	develop_begin	Mon Jul 13	pmiller Elapsed time: 0.000 days.
X			21:58:34 1992
X	develop_end	Tue Jul 14	pmiller Elapsed time: 0.001 days.
X			13:00:56 1992
X	review_pass	Tue Jul 14	pmiller Elapsed time: 0.002 days.
X			13:01:14 1992
X	integrate_begin Tue Jul 14	pmiller Elapsed time: 0.076 days.
X			13:02:04 1992
X	integrate_pass	Tue Jul 14	pmiller
X			13:36:24 1992
X
XIDENTIFICATION
X	Project "aegis.1.2", build 10, change 9.
X
XSUMMARY
X	document file templates
X
XDESCRIPTION
X	document file templates
X
XCAUSE
X	chain
X
XSTATE
X	being_integrated
X
XFILES
X	Type	Action	Edit	File Name
X	------- ------- ------- -----------
X	source	modify	4	aegis/new_file.c
X	source	modify	4	aegis/new_test.c
X	source	modify	1	config
X	source	modify	2	doc/c1.3.so
X	source	modify	3	doc/c6.0.so
X	source	modify	1	man1/aenf.1
X	source	modify	1	man1/aent.1
X	source	modify	2	man5/aepconf.5
X
XHISTORY
X	What		When		Who	Comment
X	------		------		-----	---------
X	new_change	Fri Jul 17	pmiller Elapsed time: 0.000 days.
X			21:53:17 1992
X	develop_begin	Fri Jul 17	pmiller Elapsed time: 0.239 days.
X			21:53:26 1992
X	develop_end	Fri Jul 17	pmiller Elapsed time: 0.003 days.
X			23:40:56 1992
X	review_pass	Fri Jul 17	pmiller Elapsed time: 0.002 days.
X			23:42:23 1992
X	integrate_begin Fri Jul 17	pmiller Elapsed time: 0.032 days.
X			23:43:23 1992
END_OF_FILE
if test 25416 -ne `wc -c <'aux/CHANGES.1.2'`; then
    echo shar: \"'aux/CHANGES.1.2'\" unpacked with wrong size!
fi
# end of 'aux/CHANGES.1.2'
fi
echo shar: End of archive 13 \(of 19\).
cp /dev/null ark13isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 19 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
