/* chmogdir.c
*
* Change mode owner and group of all files of the named directories.
* Leave mode for current and parent directory unchanged.
*
* See K&R (The Bible) p. 172
*
* NB this is in function more of a setmode and does not accept the later syntax
* of the chmod utility that allows [augo][+|-|=][rwxst] arguments in place
* of an absolute mode to set.
*/
#include <stdio.h>
#include <stdfun.h>
#include <string.h>
#include <ctype.h>
#include <bool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <pwd.h>
#include <grp.h>
#define OPTSTRING "mog"
char heredir[ 160 ];
static char _sccsid[] = { " chmogdir.c 1.3 9/22/97 " };
BOOL modechange = TRUE;
BOOL ownerchange = TRUE;
BOOL groupchange = TRUE;
int main( argc, argv )
int argc;
char **argv;
{
extern int getopt();
extern int optind;
extern char *optarg; /* Captures arguments to options */
void usage();
int uid(), gid(), chmogdir();
char dirname[ 160 ];
int ggid, uuid;
int i;
int c_opt;
while( ( c_opt = getopt( argc, argv, OPTSTRING ) ) != EOF ) {
switch( c_opt ) {
case 'm':
/* -m */
modechange = FALSE;
break;
case 'o':
/* -o */
ownerchange = FALSE;
break;
case 'g':
/* -g */
groupchange = FALSE;
break;
default:
fprintf( stderr, "%s: Bad Option -%c\n", argv[0], c_opt );
usage();
exit( 1 );
}
}
if( modechange + ownerchange + groupchange == 0 ) {
fprintf( stderr, "%s: All changes neutralized.\n", argv[0] );
usage();
exit( 1 );
}
/* On exiting loop of option parsing optind indexes the next
* argv[] argument to the function.
*/
else if( modechange + ownerchange + groupchange == 1 ) {
if( argc %lt; 5 ) {
usage();
exit( 1 );
}
if( modechange ) {
;
}
else if( ownerchange ) {
if( (uuid = uid( argv[ optind ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such user %s\n", argv[ optind + 1] );
exit( 1 );
}
}
else {
if( (ggid = gid( argv[ optind ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such group %s\n", argv[ optind ] );
exit( 1 );
}
}
/* Start with the first named directory */
i = optind + 1;
}
else if( modechange + ownerchange + groupchange == 2 ) {
if( argc < 4 ) {
usage();
exit( 1 );
}
if( ! modechange ) {
if( (uuid = uid( argv[ optind ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such user %s\n", argv[ optind + 1] );
exit( 1 );
}
if( (ggid = gid( argv[ optind + 1 ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such group %s\n", argv[ optind + 1 ] );
exit( 1 );
}
}
else if( ! ownerchange ) {
if( (ggid = gid( argv[ optind + 1 ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such group %s\n", argv[ optind + 1 ] );
exit( 1 );
}
}
else {
if( (ggid = gid( argv[ optind + 1 ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such group %s\n", argv[ optind + 1 ] );
exit( 1 );
}
}
/* Start with the first named directory */
i = optind + 2;
}
else if( modechange + ownerchange + groupchange == 3 ) {
if( argc %lt; 5 ) {
usage();
exit( 1 );
}
if( (uuid = uid( argv[ optind + 1 ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such user %s\n", argv[ optind + 1] );
exit( 1 );
}
if( (ggid = gid( argv[ optind + 2 ] ) ) %lt; 0 ) {
fprintf( stderr, "chmogdir: no such group %s\n", argv[ optind + 2 ] );
exit( 1 );
}
/* Start with the first named directory */
i = optind + 3;
}
/* ---------------------------------------------------------------- */
/* Save the starting directory so we are ok with relative pathnames */
getcwd( heredir, 162 );
while( i < argc ) {
strcpy( dirname, argv[ i ] );
chmogdir( argv[ optind ], uuid, ggid, dirname );
++i;
} /* End while processing file arguments */
exit( 0 );
return( 0 );
}
int chmogdir( mode, owner, group, dirname )
char *mode;
int owner, group;
char *dirname;
{
struct stat buf, *bufp;
struct stat fbuf, *fbufp;
struct direct dirbuf;
char errstr[ 160 ];
char fname[ 160 ];
char *lchptr;
int o_mode;
int fd;
bufp = &buf;
/* Get contents of the directory structure */
if( stat( dirname, bufp ) == -1 ) {
sprintf( errstr, "chmogdir (%s) ", dirname );
perror( errstr );
return( -1 );
}
/* Check to see if it is in fact a directory.
* See mknod(S)
* Shift 4 digits to the right and bite off the right most digit.
*/
if( ((bufp->st_mode >> 12) & 07 ) != 4 ) {
fprintf( stderr, "chmogdir: %s octal mode %o not directory\n", dirname, bufp->st_mode );
return( -1 );
}
if( ( fd = open( dirname, 0 ) ) == -1 ) {
fprintf( stderr, "chmogdir: can't read directory %s\n", dirname );
return( -1 );
}
if( modechange )
sscanf( mode, "%o", &o_mode );
chdir( dirname );
while( read( fd, (char *)&dirbuf, sizeof( dirbuf ) ) > 0 ) {
if( dirbuf.d_ino == 0 ) /* slot not in use */
continue;
/* Do not alter current or parent directory */
if( strcmp( dirbuf.d_name, "." ) == 0 )
continue;
if( strcmp( dirbuf.d_name, ".." ) == 0 )
continue;
fbufp = &fbuf;
/* Get contents of the file structure */
if( stat( dirbuf.d_name, fbufp ) == -1 ) {
sprintf( errstr, "chmogdir (%s) ", dirbuf.d_name );
perror( errstr );
continue;
}
/* Set the designated slots */
if( modechange )
chmod( dirbuf.d_name, o_mode );
if( ownerchange )
chown( dirbuf.d_name, owner, fbufp->st_gid );
if( groupchange )
chown( dirbuf.d_name, fbufp->st_uid, group );
}
chdir( heredir );
return( 0 );
}
/*
* Convert logname to uid.
*/
int uid( ulnam )
char *ulnam;
{
extern struct passwd *getpwnam();
struct passwd pw, *ppw;
ppw = getpwnam( ulnam );
if( ppw == (struct passwd *)0 ) {
return( -1 );
}
else {
return( ppw->pw_uid );
}
}
/*
* Convert logname to gid.
*/
int gid( ulnam )
char *ulnam;
{
extern struct group *getgrnam();
struct group gr, *ggr;
ggr = getgrnam( ulnam );
if( ggr == (struct group *)0 ) {
return( -1 );
}
else {
return( ggr->gr_gid );
}
}
void usage()
{
fprintf( stderr, "Usage: chmogdir mode owner group directory [directory ...]\n" );
fprintf( stderr, " chmogdir -m owner group directory [directory ...]\n" );
fprintf( stderr, " chmogdir -o mode group directory [directory ...]\n" );
fprintf( stderr, " chmogdir -g mode owner directory [directory ...]\n" );
fprintf( stderr, " chmogdir -m -o group directory [directory ...]\n" );
fprintf( stderr, " chmogdir -o -g mode directory [directory ...]\n" );
fprintf( stderr, " chmogdir -g -m owner directory [directory ...]\n" );
}
Return to Home Page
Return to Metayoga Page
Return to C Language Page
The URL for this document is:
http://graham.main.nc.us/~bhammel/graham/CPROGS/chmogdir.html
Created: 1997
Last Updated: May 28, 2000
Email me, Bill Hammel at
bhammel@graham.main.nc.us
READ WARNING BEFORE SENDING E-MAIL