sccs.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,630 行 · 第 1/3 页

C
1,630
字号
						 /* metsky 12/4/86 */		{			usrerr("cannot use fix command on version 1.1 (sc24)");			rval = EX_USAGE;			break;		}		/* get the version with all changes */		rval = command(&ap[1], TRUE, "get -k");		/* now remove that version from the s-file */		if (rval == 0)			rval = command(&ap[1], TRUE, "rmdel:r");		/* and edit the old version (but don't clobber new vers) */		if (rval == 0)			rval = command(&ap[2], FALSE, "get -e -g");		break;	  case CLEAN:		if (bitset(REALUSER,cmd->sccsflags))			setuid(getuid());		rval = clean((int) cmd->sccspath, ap);		break;	  case UNEDIT:		for (argv = np = &ap[1]; *argv != NULL; argv++)		{			if (unedit(*argv))				*np++ = *argv;		}		*np = NULL;		/* 		 * remove g-files here rather than in "unedit", so that		 * the UID can stay at real user -- depp (06Dec84)		 */		setuid(getuid());		for (argv = np = &ap[1]; *argv != NULL; argv++)		{			if (rmgfile(*argv))				*np++ = *argv;		}		*np = NULL;		/* get all the files that we unedited successfully */		if (np > &ap[1])			rval = command(&ap[1], FALSE, "get");		break;	  case DIFFS:		/* diff between s-file & edit file */		/* find the end of the flag arguments */		for (np = &ap[1]; *np != NULL && **np == '-'; np++)			continue;		argv = np;		/* for each file, do the diff */		p = argv[1];		while (*np != NULL)		{			/* messy, but we need a null terminated argv */			*argv = *np++;			argv[1] = NULL;			i = dodiff(ap, tail(*argv));			if (rval == 0)				rval = i;			argv[1] = p;		}		break;	  case DODIFF:		/* internal diff call */		setuid(getuid());		for (np = ap; *np != NULL; np++)		{			if ((*np)[0] == '-' && (*np)[1] == 'C')				(*np)[1] = 'c';		}		/* insert "-" argument */		np[1] = NULL;		np[0] = np[-1];		np[-1] = "-";		/* execute the diff program of choice */# ifndef V6		execvp("diff", ap);# endif		execv(cmd->sccspath, argv);		syserr("cannot exec %s (sc6)", cmd->sccspath);		exit(EX_OSERR);	  case ENTER:		/* enter new sccs files */		/* skip over flag arguments */		for (np = &ap[1]; *np != NULL && **np == '-'; np++)			continue;		argv = np;		/* do an admin for each file */		p = argv[1];		while (*np != NULL)		{			printf("\n%s:\n", *np);			strcpy(buf, "-i");			gstrcat(buf, *np, sizeof(buf));			ap[0] = buf;			argv[0] = tail(*np);			argv[1] = NULL;			rval = command(ap, TRUE, "admin");			argv[1] = p;			if (rval == 0)			{				strcpy(buf, ",");				gstrcat(buf, tail(*np), sizeof(buf));				if (link(*np, buf) >= 0)					unlink(*np);			}			np++;		}		break;	  default:		syserr("oper %d (sc7)", cmd->sccsoper);		exit(EX_SOFTWARE);	}# ifdef DEBUG	if (Debug)		printf("command: rval=%d\n", rval);# endif	return (rval);}/***  LOOKUP -- look up an SCCS command name.****	Parameters:**		name -- the name of the command to look up.****	Returns:**		ptr to command descriptor for this command.**		NULL if no such entry.****	Side Effects:**		none.*/struct sccsprog *lookup(name)	char *name;{	register struct sccsprog *cmd;	for (cmd = SccsProg; cmd->sccsname != NULL; cmd++)	{		if (strcmp(cmd->sccsname, name) == 0)			return (cmd);	}	return (NULL);}/***  CALLPROG -- call a program****	Used to call the SCCS programs.****	Parameters:**		progpath -- pathname of the program to call.**		flags -- status flags from the command descriptors.**		argv -- an argument vector to pass to the program.**		forkflag -- if true, fork before calling, else just**			exec.****	Returns:**		The exit status of the program.**		Nothing if forkflag == FALSE.****	Side Effects:**		Can exit if forkflag == FALSE.*/callprog(progpath, flags, argv, forkflag)	char *progpath;	short flags;	char **argv;	bool forkflag;{	register int i;	auto int st;# ifdef DEBUG	if (Debug)	{		printf("callprog:\n");		for (i = 0; argv[i] != NULL; i++)			printf("\t\"%s\"\n", argv[i]);	}# endif	if (*argv == NULL)		return (-1);	/*	**  Fork if appropriate.	*/	if (forkflag)	{# ifdef DEBUG		if (Debug)			printf("Forking\n");# endif		i = fork();		if (i < 0)		{			syserr("cannot fork (sc8)");			exit(EX_OSERR);		}		else if (i > 0)		{			wait(&st);			if ((st & 0377) == 0)				st = (st >> 8) & 0377;			if (OutFile >= 0)			{				close(OutFile);				OutFile = -1;			}			return (st);		}	}	else if (OutFile >= 0)	{		syserr("callprog: setting stdout w/o forking (sc23)");		exit(EX_SOFTWARE);	}	/* set protection as appropriate */	if (bitset(REALUSER, flags))		setuid(getuid());	/* change standard input & output if needed */	if (OutFile >= 0)	{		close(1);		dup(OutFile);		close(OutFile);	}		/* call real SCCS program */	execv(progpath, argv);	syserr("cannot execute %s (sc6)", progpath);	exit(EX_UNAVAILABLE);	/*NOTREACHED*/}/***  MAKEFILE -- make filename of SCCS file****	If the name passed is already the name of an SCCS file,**	just return it.  Otherwise, munge the name into the name**	of the actual SCCS file.****	There are cases when it is not clear what you want to**	do.  For example, if SccsPath is an absolute pathname**	and the name given is also an absolute pathname, we go**	for SccsPath (& only use the last component of the name**	passed) -- this is important for security reasons (if**	sccs is being used as a setuid front end), but not**	particularly intuitive.****	Parameters:**		name -- the file name to be munged.****	Returns:**		The pathname of the sccs file.**		NULL on error.****	Side Effects:**		none.*/char *makefile(name)	char *name;{	register char *p;	char buf[3*FBUFSIZ];	extern char *malloc();	extern char *rindex();	extern bool safepath();	extern bool isdir();	register char *q;	p = rindex(name, '/');	if (p == NULL)		p = name;	else		p++;	/*	**  Check to see that the path is "safe", i.e., that we	**  are not letting some nasty person use the setuid part	**  of this program to look at or munge some presumably	**  hidden files.	*/	if (SccsDir[0] == '/' && !safepath(name))		return (NULL);	/*	**  Create the base pathname.	*/	/* first the directory part */	if (SccsDir[0] != '\0' && name[0] != '/' && strncmp(name, "./", 2) != 0)	{		gstrcpy(buf, SccsDir, sizeof(buf));		gstrcat(buf, "/", sizeof(buf));	}	else		gstrcpy(buf, "", sizeof(buf));		/* then the head of the pathname */	gstrncat(buf, name, p - name, sizeof(buf));	q = &buf[strlen(buf)];	/* now copy the final part of the name, in case useful */	gstrcpy(q, p, sizeof(buf));	/* so is it useful? */	if (strncmp(p, "s.", 2) != 0 && !isdir(buf))	{		/* sorry, no; copy the SCCS pathname & the "s." */		gstrcpy(q, SccsPath, sizeof(buf));		gstrcat(buf, "/s.", sizeof(buf));		/* and now the end of the name */		gstrcat(buf, p, sizeof(buf));	}	/* if i haven't changed it, why did I do all this? */	if (strcmp(buf, name) == 0)		p = name;	else	{		/* but if I have, squirrel it away */		p = malloc(strlen(buf) + 1);		if (p == NULL)		{			perror("Sccs: no mem (sc10)");			exit(EX_OSERR);		}		strcpy(p, buf);	}	return (p);}/***  ISDIR -- return true if the argument is a directory.****	Parameters:**		name -- the pathname of the file to check.****	Returns:**		TRUE if 'name' is a directory, FALSE otherwise.****	Side Effects:**		none.*/boolisdir(name)	char *name;{	struct stat stbuf;	return (stat(name, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR);}/***  SAFEPATH -- determine whether a pathname is "safe"****	"Safe" pathnames only allow you to get deeper into the**	directory structure, i.e., full pathnames and ".." are**	not allowed.****	Parameters:**		p -- the name to check.****	Returns:**		TRUE -- if the path is safe.**		FALSE -- if the path is not safe.****	Side Effects:**		Prints a message if the path is not safe.*/boolsafepath(p)	register char *p;{	extern char *index();	if (*p != '/')	{		while (strncmp(p, "../", 3) != 0 && strcmp(p, "..") != 0)		{			p = index(p, '/');			if (p == NULL)				return (TRUE);			p++;		}	}	printf("You may not use full pathnames or \"..\"\n");	return (FALSE);}/***  CLEAN -- clean out recreatable files****	Any file for which an "s." file exists but no "p." file**	exists in the current directory is purged.****	Parameters:**		mode -- tells whether this came from a "clean", "info", or**			"check" command.**		argv -- the rest of the argument vector.****	Returns:**		none.****	Side Effects:**		Removes files in the current directory.**		Prints information regarding files being edited.**		Exits if a "check" command.*/clean(mode, argv)	int mode;	char **argv;{	struct direct *dir;	char buf[FBUFSIZ];	char *bufend;	register DIR *dirfd;	register char *basefile;	bool gotedit;	bool gotpfent;	FILE *pfp;	bool nobranch = FALSE;	extern struct pfile *getpfent();	register struct pfile *pf;	register char **ap;	extern char *username();	char *usernm = NULL;	char *subdir = NULL;	char *cmdname;	/*	**  Process the argv	*/	cmdname = *argv;	for (ap = argv; *++ap != NULL; )	{		if (**ap == '-')		{			/* we have a flag */			switch ((*ap)[1])			{			  case 'b':				nobranch = TRUE;				break;			  case 'u':				if ((*ap)[2] != '\0')					usernm = &(*ap)[2];				else if (ap[1] != NULL && ap[1][0] != '-')					usernm = *++ap;				else					usernm = username();				break;			}		}		else		{			if (subdir != NULL)				usrerr("too many args (sc11)");			else				subdir = *ap;		}	}	/*	**  Find and open the SCCS directory.	*/	gstrcpy(buf, SccsDir, sizeof(buf));	if (buf[0] != '\0')		gstrcat(buf, "/", sizeof(buf));	if (subdir != NULL)	{		gstrcat(buf, subdir, sizeof(buf));		gstrcat(buf, "/", sizeof(buf));	}	gstrcat(buf, SccsPath, sizeof(buf));	bufend = &buf[strlen(buf)];	dirfd = opendir(buf);	if (dirfd == NULL)	{		usrerr("cannot open %s (sc12)", buf);		return (EX_NOINPUT);	}	/*	**  Scan the SCCS directory looking for s. files.	**	gotedit tells whether we have tried to clean any	**		files that are being edited.	*/	gotedit = FALSE;	while (dir = readdir(dirfd)) {		if (strncmp(dir->d_name, "s.", 2) != 0)			continue;				/* got an s. file -- see if the p. file exists */		gstrcpy(bufend, "/p.", sizeof(buf));		basefile = bufend + 3;		gstrcpy(basefile, &dir->d_name[2], sizeof(buf));		/*		**  open and scan the p-file.		**	'gotpfent' tells if we have found a valid p-file		**		entry.		*/		pfp = fopen(buf, "r");		gotpfent = FALSE;		if (pfp != NULL)		{			/* the file exists -- report it's contents */			while ((pf = getpfent(pfp)) != NULL)			{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?