⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chmod.c

📁 UNIX、LINUX 环境下
💻 C
字号:
/*	Copyright (c) 1990, 1991, 1992, 1993 Novell, Inc. All Rights Reserved.	*//*	Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 Novell, Inc. All Rights Reserved.	*//*	  All Rights Reserved  	*//*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Novell Inc.	*//*	The copyright notice above does not evidence any   	*//*	actual or intended publication of such source code.	*/#ident	"@(#)chmod:chmod.c	1.9.2.5"#ident  "$Header: chmod.c 1.2 91/06/26 $"/*******************************************************************		PROPRIETARY NOTICE (Combined)This source code is unpublished proprietary informationconstituting, or derived under license from AT&T's UNIX(r) System V.In addition, portions of such source code were derived from Berkeley4.3 BSD under license from the Regents of the University ofCalifornia.		Copyright Notice Notice of copyright on this source code product does not indicate publication.	(c) 1986,1987,1988,1989  Sun Microsystems, Inc	(c) 1983,1984,1985,1986,1987,1988,1989  AT&T.	          All rights reserved.********************************************************************/ /*************************************************************************** * Command: chmod * Inheritable Privileges: P_OWNER,P_MACREAD,P_MACWRITE,P_DACREAD *       Fixed Privileges: None * Notes: changes the mode of file/directory. * ***************************************************************************//* * chmod option mode files * where  *	mode is [ugoa][+-=][rwxlstugo] or an octal number *	option is -R *//* *  Note that many convolutions are necessary *  due to the re-use of bits between locking *  and setgid */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <priv.h>#include <locale.h>#include <pfmt.h>#include <errno.h>#include <string.h>#include <limits.h>#include <unistd.h>#define	USER	05700	/* user's bits */#define	GROUP	02070	/* group's bits */#define	OTHER	00007	/* other's bits */#define	ALL	07777	/* all */#define	READ	00444	/* read permit */#define	WRITE	00222	/* write permit */#define	EXEC	00111	/* exec permit */#define	SETID	06000	/* set[ug]id */#define	LOCK	02000	/* lock permit */#define	STICKY	01000	/* sticky bit */static	char	*ms;static	char	*msp;static	int	rflag;static	mode_t	newmode(), abs(), who();static	void	errmsg(long , long , const char *, ... );static const char badstat[]	= ":5:Cannot access %s: %s\n";static const char badchmod[]	= ":13:chmod() failed on %s: %s\n";static const char errfmt[]	= ":12:%s: %s\n";static const char badmode[]	= ":14:Invalid mode\n";static	int	dochmod();static	int	chmodr();static	int	what();/* * Procedure:     main * * Restrictions:                 setlocale: 	none                 pfmt: 		none*/main(argc, argv)int argc;char **argv;{	register int i;	register char *p;	int status = 0;	(void)setlocale(LC_ALL, "");	(void)setcat("uxcore.abi");	(void)setlabel("UX:chmod");  	argv++, argc--;	while (argc > 0 && argv[0][0] == '-') {		for (p = &argv[0][1]; *p; p++)  {			if (*p == 'R') 				rflag++;			else {				goto done;			}		}		argc--, argv++;	}	/* 	 * Check for sufficient arguments 	 * or a usage error. 	 */done:	if(argc < 2){		pfmt(stderr, MM_ERROR, ":8:Incorrect usage\n");		pfmt(stderr, MM_ACTION,			":15:Usage: chmod [-R] [ugoa][+-=][rwxlstugo] file ...\n");	}		ms = argv[0];	for (i = 1; i < argc; i++)		status += dochmod(argv[i]);	exit(status);	/* NOTREACHED */}/* * Procedure:     dochmod * * Restrictions:                 lstat(2): 	none                 stat(2): 	none                 chmod(2): 	none*/static intdochmod(name)	char *name;{	static struct stat st; /* save space, recursion should not reuse */ 	int errmode;	if (lstat(name, &st) < 0) {		errmsg(MM_WARNING, 0, badstat, name, strerror(errno));		return 1;	}	if (rflag && (st.st_mode&S_IFMT) == S_IFDIR)		return chmodr(name, st.st_mode);	if ((st.st_mode & S_IFMT) == S_IFLNK) {		if (stat(name, &st) < 0) {			errmsg(MM_WARNING, 0, badstat, name, strerror(errno));			return 1;		}	}	if (chmod(name, newmode(st.st_mode, name, &errmode)) == -1) {		errmsg(MM_WARNING, 0, badchmod, name, strerror(errno));		return 1;	}	if (errmode)		return 1;	return 0;}/* * Procedure:     chmodr * * Restrictions:                 getcwd: 	none                 chmod(2): 	none                 chdir(2): 	none                 opendir: 	none*/static intchmodr(dir, mode)	char *dir;	mode_t  mode;{	register DIR *dirp;	register struct dirent *dp;	char savedir[PATH_MAX];	int ecode, errmode;	if (getcwd(savedir, sizeof(savedir)) == 0) { 		errmsg(MM_WARNING, 255, ":129:Cannot determine current directory");	}	/*	 * Change what we are given before doing it's contents	 */	if (chmod(dir, newmode(mode, dir, &errmode)) < 0) {		errmsg(MM_WARNING, 0, badchmod, dir, strerror(errno));		return 1;	}	if (chdir(dir) < 0) {		errmsg(MM_WARNING, 0, errfmt, dir, strerror(errno));		return 1;	}	if ((dirp = opendir(".")) == NULL) {		errmsg(MM_WARNING, 0, errfmt, dir, strerror(errno));		return 1;	}	dp = readdir(dirp);	dp = readdir(dirp); /* read "." and ".." */	ecode = 0;	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))		ecode += dochmod(dp->d_name);	(void) closedir(dirp);	if (chdir(savedir) < 0) {		errmsg(MM_WARNING, 255, ":11:Cannot change back to %s: %s\n",			savedir, strerror(errno));	}	return ecode;}static mode_tnewmode(nm, file, errmode)mode_t  nm;char  *file;int *errmode;{	/* m contains USER|GROUP|OTHER information	   o contains +|-|= information	   b contains rwx(slt) information  */	mode_t m, b;	register int o;	register int lcheck, scheck, xcheck, goon;	mode_t om = nm;	/* save mode for file mode incompatibility return */	*errmode = 0;	msp = ms;	if (*msp >= '0' && *msp <= '9')		return abs(om);	do {		m = who();		while (o = what()) {/*	this section processes permissions*/			b = 0;			goon = 0;			lcheck = scheck = xcheck = 0;			switch (*msp) {			case 'u':				b = (nm & USER) >> 6;				goto dup;			case 'g':				b = (nm & GROUP) >> 3;				goto dup;			case 'o':				b = (nm & OTHER);		    dup:				b &= (READ|WRITE|EXEC);				b |= (b << 3) | (b << 6);				msp++;				goon = 1;			}			while (goon == 0) switch (*msp++) {			case 'r':				b |= READ;				continue;			case 'w':				b |= WRITE;				continue;			case 'x':				b |= EXEC;				xcheck = 1;				continue;			case 'l':				b |= LOCK;				m |= LOCK;				lcheck = 1;				continue;			case 's':				b |= SETID;				scheck = 1;				continue;			case 't':				b |= STICKY;				continue;			default:				msp--;				goon = 1;			}			b &= m;			switch (o) {			case '+':				/* is group execution requested? */				if ( xcheck == 1 && (b & GROUP & EXEC) == (GROUP & EXEC)) {					/* not locking, too! */					if ( lcheck == 1 ) {						errmsg(MM_ERROR, 3, ":17:Group execution and locking not permitted together\n");					}					/* not if the file is already lockable */					if ( (nm & GROUP & (LOCK | EXEC)) == LOCK ) {						errmsg(MM_WARNING, 0, ":18:Group execution not permitted\n\ton %s, a lockable file\n", file);						*errmode = 1;						return om;					}				}				/* is setgid on execution requested? */				if ( scheck == 1 && (b & GROUP & SETID) == (GROUP & SETID) ) {					/* not locking, too! */					if ( lcheck == 1 && (b & GROUP & EXEC) == (GROUP & EXEC) ) {						errmsg(MM_ERROR, 4, ":19:Set-group-ID and locking not permitted together\n");					}					/* not if the file is already lockable */					if ( (nm & GROUP & (LOCK | EXEC)) == LOCK ) {						errmsg(MM_WARNING, 0, ":20:Set-group-ID not permitted\n\ton %s, a lockable file\n", file);						*errmode = 1;						return om;					}				}				/* is setid on execution requested? */				if ( scheck == 1 ) {					/* the corresponding execution must be requested or already set */					if ( ((nm | b) & m & EXEC & (USER | GROUP)) != (m & EXEC & (USER | GROUP)) ) {						errmsg(MM_WARNING, 0, ":21:Execute permission required for set-ID\n\ton execution for %s\n", file);						*errmode = 1;						return om;					}				}				/* is locking requested? */				if ( lcheck == 1 ) {					/* not if the file has group execution set */					/* NOTE: this also covers files with setgid */					if ( (nm & GROUP & EXEC) == (GROUP & EXEC) ) {						errmsg(MM_WARNING, 0, ":22:Locking not permitted\n\ton %s, a group executable file\n", file);						*errmode = 1;						return om;					}				}				/* create new mode */				nm |= b;				break;			case '-':				/* don't turn off locking, unless it's on */				if ( lcheck == 1 && scheck == 0 				     && (nm & GROUP & (LOCK | EXEC)) != LOCK )					b &= ~LOCK;				/* don't turn off setgid, unless it's on */				if ( scheck == 1 && lcheck == 0				     && (nm & GROUP & (LOCK | EXEC)) == LOCK )					b &= ~(GROUP & SETID);				/* if execution is being turned off and the corresponding				   setid is not, turn setid off, too & warn the user */				if ( xcheck == 1 && scheck == 0				     && ((m & GROUP) == GROUP || (m & USER) == USER)				     && (nm & m & (SETID | EXEC)) == (m & (SETID | EXEC)) ) {					errmsg(MM_WARNING, 0, ":23:Corresponding set-ID also disabled\n\ton %s since set-ID requires execute permission\n", file);					if ( (b & USER & SETID) != (USER & SETID)					     && (nm & USER & (SETID | EXEC)) == (m & USER & (SETID | EXEC)) )						b |= USER & SETID;					if ( (b & GROUP & SETID) != (GROUP & SETID)					     && (nm & GROUP & (SETID | EXEC)) == (m & GROUP & (SETID | EXEC)) )						b |= GROUP & SETID;				}				/* create new mode */				nm &= ~b;				break;			case '=':				/* is locking requested? */				if ( lcheck == 1 ) {					/* not group execution, too! */					if ( (b & GROUP & EXEC) == (GROUP & EXEC) ) {						errmsg(MM_ERROR, 3, ":17:Group execution and locking not permitted together\n");					}					/* if the file has group execution set, turn it off! */					if ( (m & GROUP) != GROUP ) {						nm &= ~(GROUP & EXEC);					}				}/* is setid on execution requested?   the corresponding execution must be requested, too! */				if (scheck == 1 				  && (b & EXEC & (USER | GROUP))  				    != (m & EXEC & (USER | GROUP)) ) {					errmsg(MM_ERROR, 2, ":24:Execute permission required for set-ID on execution\n");				}/*  * The ISGID bit on directories will not be changed when  * the mode argument is a string with "=".  */				if ((om & S_IFMT) == S_IFDIR)					b = (b & ~S_ISGID) | (om & S_ISGID);				/* create new mode */				nm &= ~m;				nm |= b;				break;			}		}	} while (*msp++ == ',');	if (*--msp) {		errmsg(MM_ERROR, 5, badmode);	}	return nm;}static mode_tabs(mode)	mode_t mode;{	register c;	mode_t i;	for ( i = 0; (c = *msp) >= '0' && c <= '7'; msp++)		i = (mode_t)((i << 3) + (c - '0'));	if (*msp)		errmsg(MM_ERROR, 6, badmode);/* The ISGID bit on directories will not be changed when the mode argument is * octal numeric. Only "g+s" and "g-s" arguments can change ISGID bit when * applied to directories. */	if ((mode & S_IFMT) == S_IFDIR)		return (i & ~S_ISGID) | (mode & S_ISGID);	return i;}static mode_twho(){	register mode_t m;	m = 0;	for (;; msp++) switch (*msp) {	case 'u':		m |= USER;		continue;	case 'g':		m |= GROUP;		continue;	case 'o':		m |= OTHER;		continue;	case 'a':		m |= ALL;		continue;	default:		if (m == 0)			m = ALL;		return m;	}}static intwhat(){	switch (*msp) {	case '+':	case '-':	case '=':		return *msp++;	}	return 0;}/* * Procedure:     errmsg * * Restrictions:                 pfmt: 	none*//* ARGSUSED3 */static voiderrmsg(long severity, long code, const char *format, ... ){	va_list args;	va_start(args, format);	(void)vpfmt(stderr, severity, format, args);	if (code != 0)		exit(code);	return;}

⌨️ 快捷键说明

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