[comp.unix.questions] Usage of SCCS

MIKEY%FLOPN2%eg.ti.com@RELAY.CS.NET (10/03/87)

We are currently in the process of setting up a XENIX machine for our
department. I, (oh joy! oh joy!), have been chosen to the be system admin-
istrator. Not because I'm a GURU, but because I'm the only one with any 
UNIX/XENIX experience. Oh well...

I am interested in using SCCS for configuration management on some projects
that we are currently working on (as well as future applications). One of the
nice features of SCCS, or so I think, is the ability to limit access to files
to a restricted group of people. However, in order to do this, an interface
program must(?) exist.

The discussion in Volume V of the Unix Programmers Manual makes mention of this
interface program, but never really goes into enough detail on just exactly
what it does or how it does it. What I really need to see is any examples that
anyone might have of this interface routine. 

Also, any pointers in the direction of references on SCCS, where I might
begin to look for information on how to perform the duties/tasks of system
administration, any anything else you think are of any importance!

Thanks in advance!!
Regards,

----------------------------------------------------------------------------
Mike McIntyre			EMAIL:  MIKEY%FLOPN2%TI-EG@CSNET-RELAY.ARPA
				USMAIL:	6500 Chase Okes Blvd.
					P.O. Box 869305
					M/S 8404
					Plano,	TX	75086
----------------------------------------------------------------------------
"You're traveling through another dimension, a dimension not only of sight
 and sound, but of mind; a journey into a wondrous land whose boundaries
 are that of imagination -- Next stop, the Twilight Zone!"

gwyn@brl-smoke.UUCP (10/04/87)

In article <9597@brl-adm.ARPA> MIKEY%FLOPN2%eg.ti.com@RELAY. (Mike McIntyre -- (214) 575-2983) writes:
>The discussion in Volume V of the Unix Programmers Manual makes mention of this
>interface program, but never really goes into enough detail on just exactly
>what it does or how it does it. What I really need to see is any examples that
>anyone might have of this interface routine. 

The following relies on the fact that the SCCS utilities use the System V
setuid() facilities to revert to the real UID.  The SCCS utilities do not
do this properly on Berkeley kernels (e.g. under the BRL UNIX System V
emulation).

/*
	SCCS -- provide controlled access to SCCS archives

	last edit:	83/09/14	D A Gwyn

Installation:
	All SCCS archives and their directories belonging to the project
	administrator optionally may be readable by authorized editors
	but should not be writable by them.  The archives must have all
	authorized editors other than the administrator added to their
	user lists via "admin -a".

	The "SCCS" program must be executable by authorized editors but
	not writable by them; it must be owned by the project
	administrator and set-UID to its owner.

	System SCCS utility binaries must be safe from unauthorized
	tampering.

Use:
	Authorized editors may invoke SCCS utilities by appending the
	appropriate command as arguments to "SCCS", as in
		$ SCCS get -e s.archive
*/
static char	sccsid[] = "@(#)SCCS.c	1.2";

#include	<fcntl.h>
#include	<stdio.h>
#include	<string.h>
#include	<sys/types.h>
#include	<sys/stat.h>

extern void	exit();
extern char	*malloc();
extern int	close(), execve(), fstat(), open();

#define DEVNULL "/dev/null"		/* black hole pathname */
#define MAXFD	19			/* maximum file descriptor */
#define SCCSBIN "/usr/bin/"		/* where SCCS commands reside --
					   important!  note the slash */

typedef int	bool;			/* Boolean data */
#define false		0
#define true		1

static char	*argv0 = NULL;		/* "SCCS" program name */

static void	DoCmd(), Fatal();
static bool	CheckFDs();
static char	*GetCmd();

main( argc, argv )
	int		argc;
	register char	**argv;
	{
	register char	*path;		/* SCCS command pathname */

	if ( !CheckFDs() )		/* check file descriptors */
		exit( 10 );		/* something is wrong! */

	if ( argc <= 1 )		/* check argument count */
		{
		argv0 = "SCCS"; 	/* for Fatal() */
		Fatal( "Usage: SCCS sccs_command arg ..." );
		}
	argv0 = *argv++;		/* remember invocation */
	/* argv is now the user SCCS command argument list */

	if ( (path = GetCmd( argv )) == NULL )
		Fatal( "Not a controlled command" );

	DoCmd( path, argv );		/* exec */

	/*NOTREACHED*/
	}


static bool
CheckFDs()				/* check file descriptors */
	{
	struct stat	sbuf;		/* dummy for fstat() */
	register int	fd;		/* file descriptor */

	for ( fd = 0; fd <= MAXFD; ++fd )
		if ( fd > 2 )
			(void)close( fd );	/* for safety */
		else			/* fd 0, 1, or 2 */
			if ( fstat( fd, &sbuf ) != 0
			  && open( DEVNULL, fd == 0 ? O_RDONLY
						    : O_WRONLY
				 ) != fd	/* forestall fraud */
			   )
				return false;	/* we tried! */

	return true;			/* okay */
	}


static char	*
GetCmd( argv )				/* return SCCS command */
	register char	**argv; 	/* user argument list */
	{
	static char	dir[] = SCCSBIN;/* where SCCS commands reside */
	static char	*ok_cmd[] =	/* controlled commands */
		{
		"cdc",
		"delta",
		"get",
		"prs",
		"rmdel",
		"sact",
		"unget",
		NULL
		};
	register char	**okp;		/* -> ok_cmd[] */

	for ( okp = ok_cmd; *okp != NULL; ++okp )
		if ( strcmp( *okp, *argv ) == 0 )
			{		/* controlled command */
			register char	*path;	/* command pathname */

			if ( (path = malloc( sizeof dir +
						(unsigned)strlen( *okp )
					   )
			     ) == NULL
			   )
				Fatal( "Out of space" );
			(void) strcat( strcpy( path, dir ), *okp );
			return path;
			}

	return NULL;			/* command not found */
	}


static void
DoCmd( path, argv )			/* execute SCCS command */
	char		*path;		/* command pathname */
	char		**argv; 	/* user argument list */
	{
	static char	*envp[] = { NULL };	/* empty environment */

	(void) execve( path, argv, envp );

	Fatal( "Can't execute command" );
	}


static void
Fatal( message )			/* print message then quit */
	char	*message;		/* error message */
	{
	(void) fputs( argv0, stderr );
	(void) fputs( ": ", stderr );
	(void) fputs( message, stderr );
	(void) putc( '\n', stderr );

	exit( 1 );
	}