#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char *progname; /* The name of this program, as taken from argv[0]. */ int done; /* When non-zero, this global means the user is done using this program. */ char pwd[PATH_MAX], home[PATH_MAX]; static sigset_t blockmask; COMMAND top_admin_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "shell", com_shell, "Activate submenu shell" }, { "users", com_users, "Activate submenu users" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND top_operator_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "shell", com_shell, "Activate submenu shell" }, { "users", com_users, "Activate submenu users" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND top_user_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "shell", com_shell, "Activate submenu shell" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND_LIST top; COMMAND shell_admin_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "cd", com_cd, "Change to directory DIR" }, { "delete", com_delete, "Delete FILE" }, { "list", com_ls, "List files in DIR" }, { "ls", com_ls, "Synonym for `list'" }, { "id", com_id, "Print user identity" }, { "ping", com_ping, "Ping some host" }, { "pwd", com_pwd, "Print the current working directory" }, { "rename", com_rename, "Rename FILE to NEWNAME" }, { "stat", com_stat, "Print out statistics on FILE" }, { "more", com_more, "View the contents of FILE" }, { "vi", com_vi, "Edit the contents of text FILE" }, { "..", com_top, "Return to top menu" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND shell_operator_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "cd", com_cd, "Change to directory DIR" }, { "delete", com_delete, "Delete FILE" }, { "list", com_ls, "List files in DIR" }, { "ls", com_ls, "Synonym for `list'" }, { "id", com_id, "Print user identity" }, { "ping", com_ping, "Ping some host" }, { "pwd", com_pwd, "Print the current working directory" }, { "rename", com_rename, "Rename FILE to NEWNAME" }, { "stat", com_stat, "Print out statistics on FILE" }, { "more", com_more, "View the contents of FILE" }, { "vi", com_vi, "Edit the contents of text FILE" }, { "..", com_top, "Return to top menu" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND shell_user_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "cd", com_cd, "Change to directory DIR" }, { "delete", com_delete, "Delete FILE" }, { "list", com_ls, "List files in DIR" }, { "ls", com_ls, "Synonym for `list'" }, { "id", com_id, "Print user identity" }, { "ping", com_ping, "Ping some host" }, { "pwd", com_pwd, "Print the current working directory" }, { "rename", com_rename, "Rename FILE to NEWNAME" }, { "stat", com_stat, "Print out statistics on FILE" }, { "more", com_more, "View the contents of FILE" }, { "vi", com_vi, "Edit the contents of text FILE" }, { "..", com_top, "Return to top menu" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND_LIST shell; COMMAND users_admin_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "useradd", com_useradd, "Register new user" }, { "userdel", com_userdel, "Delete user" }, { "..", com_top, "Return to top menu" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND users_operator_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "useradd", com_useradd, "Register new user" }, { "userdel", com_userdel, "Delete user" }, { "..", com_top, "Return to top menu" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND users_user_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, { "list", com_userlist, "List users" }, { "..", com_top, "Return to top menu" }, { "quit", com_quit, "Quit using SILA Shell" }, { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND_LIST users; COMMAND_LIST *current; void cmd_lists_init( gid_t gid ) { gid_t admin_gid = 0, operator_gid = 0, user_gid = 0; struct group *grp = NULL; grp = getgrnam( "priv-admin" ); if( grp != NULL ) admin_gid = grp->gr_gid; grp = getgrnam( "priv-operator" ); if( grp != NULL ) operator_gid = grp->gr_gid; grp = getgrnam( "priv-user" ); if( grp != NULL ) user_gid = grp->gr_gid; top.name = "top"; shell.name = "shell"; users.name = "users"; if( admin_gid != 0 && (gid == admin_gid || gid == 0) ) { top.list = &top_admin_list[0]; shell.list = &shell_admin_list[0]; users.list = &users_admin_list[0]; } else if( operator_gid != 0 && gid == operator_gid ) { top.list = &top_operator_list[0]; shell.list = &shell_operator_list[0]; users.list = &users_operator_list[0]; } else if( user_gid != 0 && gid == user_gid ) { top.list = &top_user_list[0]; shell.list = &shell_user_list[0]; users.list = &users_user_list[0]; } else { top.list = &top_user_list[0]; shell.list = &shell_user_list[0]; users.list = &users_user_list[0]; } current = ⊤ } /* Strip whitespace from the start and end of STRING. Return a pointer into STRING. */ char *stripwhite( char *string ) { register char *s, *t; for( s = string; whitespace (*s); ++s ) ; if( *s == 0 ) return( s ); t = s + strlen (s) - 1; while( t > s && whitespace( *t ) ) t--; *++t = '\0'; return s; } /* Look up NAME as the name of a command, and return a pointer to that command. Return a NULL pointer if NAME isn't a command name. */ COMMAND *find_command( char *name ) { register int i; for( i = 0; current->list[i].name; i++ ) if( strcmp( name, current->list[i].name ) == 0 ) return( ¤t->list[i] ); return( (COMMAND *)NULL ); } /* Execute a command line. */ int execute_line( char *line ) { register int i; COMMAND *command; char *word; /* Isolate the command word. */ i = 0; while( line[i] && whitespace( line[i] ) ) i++; word = line + i; while( line[i] && !whitespace( line[i] ) ) i++; if( line[i] ) line[i++] = '\0'; command = find_command( word ); if( !command ) { if( strcmp( current->name, "top" ) ) fprintf( stderr, "%s: No such command for SILA[%s] Shell.\n", word, current->name ); else fprintf( stderr, "%s: No such command for SILA Shell.\n", word ); return( -1 ); } /* Get argument to command, if any. */ while( whitespace( line[i] ) ) i++; word = line + i; /* Call the function. */ return( (*(command->func))(word) ); } void sigint( int signum ) { if( signum == SIGTERM ) { /* free resourses and exit */ exit( 0 ); } else { /* Ignore SIGINT */ return; } } static void set_signal_handlers() { struct sigaction sa; sigset_t set; memset( &sa, 0, sizeof( sa ) ); sa.sa_handler = sigint; /* TERM, INT */ sa.sa_flags = SA_RESTART; sigemptyset( &set ); sigaddset( &set, SIGTERM ); sigaddset( &set, SIGINT ); sa.sa_mask = set; sigaction( SIGTERM, &sa, NULL ); sigaction( SIGINT, &sa, NULL ); /* на случай блокировки сигналов с помощью sigprocmask(): */ sigemptyset( &blockmask ); sigaddset( &blockmask, SIGTERM ); sigaddset( &blockmask, SIGINT ); } int main( int argc, char **argv ) { char *line, *s, *home, *curdir; char prompt[PATH_MAX]; set_signal_handlers(); cmd_lists_init( getgid() ); progname = argv[0]; initialize_readline(); /* Bind our completer. */ /* Loop reading and executing lines until the user quits. */ for( ; done == 0; ) { home = getenv( "HOME" ); curdir = getcwd( pwd, PATH_MAX ); if( home && curdir == strstr( curdir, home ) ) { curdir[strlen( home ) - 1] = '~'; curdir += strlen( home ) - 1; } if( strcmp( current->name, "top" ) ) sprintf( prompt, "%s[%s]:%s$ ", "sila", current->name, curdir ); else sprintf( prompt, "%s:%s$ ", "sila", curdir ); line = readline( prompt ); if( !line ) { //continue; /* for non-priviledged users */ break; /* for admin */ } /* Remove leading and trailing whitespace from the line. Then, if there is anything left, add it to the history list and execute it. */ s = stripwhite( line ); if( *s ) { add_history( s ); execute_line( s ); } free( line ); } exit( 0 ); }