Cover V02, I04
Article
Figure 1
Figure 2
Listing 1
Listing 2
Listing 3

jul93.tar


SCCS: Keeping It under Control

Chris Hare

Why Use SCCS or RCS?

Recently, several colleagues and I were attempting to discover who had made the last set of changes to a particular file. There was no easy way to tell. All of us had the requisite permissions to edit the file, but there was no indication of who made the changes. At this point we began to consider whether we might use a tool such as SCCS (the Source Code Control System), which is a part of the UNIX development system. SCCS creates a read-only version of the actual file, so that changes must be forced through the SCCS system. In addition, the SCCS lines inserted to keep track of the version information contain the name of the user who made the last changes.

As a means of protecting ourselves and to keep a record of changes to the files, we decided to begin using SCCS on the various configuration files, starting first with our master Domain Name Server files. Since then, it has been easy to find out what changed when and who made the change. Equally important, SCCS has made it easy to go back to the previous version if something became broken as things were updated.

In this article I describe how SCCS works and how it can help you manage both your configuration files and plain text documents. Since SCCS is available to me, the article focuses on that system. If you do not have SCCS, you may want to acquire one of the many Revision Control Systems (RCSs) that are freely available.

Terminology

SCCS makes special use of certain terms.

  • A DELTA is a set of changes which have been made to a file which is under SCCS custody.

  • An SID is an SCCS IDentification number. The SID defines the release and version number of the file. This number is formed by a sequence of up to four numbers:

    release.level.branch.sequence

  • An MR is a number used to track the changes in the source file (e.g., bug report numbers).

    Protection

    Most of the protections implemented by SCCS rely upon the operating system to enforce and restrict changes made by non-SCCS commands. Protections directly implemented by SCCS are the release lock, the release floor and ceiling flags, and the user list.

    A new file created for SCCS control via the SCCS admin command (which I discuss later) receives a protection mode of read-only (444), which prevents non-SCCS commands from making changes to it. As a further protection, the directory containing the SCCS files should not be publicly writeable (protection mode 755, which allows only the directory owner to add or delete files from it), and both SCCS files and temporary files should be kept in this directory.

    There should be only one link to the SCCS files. This is because a number of files are created to indicate that the file is being edited, and name confusion could result in lost edits or difficulties later.

    The SCCS Command Set

    The SCCS command set consists of thirteen commands.

    admin creates and administers files under SCCS control.

    cdc changes delta commentary.

    comb combines multiple deltas into one.

    delta makes a change to an SCCS file.

    get retrieves a copy of an SCCS file, either for use or for editing.

    help displays messages for the SCCS error codes.

    prs prints information about SCCS files.

    sact lists the SCCS files out for editing.

    sccsdiff prints the differences between releases of the same file.

    unget cancels a get -e prior to running delta.

    val validates an SCCS file.

    vc is a filter that may be used for version control.

    what searches files for the @(#) sequence, and prints those lines.

    Creating an SCCS File

    You must use the admin command to create an SCCS file. This command places the file under the custody and watchful eye of SCCS and assigns an initial SID to the file. By default, the initial assignment is Release 1, Version 1 -- or 1.1.

    For example, to place a file called names under SCCS custody, you would enter

    admin -inames s.names

    SCCS filenames consist of the original filename prefixed with s., so in this example, I have instructed the admin command to create a new SCCS file called s.names, and to initialize the contents of the file using the data in the file called names.

    If the command line does not include -i filename, the command reads from ROM standard input to create the initial delta. Note that you can create only one SCCS file at a time using admin. If you need to create a number of new SCCS files, you can use the -n flag, as in the following example, to create empty files.

    admin -n s.a s.b

    Once you've created the s.file, delete the original. This ensures that all changes will be made to the SCCS version.

    SCCS Data

    The SCCS file contains a number of pieces of information aside from the file itself. The information lines begin with a Control-A followed by a single letter and each line has a specific meaning.

    The first line is a checksum for entire file, not including the checksum itself.

    The "s" line lists the number of lines inserted/deleted/unchanged, respectively.

    The "d" line indicates the type of delta (D is normal, R is removed), the SID of the file, the date and time of creation of the delta, the username which corresponds to the real userid who created it, and finally the serial numbers of the delta and its predecessor.

    If the "i", "x", and "g" lines are present, they contain the serial numbers of deltas which have been included, excluded, and ignored respectively. These lines are optional.

    The "m" lines contain MR or Modification Request numbers, one per line, which are associated with the delta, and the "c" lines contain a brief comment on what changed in this delta.

    The "e" line indicates the end of the delta table entry.

    The lines "u" and "U" mark an area where you can specify which users may (or may not) make changes to this file. If there are no names between these lines, then all users can make deltas. The names specified here can be either login names or their associated numerical UIDS. An exclamation point in front of login name or UID indicates that this user cannot make deltas.

    You can add or eliminate users from the list of those authorized to make deltas by using the admin command with the appropriate option (-alogin option, where login is the name or UID of the user to be added, -elogin for a user to be removed).

    The "t" and "T" lines mark an area that can contain descriptive text. The text can be added to the SCCS file using the -t keyword on the admin command line

    The "f" line allows for specification of flags. The flags available for the admin command are shown in Figure 1. The format in the file is

    ^Af <L>ag <MIO><N>	al text

    Enabling MR Numbers

    Modification Request numbers can be useful in tracking the changes in large software projects. Such a number allows for the tracking not only of the initial request (a bug report, for example), but also of the disposition of the request.

    To enable MR tracking, use the admin command

    admin -fv s.names

    which turns on the v flag in the SCCS header of the file. This flag is used by the delta command to get an MR number from the user when the delta is created.

    After the initial delta where an MRU is requested, the top of the SCCS header looks like:

    ^Ah30338
    ^As 00002/00000/00006
    ^Ad D 1.4 93/02/27 13:37:04 chare 4 3
    ^Am 93.02.26.001
    ^Ac added more names
    ^Ae

    The "m" line shows the MR number entered when the user was prompted by the delta command.

    Getting an SCCS File

    You use the get command to retrieve a file from SCCS either for editing or for use in another program. get will place a copy of the current SID and data for that SID into the non-s.file file. The new file is known as the g-file.

    Thus the command

    get s.names

    retrieves a read-only version of the file called names. get prints the revision level of the retrieved file and the number of lines retrieved.

    Editing this file is not permitted; that is, any edits you make to the file will be lost the next time the file is retrieved. To edit the file, you must use the -e option with the get command. This option causes get to assign a new delta and create a g-file for you to edit.

    In either case, you can also retrieve a specific version of the file other than the latest by specifiying the relase which you want on the command line, as in:

    $ get -r1.1 s.names

    Using this approach it is very easy to backtrack to working code or configuration files.

    You can also use get to change the revision level of the file:

    $ get -e -r3 s.names
    2.1
    new delta 3.1
    8 lines

    get will report the old SID (2.1), and the new SID once the delta is applied (3.1).

    Same File, Multiple Edits

    To allow the same file to be edited by multiple users at the same time and at the same revision level, you must either set the j- flag with admin or use a delta command in the course of the in-progress edit. To set the j- flag, use admin like this:

    $ admin -fj s.names

    Now different users can do multiple edits of the same SID. Notice that the emphasis is on different users. If the same file is retrieved for editing in the same directory, then the subsequent get will fail as there will be a p-file for that SID and file already in the current directory.

    This recalls the problem mentioned earlier in the section on protection. If the directories are set to 755, only the user who owns the directory will be able to create the temporary files for editing.

    You can circumvent this by using a project-specific interface program which is owned by the SCCS administrator of the project (who will also own all the files and diretories) and is SUID. This enables other users to have access to the files and programs.

    Recording the Changes

    SCCS itself will keep track of the lines inserted and deleted, etc., in order to be able to recreate any version of the file.

    To accomplish this, use the delta command as follows:

    $ delta s.names
    comments? Added more names
    1.3
    3 inserted
    0 deleted
    6 unchanged

    delta responds by asking for a comment which describes what you did, and then lists the current SID, followed by the number of affected lines. It then updates the s-file based upon the changes in the g-file. In addition, delta looks at a third file called the p-file.

    The p-file, which in the case of our names file would be called p.names, contains the old SID, the new SID, username, and the date and time of the creation of the delta. If you have configured the file to use MR numbers, then delta will prompt for the MR number before asking for the comments for the delta.

    If you prefer, you can provide this information on the command line rather than entering it interactively. The next example demonstrates the use of the -y option for the comment, and the -m option for the MR number.

    delta -y "Added more names" -m "93.02.26.002" s.names

    Remember that the -m flag can only be used with the delta command if the SCCS file was initially set up with the v flag on the admin command line.

    Unlike admin, delta can be used on multiple files, but there are some constraints. If you are using MR numbers, then all of the files must have the v flag set for MR number tracking. If the first file on the command line doesn't have this flag, then none of the files can have it.

    The information in the p-file and the comments form the new entry at the top of the SCCS file.

    Listing 1 shows a sample shell script which I use to get a file for editing, edit it, and record the delta.

    Reviewing the Delta History

    If you want simply to review the commentary and other information associated with a file without reading the file itself, you can use the get command to create what is called an l-file. This file contains information on all of the changes that have been applied to the SCCS file.

    If you prefer simply to display the information, add the p option, which causes get to print the information to standard out rather than write it to a file.

    Using the prs Command

    An alternate method of information about a file is to use the prs command. This command will print all or parts of the specified s-file. Non-SCCS file, or unreadable files are silently ignored.

    For example,

    $ prs s.files

    prints the information on each delta which has been applied to the file.

    prs can also be used to print various parts of the file, and can intersperse SCCS keywords within the text. (SCCS keywords and get keywords are different entities; SCCS keywords have a format of the type :I:, while get keywords look like #I#.)

    The prs command has the capability of formatting the information in many different ways -- you specify your preference through what is called a dataspec. The dataspec is entered on the command line, preceded by the option -d and is followed by the keywords associated with the data you want.

    If you are working on C code, or some type of file which expects to find a character to delimit a comment, you will need to specify something in your file generation process to include these in the finished product. Listing 2 shows a sample which we use for the maintenance of our DNS files.

    Keeping Track

    If you are the only person working on the files controlled by SCCS, you will have little trouble keeping abreast of what's being edited. However, since it's more often the case that a number of programmers or administrators may be working on the same file, SCCS provides a special variant of the prs command -- the sact command -- to keep track. This command reports on the files which are currently out for edit. It takes only one argument, which is the name or names of the file(s) you want to check on, or the name of a directory which contains SCCS files.

    sact first checks the list of files for those which are out on edits. It reports an error on any file that isn't an SCCS file (that is, that doesn't start with s.). Finally, for all SCCS files out for edit, it displays the content of the p-file, listing the delta, date, and time, and the ID of the user who executed the get -e.

    Removing Deltas

    It sometimes occurs that an entire delta must be deleted. If the problem is with the most recent delta, then you can remove the offending delta and related changes. This command should be used regularly, but only when it is necessary to correct a number of global errors.

    The command is rmdel, and there are a number of restrictions to its use:

  • The delta must be the most recent, or have no other deltas following it. For example, if the current SID of a file is 2.3, and you want to delete delta 2.2, then you must first delete delta 2.3, and then delta 2.2.

  • The specified SID cannot be out for editing.

  • The login name or UID of the user requesting the delta must be in the user list, or the user list must be empty.

  • The release cannot be locked against editing. If it is, then the delta removal will fail.

    You must run the command with the complete SID to be removed. For example, if you want to remove SID 2.1 from the file s.names, you would enter the command as

    $ rmdel -r2.1 s.names 

    If the file is being edited, then you will see this response to the rmdel command:

    ERROR [s.names]: being edited -- sid is in p-file (rc12)

    If the SID requested is not the current SID, then you will see this message:

    ERROR [s.names]: not a 'leaf' delta (rc5)

    This means that there is a delta which follows the specified one.

    Combining Deltas

    You may also have occasion to combine deltas (you might hope to save some disk space, for example; though combining deltas in fact may take more disk space). The command for this purpose is the comb command. Using this command will effectively alter the shape of the SCCS tree by removing and merging multiple deltas into a single delta.

    comb works by generating a shell procedure on the standard output which reconstructs the SCCS file by removing unwanted deltas and combining others. In the absence of any options, comb will simply preserve the leaf deltas, and the minimum number of ancestors to preserve the shape of the tree.

    The command

    comb -s s.names 

    will generate a shell procedure which reports how much space (if any) will be saved. The resulting shell program is shown in Listing 3.

    So What Changed?

    A key benefit of using SCCS is that you can find out what changed in each revision. There are a couple of methods of doing this: one with get, the other with sccsdif.

    With get you would use the -m option, which instructs get to print the SID responsible for adding the line at the beginning of each line. For the s.names file, you would enter

    $ get -m -p s.names

    You could instead use the sccsdif command, which determines and prints the differences between two releases of the same file. The two releases to be checked are specified as the first two arguments to sccsdif, followed by the name of the file.

    $ sccsdiff -r1.6 -r3.2 s.names

    The output of the command is the same as with diff.

    Auditing

    If an SCCS file becomes corrupted or damaged, you must the admin command again to rebuild the s-file. In fact, no SCCS command except for admin will even process the corrupted file.

    It's a good idea to audit SCCS files regularly for corruption. To do this, use the admin command with the -h option. This will verify the contents of the file against the checksum which is at the top of the SCCS file. If there is a problem, you may edit the file after setting its permissions to 644.

    Once the edit is complete, run admin -h again to verify that there are no problems. If the situation appears to be resolved, run admin -z to generate a new checksum, and then run admin -h once again to verify that the file is still valid.

    If the file is severely damaged, however, it will be necessary to restore it from a backup.

    Getting Help

    SCCS provides help only in conjunction with its various error messages. The help command prints the syntax of SCCS commands, as well as information on the specified error code. The argument to be passed to help is the error code reported (in brackets) after the command failed.

    If no argument is given on the command line, then help will prompt for one. You can enter more than one error code as arguments, and each one will in turn be printed.

    The help database containing all of the error messages and information is /usr/lib/help. There is a file for each group of commands, and the related text. These are flat ASCII files, so you could print them and study them at your leisure if you wished.

    Putting It All Together

    A practical example of using SCCS is our management of the configuration files for our Domain Name Server. DNS includes a number of files that need to be controlled. All of these files are included in a Makefile, which is installed in the directory where the DNS files are (on our system this is /usr/lib/named). Here is a list of the files:

    s.named.boot	named.boot (normally in /etc)
    s.named.hosts	named.hosts - host/address information
    s.named.rev	named.rev - reversed address resolution
    s.root.cache	root.cache - root nameservers
    s.named.local	named.local - local system
    s.named.soa	named.soa - authority records

    (It is not essential that you understand the Domain Namer Server technology; the focus is on a methodology for controlling this set of files.)

    Each of the files has a header which looks like

    ;----- VERSION CONTROL ----------------------------------
    ; @(#)text	2.10 /u/chare/Filecabinet/sysadmin/sccs/s.text
    ;
    ;History
    ;-------
    ; MOD  WHO   DATE  WHAT
    ;        YYMMDD
    ; -------------------------------------------------------
    *include(DELTA)
    ;----- END ----------------------------------------------
    ;

    This header contains some get keywords which are expanded during the extraction of the file. The #W# puts in a line of text that can be picked up by the what command; the #P# is the absolute pathname of the file.

    With the exception of the line *include(DELTA), the remainder goes into the finished file as is.

    The Makefile entry which creates the named.soa file looks like this

    NAMED = named.hosts named.rev named.local [etc]
    named.soa:	$(NAMED)
    get -e -s s.named.soa
    delta -y"Increment Serial Number to activate change" s.named.soa
    get -g -lp s.named.soa | head -1  .m1
    prs -e -r`cat .m1` -d';:I:\t:P:\t:D:\t:C:' s.named.soa | grep "^;"  .m2
    
    get -s -p s.named.soa  .m4
    m4 -DDELTA=.m2 .m4  named.soa
    chmod 444 named.soa
    rm .m1 .m2 .m3 .m4
    kill -1 `cat /etc/named.pid`

    When named.soa must be changed, executing this makefile entry will perform the following steps:

  • Retrieve the named.soa file, using the -e flag to force a new delta to be created (this is so that the serial number will be incremented in the file). Note that the -s option is used to suppress output to the screen.

  • Create the delta using the -y option with the commentary text indicating that this is a serial number increase. Note that the change is applied to the SCCS file.

  • Perform another get. With the -g option, no g-file is created, and lp causes the deltas to be listed to standard output. The output is sent through the head filter, as all that's needed is the current revision level. The revision level is saved in a file in the current directory called .m1.

  • prs extracts all of the deltas applied before the current revision level. This is a little tricky, as on my version of SCCS you can't specify the -e and the -d together, unless you name the revision level. For this reason, I include the -r option. The cat .m1 gets the current revision level as determined by the preceding command. Finally, the dataspec :I:\t:P:\t:D:\t:C: creates lines which have the SID, a tab, the programmer's name, a tab, the date, a tab, and the comment from the delta. I filter that through grep looking for lines which begin with a semicolon, and save them in the file called .m2.

  • Extract the file itself, and save it in .m4.

  • Using the m4 macro preprocessor (which I won't explain here), build this file to look exactly the way I want it to. If you remember, the s.named.soa file contains the line

    *include(DELTA)

    which, in actual fact, is an m4 macro command. This include command will cause the contents of DELTA to be substituted in its place. On the command line where m4 is called, I indicate that DELTA is the output of the earlier prs command. The end result is the file named.soa.

  • Perform cleanup tasks and make a call to re-sync the nameserver.

    The finished product is shown in Figure 2.

    Conclusion

    There is a wide range of possiblilities where some form of Source Code Control System or Revision Control System can be implemented -- actual Source Code management is only one of them. As I've shown here, using SCCS in combination with other facilities, such as make and the m4 macro processor, the possibilities are almost limitless.

    About the Author

    Chris Hare is Ottawa Technical Services Manager for Choreo Systems, Inc. He has worked in the UNIX environment since 1986 and in 1988 became one of the first SCO authorized instructors in Canada. He teaches UNIX introductory, system administration, and programming classes. His current focus is on networking, Perl, and X. Chris can be reached at chare@choreo.ca, or chare@unilabs.org, which is his home.


     



  •