[comp.sources.unix] v19i030: A software configuration management system, Part17/33

rsalz@uunet.uu.net (Rich Salz) (06/05/89)

Submitted-by: Axel Mahler <unido!coma!axel>
Posting-number: Volume 19, Issue 30
Archive-name: shape/part17



#! /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 17 (of 33)."
# Contents:  man/man1/vadm.1 man/man3/afintro.3 src/vc/dosave.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:09 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'man/man1/vadm.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/man1/vadm.1'\"
else
echo shar: Extracting \"'man/man1/vadm.1'\" \(16429 characters\)
sed "s/^X//" >'man/man1/vadm.1' <<'END_OF_FILE'
X...
X... Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
X...  and U. Pralle
X... 
X... This software is published on an as-is basis. There is ABSOLUTELY NO
X... WARRANTY for any part of this software to work correctly or as described
X... in the manuals. We do not accept any liability for any kind of damage
X... caused by use of this software, such as loss of data, time, money, or 
X... effort.
X... 
X... Permission is granted to use, copy, modify, or distribute any part of
X... this software as long as this is done without asking for charge, and
X... provided that this copyright notice is retained as part of the source
X... files. You may charge a distribution fee for the physical act of
X... transferring a copy, and you may at your option offer warranty
X... protection in exchange for a fee.
X... 
X... Direct questions to: Tech. Univ. Berlin
X... 		     Wilfried Koch
X... 		     Sekr. FR 5-6 
X... 		     Franklinstr. 28/29
X... 		     D-1000 Berlin 10, West Germany
X... 
X... 		     Tel: +49-30-314-22972
X... 		     E-mail: shape@coma.uucp or shape@db0tui62.bitnet
X... 
X...
X... $Header: vadm.1[3.3] Thu Feb 23 18:14:02 1989 axel@coma published $
X... 
X... Log for /u/shape/dist-tape/src/vc/vadm.1[3.1]
X... 	Thu Feb 23 18:14:02 1989 axel@coma published $
X...  --- empty log message ---
X...  vadm.1[3.2] Thu Feb 23 18:14:03 1989 axel@coma published $
X...  --- empty log message ---
X...  vadm.1[3.3] Thu Feb 23 18:14:03 1989 axel@coma published $
X...  --- empty log message ---
X...
X.UC
X.TH VADM 1 vadm \n(dy.\n(mo.\n(yr
X.SH NAME
Xvadm \- manipulate and administer version object base
X.SH SYNOPSIS
X\fBvadm\fR [\ \fIoptions\fR\ ]\ [\ \fIversion\ range\fR\ ]\ [\ \fIaction\fR\ ] name\|.\|.
X.SH DESCRIPTION
X.PP
X\fBvadm\fR is a general purpose command to perform all sorts of
Xactions upon parts of an AFS object base. It can be used to lock or unlock
Xan AFS object, to reserve (or unreserve) an object for modification, to
Xdelete a particular object instance, to associate symbolic names with
Xversion objects, to promote or unpromote certain version objects from
Xone status to another, to modify an object's access permissions, to set or
Xmodify a descriptive entry of particular version objects, to set or
Xmodify an eventual change intention, and to set
Xor unset various object attributes such as the author or any user
Xdefined attributes.
X.PP
XThe typical command invocation is supplemented by one or more
X\fIcommand options\fR, a \fIversion range\fR usually defining a
Xrange of object instances to be acted upon, an \fIaction specifier\fR
Xindicating the sort of action to be performed, and a set of \fIobject
Xnames\fR defining the initial subset of the object base that's going
Xto be manipulated. 
X.PP
XObject names may be given in \fIbound version notation\fR,
Xi.e. a notation that identifies a particular version of an object (e.g.
X\fCmkattr.c[2.4]\fR). It is also possible to use a previously assigned
X\fIsymbolic name\fR rather than a numerical 
Xversion identification (e.g. \fCmkattr.c[tools-V4R3]\fR). Make sure
Xto escape the bracket-symbols as these usually have meaning to the
Xshell.
X.PP
XThe following \fIoptions\fR are recognized:
X.IP "\fB\-version\fR" \w'\fB\-version++\fR'u
Xprint version information about the \fBvadm\fR program itself. No action
Xwill be performed on the database.
X.IP "\fB\-b\fR"
Xapply the requested operation to objects residing in the \fIbinary pool\fR.
XThe set of actions that may be performed on binary pool objects is limited.
X.IP "\fB\-h\fR"
Xprint brief instructions about using \fBvadm\fR
X.IP "\fB\-q\fR"
Xsuppress any prompts, informal messages and user dialogues. Default 
Xvalues are assumed for everything that might otherwise be inquired
Xinteractively. This option is useful for batch operation.
X.in -0.25i
X.PP
X\fBvadm\fR will perform all of its operations upon a specified set of
XAFS version objects. In case no such set is specified, the operation
Xwill be applied to the most recently saved versions of the named
Xobject(s).  A particular version can be identified by specifying its
X\fIversionnumber\fR or a previously assigned \fIsymbolic name\fR
Xthrough the \fB\-V\fI<version>\fR argument. A \fIrange\fR of versions can
Xbe defined through use of the \fB\-from\fI<versionnumber>\fR and
X\fB\-to\fI<versionnumber>\fR arguments.  The specified range
X\fIincludes\fR the given margin versions. Use of either version range 
Xspecification form (\fB\-V \fR or \fB\-from/\-to\fR) excludes the
Xother form.
X.PP
XThe kind of operation to be performed upon a specified set of AFS
Xobjects is indicated by a keyword. The following actions are defined:
X.in +0.25i
X.IP "\fB\-lock\fR" \w'\fB\-unpromote++\fR'u
Xtries to reserve the privilege to add a new version to an objects 
Xhistory, thus preventing multiple programmers working upon the same 
Xobject base from interfering with each other by saving concurrent updates.
XThis simple mechanism is for use in small development projects, that do
X\fInot\fR employ the scheme of private, experimental archives for each 
Xparticipating programmer, and one centralized \fIproject library\fR where
Xindividual work results are collected. 
XWhen setting a new lock on an object history, the requesting user
Xis prompted for an optional description of the planned changes.
XSee also \fB\-reserve\fR.
X.RS
X.PP
XIn order to lock an object history successfully, the history must not
Xbe locked by any other programmer, and the programmer requesting the
Xlock must have write permission on the AFS subdirectory hosting the
Xobject base.
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.IP "\fB\-unlock\fR"
Xgives up the previously reserved privilege to update the history of an
XAFS object. \fB\-unlock\fR may be used by the \fIowner\fR of an object
Xhistory to \fIbreak a lock\fR previously set by any programmer. This 
Xoption is useful to resolve deadlock situations resulting from careless
Xuse of \fB\-lock\fR, or exceptional circumstances that require immediate
Xupdating of an object history, even if the lockholder is not present.
XThe previous owner of a broken lock is notified by a
Xmail message. An eventually expressed change intention (see \fB\-lock\fR)
Xwill be cleared.
X.RS
X.PP
XTechnically, the owner of an object's history is the owner of the 
XAFS subdirectory hosting the object base.
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.IP "\fB\-reserve\fR"
Xtries to reserve a version object from a centrally maintained project 
Xlibrary in order to use it as starting point for the development of
Xa new entry in the objct's history. In fact, \fB\-reserve\fR does nothing
Xelse but eventually copy the specified version object from the
Xproject library to the programmer's workspace, and set a lock on the 
Xobject's history in the project library.
XWhen setting a new lock on an object history, the requesting user
Xis prompted for an optional description of the planned changes.
XSee also \fB\-lock\fR.
X.RS
X.PP
XAs with the \fB\-lock\fR request, an object's history must not be reserved
Xby any other programmer, and the requesting programmer must have permission
Xto do so. 
X.PP
XTo communicate with the project library, the reserve command either accesses
Xa distant object base directory, or connects to a local (unix domain) or
Xremote (internet domain) \fIlibrary server\fR. The place where a project's
Xcentral library resides is identified by an entry in a projects database.
XThis database is either \fI~/af_projects\fR or a default file such
Xas \fI/usr/local/lib/af_projects\fR. The name of the project a requesting
Xprogrammer is currently working on should be defined in the programmer's
Xshell environment by the \fIAF_PROJECT\fR variable.
X.PP
XThis command is currently not implemented.
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.IP "\fB\-unreserve\fR"
Xcancels a previously issued \fB\-reserve\fR request. As with the
X\fB\-lock\fR request, \fB\-unreserve\fR can be used by the \fIlibrary
Xadministrator\fR to forcefully cancel an update reservation by any
Xprogrammer. Programmers who are subject to forced cancellations will
Xbe notified by a mail message.
X.RS
X.PP
XThis command is currently not implemented.
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.IP "\fB\-delete\fR"
Xremoves the specified version objects from the object base, provided
Xthe objects' status is \fIsaved\fR. Any other status indicates that
Xsome kind of project interaction concerning this object might be in
Xprogress. If the programmer wants to delete such a version object
Xanyway, he has to \fB\-unpromote\fR the respective object's status to
X\fIsaved\fR before it can actually be deleted.
X.IP "\fB\-symbolic\fI\ <uniquename>"
Xassigns the name \fIuniquename\fR to the specified version. The symbolic
Xname works as an alias for the version number, so it must be different
Xfrom any other symbolic name assigned to any version object in a particular
Xobject history. It is, however, possible to assign the same symbolic
Xname to version objects in \fIdifferent object histories\fR. An object
Xhistory is usually denoted by a name, similarly to a file's name.
X.RS
X.PP
XThe use of symbolic names is a simple but effective way to associate component
Xmembers of a \fIsystem configuration\fR. Typical symbolic names will
Xlook something like \fIMysystem_Release_4.22(vax)\fR, indicating that 
Xversion objects with this name are part of release 4.22 of the system
Xin question.
X.RE
X.IP "\fB\-promote\fR"
Xassigns the next-higher value to the specified objects' \fIstate\fR attribute.
XThere are six states that an object instance can be in: \fIbusy, saved,
Xproposed, published, accessed, \fRand\fI frozen\fR. Version states are
Xintended to relate to visibility and operational restrictions (see for
Xexample \fB\-delete\fR) within a complex project environment.
X.RS
X.PP
XDue to the current lack of project library support, the version states
Xhave very little actual functionality. Implemented to its full extent,
Xcertain state transitions may only be triggered by appropriately
Xauthorized users. The transitions \fIbusy\(->saved\fR and 
X\fIsaved\(->proposed\fR will be triggered by regular programmers, whereas
Xthe remaining transitions have to be initiated by the \fIproject 
Xadministrator\fR. 
X.PP
XEach transition corresponds to a specific action or interaction within
Xa general software project communication scheme. As these actions/interactions
Xwill be functionally supported by the project support system currently
Xunder development, the explicit manipulation of object states will no
Xlonger be necessary (except, perhaps for manual adjusting of ill situations).
X.PP
XThe following actions relate to the state transitions:
X.IP "\fIsave\fR"
X(\fIbusy\(->saved\fR, performed by programmer)
X.IP "\fIsbmt\fR"
X(\fIsaved\(->proposed\fR, performed by programmer)
X.IP "\fIunsbmt\fR"
X(\fIproposed\(->saved\fR, performed by programmer)
X.IP "\fIaccpt\fR"
X(\fIproposed\(->published\fR, performed by project administrator)
X.IP "\fIrject\fR"
X(\fIproposed\(->proposed\fR, performed by project administrator)
X.IP "\fIaccs\fR"
X(\fIpublished\(->accessed\fR, performed by any project member)
X.IP "\fIrelease\fR"
X(\fIaccessed\(->frozen\fR, performed by project administrator)
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.IP "\fB\-unpromote\fR"
Xreverses a state transition carried out through a prior \fB\-promote\fR.
XThe same remarks about functional embedding (and thus \fIhiding\fR
Xthe state transitions) of state transitions made for \fB\-promote\fR 
Xhold for \fB\-unpromote\fR.
X.RS
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.IP "\fB\-chmod \fI<mode>\fR"
Xchanges the access permission code of the specified version objects to
Xthe supplied three-octal-digit \fImode\fR. Currently, the access
Xpermissions are centered around UNIX' notions of \fIowner, group,\fR and 
X\fIworld\fR
Xaccess as well as the access categories \fIread, write,\fR and \fIexecute\fR.
XThese
Xpermissions are inherited upon \fBsave\fR from the permissions of the
Xfile representing the \fIbusy object\fR of an AFS history. See
X\fBchmod\fR(2) for details.
X.IP "\fB\-chown \fI<user>\fR"
Xsets \fIuser\fR the owner of an entire object history. This option
Xis not supported on BSD type systems, as only the superuser may
Xchange the owner of a file.
X.IP "\fB\-chaut \fI<user>\fR"
Xsets \fIuser\fR the author of a particular revision. Normally, the
Xauthor of a revision is considered the user who \fIsaved\fR or \fIsubmitted\fR
Xthat revision. However, as certain permissions are tied to the author
Xattribute of a revision, circumstances may occur that make it necessary
Xto change the author.
X.IP "\fB\-set \fR[\fIdescription \fR| \fInote\fR | \fIintent\fR]"
Xallows to set or modify the \fIdescriptive text\fR for an AFS history object
X(i.e. an entire version history), the \fInote\fR usually describing the
Xdifferences of a version object with respect to its preceding version, or
Xan entry describing a planned change.
X(Re-) setting the change intention may be appropriate, if a previously
Xset change intent has been consumed by a \fBsbmt\fR command that 
Xretained the lock on an object history.
X.RS
X.nr Ii \n(.i
X.PP
X\fBvadm\fR will check the caller's environment for the \fIEDITOR\fR
Xvariable and invoke the program identified therein. If the \fIEDITOR\fR
Xvariable is not set, the system's default editor will be activated.
XThe user may write an arbitrary length descriptive or note entry using
Xthe editor. When the user leaves the editor, the resulting text is
Xstored with the object history or the specified version objects.
X.PP
XThis option is not available for objects in binary pools.
X.RE
X.PP
X\fB\-setc\fI\ commentstring\fR
X.nr Ci \n(.i
X.in \n(Iiu
Xsets \fIcommentstring\fR as the (sequence of) character(s) that opens a 
Xcommentline within the formalism of the document.
XThis commentstring will be prepended to the lines of the log history
Xwhen the \fC$__log$\fR attribute is expanded within the text of a revision.
X.PP
X\fB\-setuda\fI <attrname=\fR[\fI@\fR]\fIstring>\fR
X.nr Ci \n(.i
X.in \n(Iiu
Xsets the user defined attribute \fIattrname\fR to the value \fIstring\fR
Xfor all specified version objects. If the first character of \fIstring\fR
Xis an at-sign, the rest of \fIstring\fR is taken to be the \fIname of a file\fR
Xthe contents of which will be taken as the value of the attribute. User
Xdefined attributes may be of arbitrary length. Any sequence of ASCII
Xcharacters \- with the exception of \e01 (control-A) \- is allowed to make
Xup an attribute value.
X.sp \n()Pu
XIf \fIattrname\fR was already set to some value, the previous value
Xwill be replaced by the newly specified one.
X.in \n(Ciu
X.IP "\fB\-unsetuda\fI <attrname>\fR" \w'\fB\-unpromote++\fR'u
Xdeletes the user defined attribute \fIattrname\fR from the set of attributes
Xassociated with the specified version objects.
X.IP "\fB\-setattrs\fI <filename>\fR"
Xreads names and values of user defined attributes from the file \fIfilename\fR.
XThe entries in the attribute file are of the form \fINAME=VALUE\fR. \fINAME\fR
Xmust be an alphanumeric string (no spaces) imediately followed by the equal
Xsign. The value may be an arbitrary ASCII string with the exception of 
Xcontrol-A and newline characters. There is exactly one attribute definition
Xper line. The file's last character must be a newline character.
X.RS
X.PP
XThis way to attach attributes was introduced to allow quick attachment
Xof a large number of attributes to version objects. This is \fInot\fR
Xthe primary user interface for doing this. Unfortunately, \fBvadm\fR 
Xreacts ungracefully if the described convention is not followed.
X.PP
XPreviously assigned values of user defined attributes are overridden by
Xthe values defined in the attributefile.
X.RE
X.SH SEE ALSO
Xsave(1), retrv(1), rsrv(1), sbmt(1), vl(1), shape(1), 
Xaf_intro(3), af_archive(5)
X.PP
XRecommended reading: A. Mahler, A. Lampen, \fI\(lqAn Integrated
XToolkit for Engineering Software Configurations\(rq\fR, Proceedings of
Xthe ACM SIGSOFT/SIGPLAN Software Engineering Symposium on Practical
XSoftware Development Environments, November 1988, Boston Mass. (to
Xbe published).
X.SH BUGS
XI'm afraid that there might be quite a lot of flaws around. Consistent 
Xhandling of permissions is an especially error prone subject. Please report
Xany bugs to the authors.
X.SH AUTHOR
XUli Pralle and Axel Mahler
X.br
XTechnical University Berlin
X.sp
X\fIUUCP:\fR		axel@coma.uucp (unido!coma!axel)
X.br
X		uli@coma.uucp (unido!coma!uli)
X.br
X\fIBITNET:\fR	axel@db0tui62
X.br
X		uli@db0tui62
X
END_OF_FILE
if test 16429 -ne `wc -c <'man/man1/vadm.1'`; then
    echo shar: \"'man/man1/vadm.1'\" unpacked with wrong size!
fi
# end of 'man/man1/vadm.1'
fi
if test -f 'man/man3/afintro.3' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/man3/afintro.3'\"
else
echo shar: Extracting \"'man/man3/afintro.3'\" \(16204 characters\)
sed "s/^X//" >'man/man3/afintro.3' <<'END_OF_FILE'
X...
X... Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
X...  and U. Pralle
X... 
X... This software is published on an as-is basis. There is ABSOLUTELY NO
X... WARRANTY for any part of this software to work correctly or as described
X... in the manuals. We do not accept any liability for any kind of damage
X... caused by use of this software, such as loss of data, time, money, or 
X... effort.
X... 
X... Permission is granted to use, copy, modify, or distribute any part of
X... this software as long as this is done without asking for charge, and
X... provided that this copyright notice is retained as part of the source
X... files. You may charge a distribution fee for the physical act of
X... transferring a copy, and you may at your option offer warranty
X... protection in exchange for a fee.
X... 
X... Direct questions to: Tech. Univ. Berlin
X... 		     Wilfried Koch
X... 		     Sekr. FR 5-6 
X... 		     Franklinstr. 28/29
X... 		     D-1000 Berlin 10, West Germany
X... 
X... 		     Tel: +49-30-314-22972
X... 		     E-mail: shape@coma.uucp or shape@db0tui62.bitnet
X... 
X.TH AF_INTRO 3 "" \n(dy.\n(mo.\n(yr
X.SH NAME
Xaf_intro \(em introduction to AFS library functions and error codes
X.SH SYNOPSIS
X#include <afs.h>
X.SH DESCRIPTION
XThe following manual pages (named AF_*) describe the library functions
Xof the \fIAttribute Filesystem\fR (AFS).
X.PP
XAFS is an extension to the \s-1UNIX\s+1
Xfilesystem interface that allows the storage of files as complex of
Xcontent data and an arbitrary number of associated attributes.
XThese are called \fIattributed software objects\fR (ASOs).
XAFS has a built-in version
Xcontrol system that manages \fIlines of development\fR. A line of
Xdevelopment consists of a \fIbusy object\fR and a number of saved
Xversions. The busy object is an ordinary alterable \s-1UNIX\s+1 file.
XIt can be accessed via AFS \fIand\fR \s-1UNIX\s+1
Xfilesytem operations.  Versions come
Xinto being by making a copy of the current state of the busy object.
XThey can be stored as source objects or as derived objects.
X.PP
XSource objects are typically composed manually (e.g. by use of a text
Xeditor). AFS stores source objects as immutable objects. Once saved,
Xthey cannot be modified any longer. Saved ASOs are stored in archive
Xfiles (like SCCS and RCS). AFS maintains two archive files for each
Xline of development of source objects \- one holding the attributes
Xand the other holding the data.  Normally, archives are stored in a
Xsubdirectory called AFS (see \fIaf_setarchpath\fR for an exception to
Xthis rule).  To save disk space, the versions in an archive are stored
Xas deltas (differences to the previous version).
X.PP
XDerived objects
Xare typically derived automatically (e.g. by a compiler) from a source
Xobject and thus be reproducible at any time. They are kept in a
X\fIderived object pool\fR (or \fIbinary pool\fR),
Xa data store of limited size that is
Xadministered in a cache fashion. The oldest (access date) derived
Xobjects get removed if space runs short in the derived object pool.
XDerived objects are stored physically unchanged. The attributes for
Xderived objects are stored in a \fIndbm\fR database residing in the
XAFS subdirectory. The maximum number of objects stored in a binary pool
Xcan be given by setting the environment variable AFSBPSIZ to the
Xappropriate value (default is 64).
X.PP
XAFS makes no assumptions
Xwhether a copy of a busy object shall be stored as source object or as
Xderived object. The application has to decide that by calling the
Xappropriate function (see \fIAF_VERSIONS\fR).
X.PP
XThe main datatypes for AFS applications are:
X.IP \(bu 0.2i
XThe \fIobject key\fR that uniquely
Xidentifies a software object. The structure of this type can be
Xdifferent in different implementations of AFS. Consequently,
Xapplication programs should handle this type as opaque type and should
Xnot access single fields.
X.IP \(bu
X\fISet descriptors\fR represent a
Xset of object keys. A set descriptor contains information about the
Xnumber of keys in the set and a pointer to a list of object keys (see
X\fIAF_SETS\fR).
X.IP \(bu
XAn \fIAttribute buffer\fR is capable to hold
Xall attributes of a software object (standard attributes and user
Xdefined attributes). Attribute buffers have two different purposes.
XFirst, they can hold a retrieve pattern, i.e. they may be (partially)
Xfilled with \fIdesired\fR attribute values and then be passed as
Xargument to a retrieve operation (\fIAF_RETRIEVE\fR). Second, an
Xattribute buffer is used to return all attributes of an identified ASO
Xon demand (see \fIAF_ATTRS\fR).
X.RE
X.PP
XMost of the AFS calls have
Xone or more error returns.  An error is indicated by a return value
Xthat is either \-1 or a nil pointer, depending on the type of the
Xfunction.  If one of the functions returns with an error, the variable
X\fIaf_errno\fR is set to indicate the appropriate error number.
X\fIAf_errno\fR is not cleared upon successful calls.
X.bp
X.PP
XThe following is a complete collection of the error numbers
Xdefined in \fIafs.h\fR. The first list contains return values
Xindicating \(lqnormal\(rq errors like unplausible arguments passed to
Xan AFS function or permission problems. The error codes listed in the
Xsecond list point to serious trouble, which can either be an internal
Xerror in AFS or a corrupted archive file. The occurrence of an
Xserious problem is recorded in an error protocol
X(\fI/usr/adm/AFSerrlog\fR). On machines without \fIsyslog (3)\fR
Xfacility, the error protocol is located in a \fI/tmp/AFSerrlog\fR.
X.IP " -2  AF_ESYSERR Error during execution of syslib-command or syscall"
XA called syslib function or syscall returned with an error
Xcondition. See \fIerrno\fR for a more precise error specification.
X.IP " -3  AF_EACCES permission denied"
XAn attempt was made to perform
Xan operation (e.g. open a file) without appropriate permissions.
X.IP " -4  AF_EARCHANGED archive file has changed since last read"
XOne of the archive files you are operating on has been modified
Xby another process since your process has read it from disk.
XIn this case, AFS refuses to store your changes because this would
Xdestroy the modifications made by the other process.
XIn order to make your desired changes happen, you have to rerun
Xyour application.
X.IP " -5  AF_EARLOCKED archive file is locked for writing"
XAnother process is currently writing one of the archive files
Xyou are operating on. Try again later.
X.IP " -6  AF_EBPFULL no additional space in derived object pool"
XThe AFS is
Xunable to delete an old object from a derived object pool in order to
Xget space for a new one. This error occurs if the concerning derived
Xobject pool is full and all objects stored in this derived object pools
Xare accessed by the current application. Use \fIaf_dropkey\fR or
X\fIaf_dropset\fR to release one or more derived objects.
X.IP "  -7  AF_EBUSY  Specified ASO must not be a busy version"
XSome AFS-operations (eg. \fIaf_snote\fR, \fIaf_svnum\fR) cannot be
Xperformed on ASOs which have the state \fIAF_BUSY\fR. 
X.IP "  -8  AF_EDERIVED  Specified ASO must not be a derived object"
XSome AFS-operations (eg. \fIaf_lock\fR, \fIaf_newgen\fR) cannot be
Xperformed on ASOs stored in derived object pools.
X.IP "  -9  AF_EFORMAT  illegal format of udattr string"
XUser defined attributes must have the form \fIname[=value]\fR.
XSee af_udas (3) for further details.
X.IP "-10  AF_EINVKEY invalid object key"
XAn invalid object key (eg. nil pointer) was passed to an AFS-function.
X.IP "-11  AF_EINVSET invalid set descriptor"
XAn invalid set descriptor (eg. nil pointer) was passed to an AFS-function.
X.IP "-12  AF_EINVUSER invalid user"
XAn invalid user name was passed to an AFS-operation.
X.IP "-13  AF_EINVVNUM Bad version number"
XAn attempt was made to set a version number, that
Xcontradicts the AFS version numbering philosophy, to an ASO.
XYou cannot change the version number of an ASO into a version
Xnumber that is \(lqsmaller\(rq than the one given by the system.
X.IP "-14  AF_ELOC invalid location of archive file"
XAn archive file has been moved without updating the \fIhost\fR and
X\fIpathname\fR attribute.
X.IP "-15  AF_EMISC miscellaneous errors"
XThis error code is set when an error occurs that does not fit in any
Xof the other error categories.
XSee your error logging file (\fI/usr/adm/AFSerrlog\fR of \fI/tmp/AFSerrlog\fR)
Xfor a detailed description of the error.
X\fIAf_perror\fR also gives a diagnostic message explaining the error.
X.IP "-16  AF_EMODE invalid mode"
XThe functions \fIaf_svar\fR and \fIaf_sudattrs\fR require a change mode.
XThis error condition complains about an invalid mode given to one
Xof these two functions. See \fIaf_udattrs\fR for further
Xdetails.
X.IP "-17  AF_ENOAFSDIR  AFS subdirectory missing or not writable"
XThere is no place where AFS can create it's archive files.
XEither a global archive path should be defined (see \fIaf_setarchpath\fR)
Xor a subdirectory named \(lqAFS\(rq should be present and writable.
X.IP "-18  AF_ENOKEY  key does not exist in set"
XA specified key that shall be removed from a keyset does not exist
Xin the concerning set.
X.IP "-19  AF_ENOPOS  invalid position in set"
XA specified position in a keyset (keysets are organized as arrays
Xof object keys) lies beyond the bounds of the concerning set.
X.IP "-20  AF_ENOREV  specified revision does not exist"
XA revision - uniquely identified by a set of attributes (eg.
X\fIaf_getkey\fR) - does not exist in the current search space.
X.IP "-21  AF_ENOTBUSY  specified ASO is not busy version"
XSome AFS-operations (eg. af_setbusy (3)) require the key of a busy ASO
Xas input parameter. If you pass key of a non-busy ASO, the
Xfunction sets this error code. 
X.IP "-22  AF_ENOTDERIVED  specified ASO is no derived object"
XAn attempt was made to restore an object that in not stored in a
Xderived object pool.
X.IP "-23  AF_ENOTLOCKED  spec. ASO is not locked or locked by another user"
XAn AFS-operation cannot be performed because the specified ASO
Xis either not locked (see \fIaf_lock\fR) or it is locked by
Xanother user.
X.IP "-24  AF_ENOTREGULAR  specified ASO is no regular file"
XWith this error number the AFS refuses to generate versions of
Xnon-regular \s-1UNIX\s+1 files such as directories, special files and sockets.
X.IP "-25  AF_ENOTVERS  specified ASO has no versions"
XTypically, this error occurs if an operation that requires at least
Xone saved revision (eg. af_newgen (3)) is applied on a versionless file.
X.IP "-26  AF_ENOUDA  user defined attribute does not exist"
XA user defined attribute with the given name does not exist.
X.IP "-27  AF_ESAVED  saved versions cannot be modified"
XAn attempt was made to open a non-busy version with write access.
X.IP "-28  AF_ESTATE  invalid state transition"
XThe \fIAttribute Filesystem\fR's built in revision-states model allows
Xonly well defined revision state changes. See af_states (3) for further
Xdetails.
X.IP "-29  AF_ETOOLONG  String too long"
XA given string that shall be set as the value of a string attribute
X(eg. \fIaf_variant\fR) is too long.
X.IP "-30  AF_EUDASNUM too many user defined attributes"
XDue to the
Xfact, that an attribute buffer can only hold a limited number of user
Xdefined attributes, AFS complains if the number of user defined
Xattributes attached to an ASO exceeds this limit. The constant
X\fIAF_MAXUDAS\fR defined in \fIafs.h\fR defines the maximum number of
Xuser defined attributes.
X.IP "-31  AF_EWRONGSTATE wrong state"
XSome AFS-operations can only be performed on ASOs with a specific version
Xstate.
X.RE
X.PP
XThe error codes indicating real trouble:
X.IP "-32  AF_EDELTA Error during delta operation"
XSome error occurred during
Xinvocation of the delta processor.
X.IP "-33  AF_EINCONSIST Archive file inconsistent"
XThe data in the archive file are corrupted. This
Xmay have happened by editing the archive file or by malfunction of an
XAFS-operation.  Please inform your local trouble shooting service, go
Xto your favorite pub and order a beer.
X.IP "-34  AF_EINTERNAL internal error"
XPlease inform your local trouble shooting service, go to your
Xfavorite pub and order two beers.
X.IP "-35  AF_ENOAFSFILE No AFS file"
XArchive file missing.
X.RE
X.SH LIST OF FUNCTIONS
X.ta 1.4i 2.8i
X\fIName	Appears on Page	Description\fR
X.sp
Xaf_access	af_misc.3	test accessibility of ASO
X.br
Xaf_afname	af_misc.3	get ASO name from \s-1UNIX\s+1 path
X.br
Xaf_afpath	af_misc.3	get ASO syspath from \s-1UNIX\s+1 path
X.br
Xaf_aftype	af_misc.3	get ASO type from \s-1UNIX\s+1 path
X.br
Xaf_bpfind	af_retr.3	find derived objects by attributes
X.br
Xaf_chauthor	af_perm.3	change author of ASO
X.br
Xaf_chmod	af_perm.3	change access permissions of ASO
X.br
Xaf_chowner	af_perm.3	change owner of ASO
X.br
Xaf_cleanup	af_misc.3	do cleanup
X.br
Xaf_close	af_files.3	close ASO
X.br
Xaf_copyset	af_setops.3	copy sets
X.br
Xaf_crkey	af_files.3	create object key for \s-1UNIX\s+1\-file
X.br
Xaf_diff	af_setops.3	build difference between two sets of object keys
X.br
Xaf_dropkey	af_retrieve.3	drop object key
X.br
Xaf_dropset	af_sets.3	drop set of object keys
X.br
Xaf_find	af_retrieve.3	find ASOs by attributes
X.br
Xaf_gattrs	af_attrs.3	get all attributes of ASO
X.br
Xaf_getkey	af_retrieve.3	get key by unique attributes
X.br
Xaf_initattrs	af_retrieve.3	initialize attribute buffer
X.br
Xaf_initset	af_sets.3	initialize set
X.br
Xaf_intersect	af_setops.3	build intersection between two sets of object keys
X.br
Xaf_link	af_files.3	create a link between two ASOs
X.br
Xaf_lock	af_lock.3	set lock on ASO 
X.br
Xaf_newgen	af_versions.3	increase generation number of ASO
X.br
Xaf_nrofkeys	af_sets.3	return number of keys in set of object keys
X.br
Xaf_open	af_files.3	open ASO
X.br
Xaf_perror	af_misc.3	report AFS- or system error
X.br
Xaf_rauthor	af_perm.3	return author
X.br
Xaf_restore	af_files.3	restore derived ASO
X.br
Xaf_rgen	af_attr.3	return generation number of ASO
X.br
Xaf_rm	af_files.3	remove ASO
X.br
Xaf_rname	af_attrs.3	return name of ASO
X.br
Xaf_rnote	af_note.3	read note attribute 
X.br
Xaf_rowner	af_perm.3	return owner of ASO
X.br
Xaf_rrev	af_attr.3	return revision number of ASO
X.br
Xaf_rstate	af_versions.3	return version state of ASO
X.br
Xaf_rsyspath	af_attrs.3	return system path of ASO
X.br
Xaf_rtype	af_attrs.3	return type of ASO
X.br
Xaf_rudattr	af_udattrs.3	return user defined attribute
X.br
Xaf_rvariant	af_variant.3	return variant attribute
X.br
Xaf_savebinary	af_versions.3	save derived object
X.br
Xaf_saverev	af_versions.3	save busy version of source object
X.br
Xaf_setaddkey	af_sets.3	add key to set of object keys
X.br
Xaf_setarchpath	af_misc.3	set path for location of archives
X.br
Xaf_setbusy	af_versions.3	set version busy
X.br
Xaf_sgetkey	af_sets.3	get key from set of object keys
X.br
Xaf_setposrmkey	af_sets.3	remove key (id. by position) from set of object keys
X.br
Xaf_setrmkey	af_sets.3	remove key from set of object keys
X.br
Xaf_snote	af_note.3	set note attribute
X.br
Xaf_sortset	af_setops.3	sort set of object keys
X.br
Xaf_sstate	af_versions.3	set version state
X.br
Xaf_subset	af_setops.3	build subset of set of object keys
X.br
Xaf_sudattr	af_udattrs.3	set user defined attribute
X.br
Xaf_svariant	af_variant.3	set variant attribute
X.br
Xaf_svnum	af_versions.3	set version number
X.br
Xaf_testlock	af_lock.3	see if ASO is locked
X.br
Xaf_union	af_setops.3	build union of two sets of object keys
X.br
Xaf_unlock	af_lock.3	remove lock from ASO
X.br
Xaf_version	af_misc.3	return identification of current AFS version
X.br
X.SH FILES
X/usr/adm/AFSerrlog (/tmp/AFSerrlog)
X.SH SEE ALSO
Xintro (2), intro (3)
X.br
XA. Lampen and A. Mahler, \(lqAn Object Base for Attributed
XSoftware Objects,\(rq
X.br
X\fIProceedings of the Autumn '88 EUUG Conference\fR (Cascais, 3-7 October)
X.br
XEuropean UNIX system User Group, London 1988
X.SH BUGS
XThe built in archive file locking to prevent concurrent updates
Xis very simple and my lead to confusing situations.
XIt may happen that changes will not be saved to disk.
XSee the error conditions \fIAF_EARCHANGED\fR and \fIAF_EARLOCKED\fR
Xfor more details
X.PP
XThis is a draft version of the AFS-Manual.
XIt may still be a bit vague or even uncomplete every here and there.
XIf you have questions or suggestions, please mail them to the author.
XNevertheless, I hope this manual will provide enough information
Xto enable you to write AFS-applications. Happy hackin'!
X.SH AUTHOR
XAndreas Lampen, TU Berlin
X.br
X.ta 0.7i
XUUCP:	unido!coma!andy
X.br
XBITNET:	andy@db0tui62
END_OF_FILE
if test 16204 -ne `wc -c <'man/man3/afintro.3'`; then
    echo shar: \"'man/man3/afintro.3'\" unpacked with wrong size!
fi
# end of 'man/man3/afintro.3'
fi
if test -f 'src/vc/dosave.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/vc/dosave.c'\"
else
echo shar: Extracting \"'src/vc/dosave.c'\" \(16567 characters\)
sed "s/^X//" >'src/vc/dosave.c' <<'END_OF_FILE'
X/*
X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
X *  and U. Pralle
X * 
X * This software is published on an as-is basis. There is ABSOLUTELY NO
X * WARRANTY for any part of this software to work correctly or as described
X * in the manuals. We do not accept any liability for any kind of damage
X * caused by use of this software, such as loss of data, time, money, or 
X * effort.
X * 
X * Permission is granted to use, copy, modify, or distribute any part of
X * this software as long as this is done without asking for charge, and
X * provided that this copyright notice is retained as part of the source
X * files. You may charge a distribution fee for the physical act of
X * transferring a copy, and you may at your option offer warranty
X * protection in exchange for a fee.
X * 
X * Direct questions to: Tech. Univ. Berlin
X * 		     Wilfried Koch
X * 		     Sekr. FR 5-6 
X * 		     Franklinstr. 28/29
X * 		     D-1000 Berlin 10, West Germany
X * 
X * 		     Tel: +49-30-314-22972
X * 		     E-mail: shape@coma.uucp or shape@db0tui62.bitnet
X */
X#ifndef lint
Xstatic char *AFSid = "$Header: dosave.c[3.21] Thu Feb 23 18:13:30 1989 axel@coma published $";
X#ifdef CFFLGS
Xstatic char *ConfFlg = CFFLGS;
X	/* should be defined from within Makefile */
X#endif
X#endif
X/*
X * Log for /u/shape/dist-tape/src/vc/dosave.c[3.8]
X * 	Thu Feb 23 18:13:30 1989 axel@coma save $
X *  Intention for change:
X *  This is still a test. A minute ago, I was able to set an intention
X *  but now I doubt, that I'll be allowed to set a user defined attribute
X *  to the bus
X *  dosave.c[3.9] Thu Feb 23 18:13:30 1989 axel@coma save $
X *  Intention for change:
X *  This is still a test. A minute ago, I was able to set an intention
X *  but now I doubt, that I'll be allowed to set a user defined attribute
X *  to the bus
X *  dosave.c[3.15] Thu Feb 23 18:13:30 1989 axel@coma published $
X *  --- empty log message ---
X *  dosave.c[3.19] Thu Feb 23 18:13:30 1989 axel@coma published $
X *  --- empty log message ---
X *  dosave.c[3.20] Thu Feb 23 18:13:30 1989 axel@coma save $
X *  --- empty log message ---
X *  dosave.c[3.21] Thu Feb 23 18:13:30 1989 axel@coma published $
X *  --- empty log message ---
X */
X
X#include <strings.h>
X#include <stdio.h>
X#include <pwd.h>
X#include "afs.h"
X#include "save.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "project.h"
X#include "locks.h"
X
Xextern unsigned int options;
Xextern char tfname[], vcomment[], atr_fname[], symname[];
Xextern int newvnum;
Xextern struct Transaction ThisTransaction;
X
XSaveAFile (fname, proj) char *fname; Project *proj; {
X/*
X * Save working file with the given name in the project location (syspath)
X * determined by proj. Check for changes before saving.
X * Attributes are also derived from the proj-context.
X * Unless QUIETPLEASE is set, the user will be prompted for a note 
X * describing the changes to be saved.
X * On the locking strategy:
X * An author can save a busy version, only if he holds a lock (update
X * privilege) for the document history. When an archive is newly
X * created from a (busy) file, such a lock is assumed to be set.
X * Upon save operations - which are conceptually local to a user context -
X * the lock is kept. A lock can be released by submitting a version
X * to the project and explicitly giving up the lock (option). After that,
X * no more 'saves' are possible even though the user is in unix sense still
X * owner of his local archive-file. This is so because we guarantee object
X * consistency in a project among several databases.
X * Locks on certain documents can be obtained through means of 'reserve'
X * which is a User <--> Project transaction. Locally created documents
X * are placed under project discipline (or configuration control) the
X * first time they are submitted -- even if they have not been reserved
X * yet. Locks have token-character, i.e. they may be passed around, but
X * never ever be duplicated.
X */
X /*
X  *  NOTE: use of variant attribute in af_getkey is not yet functional.
X  *        The parameter, however, is necessary to occupy the slot.
X  *        Implementation of variant selection may make it necessary
X  *        to add another parameter to this procedure.
X  */
X  char spath[MAXNAMLEN], origpath[MAXNAMLEN], name[MAXNAMLEN], 
X  *afname, *aftype, *afvariant = NULL, str[80], messg[80], *note, 
X  *getnote(), *gettxt(), *vnum(), *getattr(), *as;
X  int truth = TRUE;
X  Af_attrs reqattrs, busyattrs, sattrs;
X  Af_key busy, lastsave, skey, *newkey, ngkey, tmpkey;
X  Af_set junkset;
X
X  if (!fname) return;
X  
X  af_initattrs (&reqattrs);
X  getsyspath (fname, proj, spath, origpath, name); 
X               /* splits name and pathname prefix */
X
X  afname = af_afname (name);
X  aftype = af_aftype (name);
X  /* give a little feedback ... */
X  if (spath[0]) {
X    (void)sprintf (messg, "[%s]%s:", spath, name);
X  }
X  else {
X    (void)sprintf (messg, "%s:", name);
X  }
X  logmsg (messg);
X  
X  if (options & SYMNSET) {
X    af_initattrs (&sattrs);
X    (void)strcpy (sattrs.af_syspath, spath);
X    (void)strcpy (sattrs.af_name, afname);
X    (void)strcpy (sattrs.af_type, aftype);
X    (void)sprintf (str, "%s=%s", SYMNAME, symname);
X    sattrs.af_udattrs[0] = str;
X    sattrs.af_udattrs[1] = NULL;
X    af_find (&sattrs, &junkset);
X    if (af_nrofkeys(&junkset)) {
X      af_setgkey (&junkset, 0, &tmpkey);
X      (void)sprintf (messg, "symbolic name %s already in use by %s[%s]", 
X	       symname, fname, vnum(&tmpkey));
X      logerr (messg);
X      af_dropset (&junkset);
X      af_dropkey (&tmpkey);
X      abort_this (FALSE);
X    }
X    else {
X      af_cleanup ();		/* ??? */
X    }
X  }
X  if (fail(af_getkey (spath, afname, aftype, AF_BUSYVERS, 
X		      AF_BUSYVERS, afvariant, &busy))) {
X    (void)sprintf (messg, "%s[busy]", fname);
X    af_perror (messg);
X    abort_this (TRUE);
X  }
X
X  if (fail(af_gattrs (&busy, &busyattrs))) {
X    (void)sprintf (messg, "Cannot access attributes of %s.", name);
X    af_perror (messg);
X    af_dropkey (&busy);
X    abort_this(TRUE);
X  }
X  if (fail(af_getkey (spath, afname, aftype, AF_LASTVERS,
X		      AF_LASTVERS, afvariant, &lastsave))) {
X    logmsg ("creating archive");
X    if (options & TXTFSET) {
X      note = gettxt (tfname);
X    }
X    else {
X      note = getnote ("How about describing the purpose of this document ?", 
X		      truth, TRUE, (char *)NULL);
X    }
X    if (lockeruid(vc_lock_g(&busy, (Uid_t)getuid())) != (Uid_t)getuid()) {
X      af_perror ("cannot lock archive");
X      af_dropkey (&busy);
X      abort_this (TRUE);
X    }
X    if (fail(af_saverev (&busy, &skey))) {
X      af_perror (fname);
X      af_dropkey (&busy);
X      abort_this(TRUE);
X    }
X    newkey = &skey;
X    ThisTransaction.tr_done = TRUE;
X    if (options & SUBMIT) {
X      af_sstate (newkey, AF_PROPOSED);
X      af_sstate (newkey, AF_PUBLISHED);
X    }
X    (void)sprintf (messg, "saved version %s", vnum (newkey));
X    logmsg (messg);
X  }    /* This was handling of newly created archive */
X  else {
X#ifdef PROJIMPL
X    if (!mylock (&busy, proj)) /* { */ /* -- emacs c-mode */
X#else
X      if (!mylock (&busy, (Project *)NULL)) {
X#endif
X	(void)sprintf (messg, "%s not saved.", fname);
X	logmsg (messg);
X	af_dropkey (&busy);
X	abort_this (FALSE);
X      }
X    if (changed (&busy, &lastsave, &truth)) { 
X      /* Version alias problem: copy or ref */
X      if (options & TXTFSET) {
X	note = gettxt (tfname);
X      }
X      else if (options & MSGSET) {
X	note = vcomment;
X      }
X      else {
X	char *intent = (char *)0;
X	if (options & (LCKGIVEUP | SUBMIT))
X	  intent = af_rudattr (&busy, INTENT);
X	note = getnote ("Do you want to comment your modifications ?", truth, 
X			FALSE, intent);
X	if (intent) free (intent);
X	af_sudattr (&busy, AF_REMOVE, INTENT);
X      }
X      if (fail(af_saverev (&busy, &skey))) {
X	af_perror (fname);
X	af_dropkey (&busy);
X	abort_this(TRUE);
X      }
X      newkey = &skey;
X      ThisTransaction.tr_done = TRUE;
X      af_sudattr (newkey, AF_REMOVE, INTENT);
X      if (options & NEWGEN) {
X	if (myproject(proj)) {
X	  af_newgen (newkey, &ngkey);
X	  (void)sprintf (messg, 
X		   "saved version %s (aliassed by ",
X		   vnum (newkey));
X	  (void)sprintf (messg, "%s%s due to new generation)", messg, vnum(&ngkey)); 
X	  logmsg (messg);
X	  af_dropkey (newkey);
X	  newkey = &ngkey;
X	  if (options & SUBMIT)
X	    setpublished (newkey);
X	}
X	else {
X	  logmsg ("You must be project-admin to increase generation number.");
X	}
X      }
X      else {
X	(void)sprintf (messg, "saved version %s", vnum (newkey));
X	logmsg (messg);
X	if (options & SUBMIT) 
X	  setpublished (newkey);
X      }
X    }
X    else {
X      if (options & SUBMIT) {
X	char *intent = (char *)0;
X	intent = af_rudattr (&busy, INTENT);
X	note = getnote ("Do you want to comment your modifications ?", truth,
X			FALSE, intent);
X	if (intent) free (intent);
X	af_sudattr (&busy, AF_REMOVE, INTENT);
X	setpublished (&lastsave);
X	(void)sprintf 
X	  (messg, "%s set to state \"published\" (no changes to be saved)",
X	   fname);
X	logmsg (messg);
X	newkey = &lastsave;
X      }
X      else {
X	(void)sprintf (messg, "%s not saved.", fname);
X	logmsg (messg);
X	af_dropkey (&busy);
X	abort_this(FALSE);
X      }
X    }
X  }
X  /* If we get here, something has been saved -- set note */
X  if (fail(af_snote (newkey, note))) {
X    af_perror ("");
X  }
X  if (options & SYMNSET) {
X    (void)sprintf (str, "%s=%s", SYMNAME, symname);
X    as = str;
X    af_sudattr (newkey, AF_ADD, as);
X  }
X  if (options & SETVNUM) {
X    if (!(mkvno(vnum(newkey)) == newvnum)) { /* do nothing */
X      if (af_svnum (newkey, gen(newvnum), rev(newvnum)) < 0) {
X	(void)sprintf (messg, "version number %d.%d too small for %s.",
X		 gen(newvnum), rev(newvnum), fname );
X	logerr (messg);
X      }
X    }
X  }
X  if (options & ATTRDEF) {
X    as = getattr (atr_fname, proj, aftype, REWIND);
X    af_sudattr (newkey, AF_ADD, as);
X    while (as=getattr (atr_fname, proj, aftype, NEXT)) {
X      af_sudattr (newkey, AF_ADD, as);
X    }
X  }
X  if (options & LCKGIVEUP) {
X    if ((lockeruid(vc_unlock_g(&busy))) != (Uid_t)getuid()) {
X      af_perror ("af_unlock: foul");
X    }
X  }
X  /* right before we are done, release the version lock on new version */
X  (void)vc_unlock_v(newkey);
X  af_dropkey (newkey);
X  af_dropkey (&busy);
X}
X
Xchanged (new, old, realtruth) Af_key *new, *old; int *realtruth; {
X/*
X * Return true if new and old are actually different OR deposit is
X * forced OR if user says 'yes' when asked whether an unchanged version
X * shall be saved anyway.
X * As AFS is still in the tests, this is programmed very defensively.
X */
X  FILE *newf, *oldf;
X  Af_attrs newat, oldat;
X  char *news, *olds, *malloc(), messg[80];
X
X  *realtruth = TRUE;  /* initially assume that something has act. changed */
X  if (fail(af_gattrs (new, &newat))) {
X    af_perror ("busy-version");
X  }
X  if (fail(af_gattrs (old, &oldat))) {
X    af_perror ("lastsaved-version");
X  }
X  if (newat.af_size != oldat.af_size) {
X    return TRUE;
X  }
X  else { /* lets have a closer look at 'em */
X    if ((news = malloc ((unsigned)newat.af_size)) == NULL) {
X      (void)sprintf (messg, "Can't malloc %d bytes.", newat.af_size);
X      logmsg (messg);
X      abort_this(TRUE);
X    }
X    if ((olds = malloc ((unsigned)oldat.af_size)) == NULL) {
X      (void)sprintf (messg, "Can't malloc %d bytes.", oldat.af_size);
X      logmsg (messg);
X      free (news);
X      abort_this(TRUE);
X    }
X    if ((newf = af_open (new, "r")) == NULL) {
X      af_perror ("busy-version");
X      free (news);
X      free (olds);
X      abort_this(TRUE);
X    }
X    if ((oldf = af_open (old, "r")) == NULL) {
X      af_perror ("lastsaved-version");
X      free (news);
X      free (olds);
X      af_close (newf);
X      abort_this(TRUE);
X    }
X#ifdef ULTRIX_2_0
X    if (fread (news, sizeof (char), (unsigned)newat.af_size, newf) == NULL)
X#else
X    if (fread (news, sizeof (char), (int)newat.af_size, newf) == NULL) 
X#endif
X      {
X      logmsg ("Couldn't read busy version.");
X      free (news);
X      free (olds);
X      af_close (newf);
X      af_close (oldf);
X      abort_this (TRUE);
X    }
X#ifdef ULTRIX_2_0
X    if (fread (olds, sizeof (char), (unsigned)oldat.af_size, oldf) == NULL) 
X#else
X    if (fread (olds, sizeof (char), (int)oldat.af_size, oldf) == NULL) 
X#endif
X      {
X      logmsg ("Couldn't read lastsaved version.");
X      free (news);
X      free (olds);
X      af_close (newf);
X      af_close (oldf);
X      abort_this (TRUE);
X    }
X    af_close (newf);
X    af_close (oldf);
X    free (news);
X    free (olds);
X    if (bcmp (olds, news, (int)newat.af_size)) {
X      return TRUE;
X    }
X    else {  /* Hmmm, looks like nothing has changed ... */
X      *realtruth = FALSE; /* return value may be a lie */
X      if (options & FORCE) {
X	return TRUE;
X      }
X      else {
X	if (options & QUIETPLEASE) {
X	  return FALSE;
X	}
X	if (isatty (fileno (stdin)) && isatty (fileno (stdout))) {
X	  (void)sprintf (messg, "There are no changes with respect to the previously saved version.\nSave anyway ?");
X	  return !ask_confirm (messg, "no");
X	}
X	else return FALSE;
X      }
X    }
X  }
X}
X
Xchar *gettxt (fname) char *fname; {
X  static char *txt = EMPTYNOTE;
X  FILE *txtfil;
X  struct stat statbuf;
X  static int firsttime = TRUE;
X
X  if (firsttime) {
X    firsttime = FALSE;
X    if ((txtfil = fopen (fname, "r")) == NULL) {
X      logerr ("no descriptive text file");
X    }
X    else {
X      if (fstat (fileno(txtfil), &statbuf) == -1) {
X	perror ("couldn't stat");
X      }
X      else {
X	txt = malloc ((unsigned)statbuf.st_size);
X	if (!txt) {
X	  logerr ("not enough memory for descriptive text.");
X	  txt = EMPTYNOTE;
X	}
X	else {
X	  (void)fread (txt, sizeof (char), (Size_t)statbuf.st_size, txtfil);
X	  (void)fclose (txtfil);
X	}
X      }
X    }
X  }
X  return txt;
X}
X
Xchar *getnote (prompt, changeflg, force, intent) char *prompt, *intent; {
X  char *tmpname, *mktemp(), *edname, cmd[128], *getenv(), messg[80];
X  static char *notetxt;
X  FILE *tmpfil;
X  struct stat statbuf;
X  static int firsttime = TRUE;
X
X  if ((options & QUIETPLEASE) ||
X      (!(isatty(fileno(stdin))))) {
X    if (intent) goto retintent;
X    else return EMPTYNOTE;
X  }
X  if ((!force) && (!firsttime) && notetxt) {
X    if (ask_confirm ("Use previous log message ?", "yes")) {
X      return notetxt;
X    }
X    else {
X      free (notetxt);
X    }
X  }
X  firsttime = FALSE;
X  if (changeflg) {
X    if (!ask_confirm (prompt, "yes"))
X      if (intent) goto retintent;
X      else return EMPTYNOTE;
X  }
X  else {
X    if (ask_confirm ("The new version is unmodified. Comment it anyway ?", 
X		     "no"))
X      if (intent) goto retintent;
X      else return EMPTYNOTE;
X  }
X  tmpname = mktemp ("/tmp/afsXXXXXX");
X  Register (tmpname, TYPEF);
X  if (intent) {
X    FILE *tfd;
X    tfd = fopen (tmpname, "w");
X    if (fwrite (intent, strlen (intent), sizeof (char), tfd) != 
X	strlen (intent)) {
X      logerr ("write failure on tmp-file");
X    }
X    (void)fclose (tfd);
X  }
X  if (edname = getenv ("EDITOR")) {
X    (void)sprintf (cmd, "%s %s", edname, tmpname);
X    (void)sprintf (messg, "starting up %s ...", edname);
X    logmsg (messg);
X    if (system (cmd) == NOSHELL) {
X      logerr ("couldn't execute shell");
X    }
X    else {
X      if ((tmpfil = fopen (tmpname, "r")) == NULL) {
X	logerr ("empty logentry");
X	return EMPTYNOTE;
X      }
X      else {
X	(void)unlink (tmpname);
X	UnRegister (tmpname, TYPEF);
X	if (fstat (fileno(tmpfil), &statbuf) == -1) {
X	  perror ("couldn't stat");
X	}
X	else {
X	  notetxt = malloc ((unsigned)statbuf.st_size);
X	  if (!notetxt) {
X	    logerr ("not enough memory for note text.");
X	  }
X	  (void)fread (notetxt, sizeof (char), (Size_t)statbuf.st_size, 
X		       tmpfil);
X	  (void)fclose (tmpfil);
X	  return notetxt;
X	}
X      }
X    }
X  }
X  logerr ("You must set the EDITOR environment variable to write a note");
X  return EMPTYNOTE;   /* maybe we should try to read from stdin */
X retintent:
X  notetxt = malloc ((unsigned)(strlen (intent) + 1));
X  (void)strcpy (notetxt, intent);
X  return notetxt;
X}
X
Xsetpublished (key) Af_key *key; {
X  /* set specified version to state 'published' */
X
X  int sdiff, oldstate = af_rstate (key);
X  register int i;
X
X  if (sdiff = (AF_PUBLISHED - oldstate)) {
X    if (sdiff > 0)
X      for (i = 1; i <= sdiff; i++) {
X	if ((lockeruid(vc_lock_v(key, (Uid_t)getuid()))) != (Uid_t)getuid()) {
X	  logerr ("can't change state to published -- locked");
X	  return;
X	}
X	af_sstate (key, oldstate+i);
X	(void)vc_unlock_v(key);
X      }
X    else /* sdiff must be < 0 */
X      for (i = 1; i <= abs(sdiff); i++) {
X	if ((lockeruid(vc_lock_v(key, (Uid_t)getuid()))) != (Uid_t)getuid()) {
X	  logerr ("can't change state to published -- locked");
X	  return;
X	}
X	af_sstate (key, oldstate-i);
X	(void)vc_unlock_v(key);
X      }
X  }
X  /* else: state already is published */
X}
END_OF_FILE
if test 16567 -ne `wc -c <'src/vc/dosave.c'`; then
    echo shar: \"'src/vc/dosave.c'\" unpacked with wrong size!
fi
# end of 'src/vc/dosave.c'
fi
echo shar: End of archive 17 \(of 33\).
cp /dev/null ark17isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 33 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
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.