/*
* filename: my_chmod.c
* Email: lin.jian1986@gmail.com
* Date: 2008/10/24
*/
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include "../my_error.h"
#define MODE O777
#define CHMOD(file, MODE); { \
if ( chmod(file, statbuf.st_mode) < 0 ) \
my_error( "chmod" ); \
break; \
}
/* return 'n' when arg is number, or 's' if arg is string*/
int number_or_string( const char *arg )
{
assert( arg != NULL );
if ( arg[0] >= '0' && arg[0] <= '9' )
return 'n';
return 's';
}
/* the implement of number argument */
void number_chmod( const char *arg, const char *file )
{
int mode;
mode = atoi( arg );
if ( mode > 777 || mode < 0 ) {
fprintf( stderr, "usage: mode" );
exit ( 1 );
}
/* To change a decimal system to a octal system */
sscanf( arg, "%o", &mode );
if ( chmod(file, mode) == -1 )
exit ( 2 );
}
/* the implement of string argument */
void string_chmod( const char *arg, const char *file )
{
int i, j;
int mode;
struct stat statbuf;
if ( stat(file, &statbuf) < 0 )
my_error( "stat" );
for ( i = 0; i < strlen(arg); i += j + 1 ) {
/* if change the user mode */
if ( arg[i] == 'u' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IRUSR;
else
statbuf.st_mode &= ~S_IRUSR;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWUSR;
else
statbuf.st_mode &= ~S_IWUSR;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXUSR;
else
statbuf.st_mode &= ~S_IXUSR;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
/* if change the group mode */
else if ( arg[i] == 'g' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IRGRP;
else
statbuf.st_mode &= ~S_IRGRP;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWGRP;
else
statbuf.st_mode &= ~S_IWGRP;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXGRP;
else
statbuf.st_mode &= ~S_IXGRP;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
/* if change the other user mode */
else if ( arg[i] == 'o' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IROTH;
else
statbuf.st_mode &= ~S_IROTH;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWOTH;
else
statbuf.st_mode &= ~S_IWOTH;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXOTH;
else
statbuf.st_mode &= ~S_IXOTH;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
}
}
int main( int argc, char *argv[] )
{
int mode;
char buf[20];
if ( argc < 3 ) {
fprintf( stderr, "usage: argc < 3" );
exit (1);
}
if ( number_or_string(argv[1]) == 'n' )
number_chmod( argv[1], argv[argc - 1] );
else {
strcpy( buf, argv[1] );
for ( int i = 2; i < argc - 1; i++ ) {
strcat( buf, " ");
strcat( buf, argv[i] );
}
string_chmod( buf, argv[argc - 1] );
}
return 0;
}
|