From 2cb9fbfe059354d06c088e090b6af7238b4fa806 Mon Sep 17 00:00:00 2001 From: "Andrey V.Kosteltsev" Date: Sat, 24 Sep 2022 16:49:18 +0300 Subject: Initial commit --- src/main.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 src/main.c (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c950f40 --- /dev/null +++ b/src/main.c @@ -0,0 +1,365 @@ + +#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'" }, + { "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'" }, + { "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'" }, + { "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 ); +} -- cgit v1.2.3