Cracking Shellsush.hush1.cProblems with ush1.cush2.cexecutecmdlinesimple.cProblems Solved by ush2.cProblems with ush2.cAdding in Redirectionush2a.cexecutecmdline.c with ush2a.credirect.c with ush2a.cparsefile.c with ush2a.cparsfile.c Actions on cat < my.input > my.outputush2b.cexecutecmdlinepipe.c – ush2b.c (top)executecmdlinepipe.c – (middle)executecmdlinepipe.c – (bottom)connectpipeline.c (top)connectpipeline.c (bottom)ush3.c – (top)ush3.c – (bottom)ush3.c Analysisush4.c – (top)ush4.c – (middle)ush4.c – (bottom)ush4.c Analysiskill CommandProcess GroupGetting and Changing Process GroupsetpgidBackground ProcessGetting and Changing Session IDSession/Group ID ExampleSession/Process Group DiagramBackground/Foreground ProcessesJob Controltcgetpgrp/tcsetpgrp/tcgetsidush5.c – (top)ush5.c – (bottom)ush6.cush7.c – (top)ush7.c – (bottom)Job Control – (1)Job Control – (2)Job Control – (3)Job Control – (4)Cracking ShellsShell – A process that does command-line interpretationush.h/* Program 7.1 */#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <sys/wait.h>#include <limits.h>#define STDMODE 0600#define DELIMITERSET " ><|&"#ifndef MAX_CANON#define MAX_CANON 256#endif int makeargv(char *s, char *delimiters, char ***argvp);int parsefile(char *inbuf, char delimiter, char **v);int redirect(char *infilename, char *outfilename);void executecmdline(char *cmd);int connectpipeline(char *cmd, int frontfd[], int backfd[]);#define TRUE 1#define FALSE 0#define BLANK_STRING " "#define PROMPT_STRING ">>"#define QUIT_STRING "q"#define BACK_STRING "&"#define PIPE_STRING "|"#define NEWLINE_STRING "\n"#define IN_REDIRECT_SYMBOL '<'#define OUT_REDIRECT_SYMBOL '>'#define NULL_SYMBOL '\0'#define PIPE_SYMBOL '|'#define BACK_SYMBOL '&'#define NEWLINE_SYMBOL '\n'ush1.c/* Program 7.2 */#include "ush.h"#define MAX_BUFFER 256void main (void){ char inbuf[MAX_BUFFER]; char **chargv; for( ; ; ) { gets(inbuf); if (strcmp(inbuf, QUIT_STRING) == 0) break; else { if (fork() == 0) { if (makeargv(inbuf, BLANK_STRING, &chargv) > 0) execvp(chargv[0], chargv); } wait(NULL); } } exit(0);}Problems with ush1.c•cd is not available•No wildcards such as * and ?•What if parent doesn’t call wait?–Execute with wait removed and run an invalid command such as “xyz”•Since execvp does not catch error, child falls through and begins executing commands – ps shows two ush1 shells•The parent and child shells can execute concurrently. Execute ls /user/s followed by ls•Notice MAX_BUFFER is user defined, non-portable constant – uses gets rather than fgetsush2.c/* Program 7.3 */#include "ush.h"void main (void){ char inbuf[MAX_CANON+1]; pid_t child_pid; for( ; ; ) { fputs(PROMPT_STRING, stdout); if (fgets(inbuf, MAX_CANON, stdin) == NULL) break; if (*(inbuf + strlen(inbuf) - 1) == NEWLINE_SYMBOL) *(inbuf + strlen(inbuf) - 1) = 0; if (strcmp(inbuf, QUIT_STRING) == 0) break; else { if ((child_pid = fork()) == 0) { executecmdline(inbuf); exit(1); } else if (child_pid > 0) wait(NULL); } } exit(0);}executecmdlinesimple.c#include "ush.h"void executecmdline(char *incmd){ char **chargv; if (makeargv(incmd, BLANK_STRING, &chargv) > 0) { if(execvp(chargv[0], chargv) == -1) { perror("Invalid command"); exit(1); } } exit(1);}Why not have perror before second exit? Consider entering blank commandProblems Solved by ush2.c•Command prompt is displayed•Proper termination of execvp on error•System-defined constant MAX_CANON replaces MAX_BUFFER•fgets replaces getsProblems with ush2.c•cd doesn’t work – cd must change the user’s environment•Try ls –l and q with interspersed and leading extra blanksls –l works but q doesn’t becausels –l is handled by makeargv – q isn’t•Try commands found at stty –a such as ^c – What do they do to parent/child? Why?•Try erase, ^h – It still works because characters entered are not in program yet but are stored in a temporary buffer•Doesn’t recognize redirect or pipe symbolsAdding in Redirection•compile < t.c•cat file1 > file2•cat < my.input > my.outputush2a.c#include "ush.h"#include "redirect.c"#include "parsefile.c"#include "executecmdline.c“void main (void){ char inbuf[MAX_CANON+1]; pid_t child_pid; for( ; ; ) { fputs(PROMPT_STRING, stdout); if (fgets(inbuf, MAX_CANON, stdin) == NULL) break; if (*(inbuf + strlen(inbuf) - 1) == NEWLINE_SYMBOL) *(inbuf + strlen(inbuf) - 1) = 0; if (strcmp(inbuf, QUIT_STRING) == 0) break; else { if ((child_pid = fork()) == 0) { executecmdline(inbuf); exit(1); } else if (child_pid > 0) wait(NULL); } } exit(0); }executecmdline.c with ush2a.c/* Program 7.4 * The executecmdline function parses incmd for possible redirection. It * calls redirect to perform the redirection and makeargv to create the * command argument array. It then execvp's the command executable. * The function exits on error so it never returns to the caller. */void executecmdline(char *incmd){ char **chargv; char *infilename; char *outfilename; if (parsefile(incmd, IN_REDIRECT_SYMBOL , &infilename) == -1) fprintf(stderr, "Incorrect input redirection\n"); else if (parsefile(incmd, OUT_REDIRECT_SYMBOL, &outfilename) == -1) fprintf(stderr, "Incorrect output redirection\n"); else if (redirect(infilename, outfilename) == -1) fprintf(stderr, "Redirection failed\n"); else if (makeargv(incmd, BLANK_STRING, &chargv) > 0) { if (execvp(chargv[0], chargv) == -1) perror("Invalid command"); } exit(1); }int redirect(char *infilename, char *outfilename){ int indes; int outdes; if (infilename != NULL) { /* redirect standard in to infilename */ if ((indes = open(infilename, O_RDONLY, STDMODE)) == -1) return -1; if (dup2(indes, STDIN_FILENO) == -1) { close(indes); return -1; } close(indes); } if (outfilename != NULL) {/* redirect standard out to outfilename */ if ((outdes = open(outfilename, O_WRONLY|O_CREAT, STDMODE)) == -1) return -1; if (dup2(outdes, STDOUT_FILENO) == -1) { close(outdes); return -1; } close(outdes); } return 0;}redirect.c with ush2a.cint parsefile(char *s, char delimiter, char **v){ char *p; char *q; int offset; int error = 0;
View Full Document