Created
April 3, 2019 16:49
-
-
Save PrunedNeuron/0fc4f87f5af2041628d30a64dcffacb3 to your computer and use it in GitHub Desktop.
Revisions
-
PrunedNeuron created this gist
Apr 3, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,716 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <limits.h> #include <math.h> #include <string.h> #include <sys/wait.h> #include <dirent.h> #include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <fcntl.h> #include <grp.h> #include <pwd.h> #define rep(i, a, b) for(i = a; i < b; i++) #define rev(i, a, b) for(i = a; i > b; i--) #define TOK_BUFFER 64 #define COMM_BUFFER 64 #define TOK_DELIM " \t\n\a\r" #define COMM_DELIM ";" char* root; int shell_cd (char **args); int shell_exit (char **args); int shell_quit(char **args); int shell_pwd (char **args); int shell_echo (char **args); int shell_pinfo (char **args); int shell_ls (char **args); int shell_setenv (char **args); int shell_unsetenv (char **args); char *builtin_arr[] = {"cd","exit","pwd","echo","pinfo", "ls","setenv","unsetenv","quit"}; int (*builtin_functions[])(char**) = {&shell_cd,&shell_exit,&shell_pwd,&shell_echo,&shell_pinfo,&shell_ls,&shell_setenv,&shell_unsetenv,&shell_quit}; void sigintHandler(int sig_num) { signal(SIGINT,sigintHandler); fflush(stdout); } void pipehandler(char **args){ // File descriptors int filedes[2]; int filedes2[2]; int num_cmds = 0; char *command[256]; pid_t pid; int err = -1,end = 0, i = 0, j = 0,k = 0,l = 0; while (args[l] != NULL){ if (strcmp(args[l],"|") == 0){ num_cmds++; } l++; } num_cmds++; while (args[j] != NULL && end != 1){ k = 0; while (strcmp(args[j],"|") != 0){ command[k] = args[j]; j++; if (args[j] == NULL){ end = 1; k++; break; } k++; } command[k] = NULL; j++; if (i % 2 != 0){ pipe(filedes); }else{ pipe(filedes2); } pid=fork(); if(pid==-1){ if (i != num_cmds - 1){ if (i % 2 != 0){ close(filedes[1]); // for odd i }else{ close(filedes2[1]); // for even i } } printf("Child process could not be created\n"); return; } if(pid==0){ if (i == 0){ dup2(filedes2[1], STDOUT_FILENO); } else if (i == num_cmds - 1){ if (num_cmds % 2 != 0){ dup2(filedes[0],STDIN_FILENO); }else{ dup2(filedes2[0],STDIN_FILENO); } }else{ if (i % 2 != 0){ dup2(filedes2[0],STDIN_FILENO); dup2(filedes[1],STDOUT_FILENO); }else{ dup2(filedes[0],STDIN_FILENO); dup2(filedes2[1],STDOUT_FILENO); } } if (execvp(command[0],command)==err){ kill(getpid(),SIGTERM); } } if (i == 0){ close(filedes2[1]); } else if (i == num_cmds - 1){ if (num_cmds % 2 != 0){ close(filedes[0]); }else{ close(filedes2[0]); } }else{ if (i % 2 != 0){ close(filedes2[0]); close(filedes[1]); }else{ close(filedes[0]); close(filedes2[1]); } } waitpid(pid,NULL,0); i++; } } int redirect(char **args, int num) { char in[100],out[100],app[100]; int r = 0,pid,flag1=0,flag2=0,flag3=0; args[num] = NULL; pid = fork(); if (pid==0) { for (int i=0;i<num;i++) { if (strcmp(args[i],"<")==0) { args[i] = NULL; strcpy(in,args[i+1]); flag1 = 1; } if (args[i]!=NULL) { if (strcmp(args[i],">")==0) { args[i] = NULL; strcpy(out,args[i+1]); flag2 = 1; } } if (args[i]!=NULL) { if (args[i][1]==62) { args[i] = NULL; strcpy(app,args[i+1]); flag3 = 1; } } } if (flag1) { int fd; fd = open(in,O_RDONLY,0); if (fd<0) {perror("Could not open input file"); exit(0);} dup2(fd,0); close(fd); } if (flag2) { struct stat buf; if (stat(out,&buf)==0) { int fo; fo = open(out, O_WRONLY); if (fo<0) {perror("Could not open output file"); exit(0);} dup2(fo,1); close(fo); } else { int fo; fo = creat(out,0644); if (fo<0) {perror("Could not create output file"); exit(0);} dup2(fo,1); close(fo); } } if (flag3) { struct stat buffer; if (stat(app,&buffer)==0) { int fa; fa = open(app,O_APPEND | O_WRONLY); if (fa<0) {perror("Could not open output file"); exit(0);} dup2(fa,1); close(fa); } else { int fa; fa = creat(app,0644); if (fa<0) {perror("Could not create output file"); exit(0);} dup2(fa,1); close(fa); } } if (execvp(args[0],args)<0) {r=1; printf("%s: Command doesn't exist\n", args[0]);} } else {wait(NULL);} if (r!=1) {printf("%s with process id: %d exited normally\n",args[0],pid);} return 1; } int shell_setenv (char **args) { if (args[2] == NULL) args[2] = " "; if (setenv(args[1],args[2],1) != 0) perror("shell"); return 1; } int shell_unsetenv (char **args) { if (unsetenv(args[1]) != 0) perror("shell"); return 1; } int shell_cd (char** args) { if (args[1] == NULL) return 1; else if (strcmp(args[1],"~")==0){ chdir(root); } else if (chdir(args[1]) != 0) perror("SHELL"); return 1; } int shell_exit (char** args) { return EXIT_SUCCESS; } int shell_quit (char** args) { return EXIT_SUCCESS; } int shell_pwd (char** args) { char *curr_dir = (char *)malloc(1000*sizeof(char)); getcwd(curr_dir, 1000); printf("%s\n", curr_dir); free(curr_dir); return 1; } int shell_echo (char** args) { int i = 1; while(args[i] != NULL) { printf("%s ", args[i]); i++; } printf("\n"); return 1; } int shell_pinfo (char ** args) { char Process[1000]; strcpy(Process, "/proc/"); if(args[1]) strcat(Process, args[1]); else strcat(Process, "self"); char Stats[100]; strcpy(Stats, Process); strcat(Stats, "/stat"); int error_number[3]; error_number[0] = 0; FILE * stat = fopen(Stats, "r"); if(error_number[0]) { fprintf(stderr, "Error reading %s: %s\n", Stats, strerror(error_number[0])); return 1; } int pid; char status; char name[20]; fscanf(stat, "%d", &pid); fscanf(stat, "%s", name); fscanf(stat, " %c", &status); printf( "pid: %d\n", pid); printf( "Process Status: %c\n", status); fclose(stat); error_number[0] = 0; strcpy(Stats, Process); strcat(Stats, "/statm"); FILE * mem = fopen(Stats, "r"); if(error_number[0]) { fprintf(stderr, "Error reading %s: %s\n", Stats, strerror(error_number[0])); return 1; } int memSize; fscanf(mem, "%d", &memSize); fprintf(stdout, "Memory: %d\n", memSize); fclose(mem); char exePath[1000]; strcpy(Stats, Process); strcat(Stats, "/exe"); error_number[0] = 0; readlink(Stats, exePath, sizeof(exePath)); if(error_number[0]) { fprintf(stderr, "Error reading symbolic link %s: %s\n", Stats, strerror(error_number[0])); return 1; } int sameChars = 0, baseL = strlen(root); for(sameChars = 0; sameChars < baseL; sameChars++) if(root[sameChars] != exePath[sameChars]) break;; char relPath[1000]; if(sameChars == baseL) { relPath[0] = '~'; relPath[1] = '\0'; strcat(relPath, (const char *)&exePath[baseL]); } else { strcpy(relPath, exePath); relPath[strlen(exePath)] = '\0'; } int i = 0; while(exePath[i]) exePath[i++] = '\0'; fprintf(stdout, "Executable Path: %s\n", relPath); return 1; } int shell_ls (char** args) { DIR* dir; struct stat mystat[4]; struct passwd *user[2]; struct group *group[2]; char *buffer; int count[6]; count[1] = 0; count[2] = 0; count[3] = 0; count[4] = 1; count[5] = 0; unsigned char mod[13]; struct tm *starttime[2]; time_t now; int year; struct dirent **dient[4]; buffer = malloc(1024*sizeof(char)); while(args[count[4]] != NULL) { count[5] = 0; if (args[count[4]][count[5]] == 45) { count[5] = 1; while(args[count[4]][count[5]] != 0) { if(args[count[4]][count[5]] == 108) count[1] = 1; if(args[count[4]][count[5]] == 97) count[2] = 1; count[5]++; } } else { if (count[4] > 0) count[3] = count[4]; } count[4]++; } if (count[3] == 0 || args[count[3]] == NULL) args[count[3]] = "."; count[0] = scandir(".",&dient[0],NULL,alphasort); count[0] = scandir(args[count[3]],&dient[0],NULL,alphasort); if (count[0] < 0) perror("shell"); else { for(count[4]=0;count[4]<count[0];count[4]++) { if (count[1] == 1) { if (count[2] == 1) { sprintf(buffer,"%s/%s",args[count[3]],dient[0][count[4]]->d_name); stat(buffer,&mystat[0]); printf( (S_ISDIR(mystat[0].st_mode)) ? "d" : "-"); printf( (mystat[0].st_mode & S_IRUSR) ? "r" : "-"); printf( (mystat[0].st_mode & S_IWUSR) ? "w" : "-"); printf( (mystat[0].st_mode & S_IXUSR) ? "x" : "-"); printf( (mystat[0].st_mode & S_IRGRP) ? "r" : "-"); printf( (mystat[0].st_mode & S_IWGRP) ? "w" : "-"); printf( (mystat[0].st_mode & S_IXGRP) ? "x" : "-"); printf( (mystat[0].st_mode & S_IROTH) ? "r" : "-"); printf( (mystat[0].st_mode & S_IWOTH) ? "w" : "-"); printf( (mystat[0].st_mode & S_IXOTH) ? "x" : "-"); printf(" \t%d",(int)mystat[0].st_nlink); user[1] = getpwuid(mystat[0].st_uid); printf(" \t%s", user[1]->pw_name); group[1] = getgrgid(mystat[0].st_gid); printf(" \t%s", group[1]->gr_name); printf(" \t%lld",(long long)mystat[0].st_size); time(&now); year = localtime(&now)->tm_year; starttime[1] = localtime(&mystat[0].st_ctime); if(starttime[1]->tm_year == year) strftime(mod,13,"%b %e %R",starttime[1]); else strftime(mod,13,"%b %e %Y",starttime[1]); printf(" \t%s",mod ); printf(" \t%s\n",dient[0][count[4]]->d_name); } else { if ((dient[0][count[4]] ->d_name)[0] != 46) { sprintf(buffer,"%s/%s",args[count[3]],dient[0][count[4]]->d_name); stat(buffer,&mystat[0]); printf( (S_ISDIR(mystat[0].st_mode)) ? "d" : "-"); printf( (mystat[0].st_mode & S_IRUSR) ? "r" : "-"); printf( (mystat[0].st_mode & S_IWUSR) ? "w" : "-"); printf( (mystat[0].st_mode & S_IXUSR) ? "x" : "-"); printf( (mystat[0].st_mode & S_IRGRP) ? "r" : "-"); printf( (mystat[0].st_mode & S_IWGRP) ? "w" : "-"); printf( (mystat[0].st_mode & S_IXGRP) ? "x" : "-"); printf( (mystat[0].st_mode & S_IROTH) ? "r" : "-"); printf( (mystat[0].st_mode & S_IWOTH) ? "w" : "-"); printf( (mystat[0].st_mode & S_IXOTH) ? "x" : "-"); printf(" \t%d",(int)mystat[0].st_nlink); user[1] = getpwuid(mystat[0].st_uid); printf(" \t%s", user[1]->pw_name); group[1]=getgrgid(mystat[0].st_gid); printf(" \t%s", group[1]->gr_name); printf(" \t%lld",(long long)mystat[0].st_size); time(&now); year = localtime(&now)->tm_year; starttime[1] = localtime(&mystat[0].st_ctime); if(starttime[1]->tm_year == year) strftime(mod,13,"%b %e %R",starttime[1]); else strftime(mod,13,"%b %e %Y",starttime[1]); printf(" \t%s",mod ); printf(" \t%ld",mystat[0].st_mtime); printf(" \t%s\n",dient[0][count[4]]->d_name); } } } else { if (count[2] == 1) { printf(" %s\n",dient[0][count[4]]->d_name); } else { if ((dient[0][count[4]] ->d_name)[0] != 46) printf("%s ",dient[0][count[4]]->d_name); } } free(dient[0][count[4]]); } free(dient[0]); } return 1; } char* returnPath (char* cwd) { int i,cwd_size = strlen(cwd), root_size = strlen(root); if (root_size > cwd_size) { return cwd; } else if (root_size == cwd_size) { return "~"; } else { char *new = (char*)malloc(100); new[0] = '~'; new[1] = '/'; for (i = 0 ; i < cwd_size-root_size-1; i++) { new[i+2] = cwd[root_size+i+1]; } return new; } } void printPrompt (char *root) { char hostname[1024]; char cwd[1024]; hostname[1023] = '\0'; gethostname(hostname, 1023); char *username = getenv("USER"); getcwd(cwd, sizeof(cwd)); char *path = returnPath(cwd); printf("\n<%s@%s:%s/> ",username, hostname, path); } char *readCommands (void) { int buffer_size = 1024,check, pos = 0, i; char *buffer = malloc(sizeof(char) * buffer_size); if (!buffer) { fprintf(stderr, "ALLOCATION ERROR\n"); exit(EXIT_FAILURE); } for (i = 0; ;i++) { check = getchar(); if (check == EOF || check == '\n') { buffer[pos] = '\0'; return buffer; } else buffer[pos] = check; pos++; if (pos >= buffer_size) { buffer_size += 1024; buffer = realloc(buffer, buffer_size); if (!buffer) { fprintf(stderr, "ALLOCATION ERROR\n"); exit(EXIT_FAILURE); } } } } char **splitLine (char* line) { int buffer_size = COMM_BUFFER; int position = 0, i = 0; char **commands = malloc(buffer_size * (sizeof(char*))); char *command; if (!commands) { fprintf(stderr, "Allocaiton Error \n"); exit(EXIT_FAILURE); } command = strtok(line, COMM_DELIM); for (i = 0;; i++) { if (command!= NULL) { commands[position++] = command; if (buffer_size < position) { buffer_size += COMM_BUFFER; commands = realloc(commands, buffer_size * sizeof(char*)); if (!commands) { fprintf(stderr, "Allocaiton Error \n"); exit(EXIT_FAILURE); } } command = strtok(NULL, COMM_DELIM); continue; } break; } commands[position] = NULL; return commands; } char **splitCommand (char* line) { int buffer_size = TOK_BUFFER; int position = 0, i = 0; char **tokens = malloc(buffer_size * (sizeof(char*))); char *token; if (!tokens) { fprintf(stderr, "Allocaiton Error \n"); exit(EXIT_FAILURE); } token = strtok(line, TOK_DELIM); for (i = 0;; i++) { if (token!= NULL) { tokens[position++] = token; if (buffer_size < position) { buffer_size += TOK_BUFFER; tokens = realloc(tokens, buffer_size * sizeof(char*)); if (!tokens) { fprintf(stderr, "Allocaiton Error \n"); exit(EXIT_FAILURE); } } token = strtok(NULL, TOK_DELIM); continue; } break; } tokens[position] = NULL; return tokens; } int launch (char** args) { int i,j,background = 0, redirectflag = 0, piping = 0; for (i = 0;args[i] != NULL;i++) { for (j = 0;args[i][j] != '\0'; j++) { if (args[i][j] == '>' || args[i][j] == '<') { redirectflag = 1; } if (args[i][j] == '|') { piping = 1; } if (args[i][j] == '&') { background = 1; } } } if (piping) { pipehandler(args); return 1; } if (redirectflag) { return redirect(args, i); } pid_t pid, wpid; int state; pid = fork(); if (pid < 0) { perror("ERROR"); } else if(!pid) { if ( execvp(args[0], args) == -1) perror("ERROR"); exit(EXIT_FAILURE); } if(!background) { wpid = waitpid (pid, &state, WUNTRACED); for (i = 0;; i++) { if (!WIFEXITED(state) && !WIFSIGNALED(state)) { wpid = waitpid (pid, &state, WUNTRACED); continue; } break; } } return 1; } int checkCommand (char** args) { int count; if (args[0] == NULL) return EXIT_FAILURE; count = 0; while (count < sizeof(builtin_arr)/sizeof(char*)) { if (strcmp(args[0],builtin_arr[count]) == 0) return (*builtin_functions[count])(args); count++; } return launch(args); } void interpretCommand(void) { char **args; char *commands; char **split_line; int state; int i,j; signal(SIGINT,sigintHandler); for (i = 0;; i++) { printPrompt(root); commands = readCommands(); split_line = splitLine(commands); for (j = 0;split_line[j] != NULL ;j++) { args = splitCommand(split_line[j]); state = checkCommand(args); free (args); if (!state) { break; } } free(commands); free(split_line); if(!state) { break; } } } int main(int arg1, char **arg2) { root = getenv("PWD"); interpretCommand(); return EXIT_SUCCESS; }