summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c365
1 files changed, 365 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <signal.h>
+#include <grp.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include <utils.h>
+#include <completion.h>
+#include <commands.h>
+
+
+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 = &top;
+}
+
+/*
+ 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( &current->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 );
+}