1
- #include <stdio.h>
2
- #include <stdlib.h>
3
- #include <string.h>
4
- #include <unistd.h>
5
- #include <sys/types.h>
6
-
7
- void main (int argc , char const * argv []) {
8
- char readIn [2048 ], * commandList [2048 ], str [512 ], pwd [100 ]; /*Init variables*/
9
-
10
- while (1 ) { /*start shell*/
11
- printf (": " );
12
- fflush (stdout ); /*flush stdin*/
13
- fgets (readIn , 2048 , stdin );
14
- int count = 0 ;
15
-
16
- char * token = strtok (readIn , " " );
17
- while ( token != NULL ) {
18
- sscanf (token , "%s" , str );
19
- commandList [count ++ ] = strdup (str );
20
- token = strtok (NULL , " " );
21
- }
22
- commandList [count ++ ] = NULL ;
23
-
24
- if (strcmp (commandList [0 ], "exit" ) == 0 )
25
- exit (0 );
26
- else if (strcmp (commandList [0 ], "cd" ) == 0 ) {
27
- if (count == 1 )
28
- chdir (getenv ("HOME" ));
29
- else
30
- chdir (commandList [1 ]);
31
- }
32
- else if (strcmp (commandList [0 ], "status" ) == 0 ) {
33
- if (WIFEXITED (0 )){
34
- printf ("exit value %i\n" , WEXITSTATUS (0 ));
35
- }
36
- else {
37
- printf ("terminated by signal %i\n" , 0 );
38
- }
39
- }
40
- else {
41
- pid_t spawnPID = -5 ;
42
- int childExitStatus = -5 ;
43
-
44
- spawnPID = fork ();
45
- switch (spawnPID ) {
46
- case -1 : {
47
- perror ("Hull Breach!\n" );
48
- _Exit (1 ); break ;
49
- }
50
- case 0 : {
51
- if (execvp (commandList [0 ], commandList )){
52
- printf ("smallsh: Sorry, command \"%s\" is not a valid command\n" , commandList [0 ]);
53
- fflush (stdout );
54
- _Exit (1 );
55
- }
56
- _Exit (2 );
57
- }
58
- default : {
59
- _Exit (0 );
60
- }
61
- }
62
- }
63
- }
1
+ /*
2
+ Harinder Gakhal
3
+ CS 344
4
+ Program 3 - smallsh
5
+ 2/26/20
6
+ */
7
+
8
+ // libraries used
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+ #include <unistd.h>
13
+ #include <sys/types.h>
14
+ #include <sys/wait.h>
15
+ #include <signal.h>
16
+ #include <sys/stat.h>
17
+ #include <fcntl.h>
18
+ #include <signal.h>
19
+
20
+ // prototypes
21
+ void catchSIGINT (int signo );
22
+ void catchSIGTSTP (int signal );
23
+ char * findAndReplace (char * s , int PID );
24
+
25
+ int fgONLY = 0 ;
26
+
27
+ void catchSIGINT (int signo ) { /*catch ctrl-c*/
28
+ char * message = "\nCaught SIGINT.\n" ;
29
+ write (STDOUT_FILENO , message , 38 );
30
+ }
31
+
32
+ void catchSIGTSTP (int signal ) { /*catch ctrl-z*/
33
+ if (fgONLY == 0 ) {
34
+ char * message = "\nEntering foreground-only mode (& is now ignored)\n" ;
35
+ write (STDOUT_FILENO , message , 25 );
36
+ fgONLY = 1 ;
37
+ }
38
+ else {
39
+ char * message = "\nExiting foreground-only mode\n" ;
40
+ write (STDOUT_FILENO , message , 25 );
41
+ fgONLY = 0 ;
42
+ }
43
+ }
44
+
45
+ void main (int argc , char const * argv []) {
46
+ char readIn [2048 ], * commandList [2048 ], str [512 ], pwd [100 ]; /*Init variables*/
47
+ int childExitStatus = -5 , bg = 0 , pListCount = 0 ;
48
+ pid_t spawnPID = -5 ;
49
+ struct sigaction action = {0 }, action2 = {0 };
50
+
51
+ action .sa_handler = SIG_IGN ; /*set up signal handler for SIGINT*/
52
+ action .sa_flags = 0 ; /*ctrl-c disabled by default*/
53
+ sigfillset (& (action .sa_mask ));
54
+ sigaction (SIGINT , & action , NULL );
55
+
56
+ action2 .sa_handler = catchSIGTSTP ; /*set up signal handler for SIGINT*/
57
+ action2 .sa_flags = 0 ;
58
+ sigfillset (& (action2 .sa_mask ));
59
+ sigaction (SIGTSTP , & action2 , NULL );
60
+
61
+ while (1 ) { /*start shell*/
62
+ printf (": " );
63
+ fflush (stdout ); /*flush stdin*/
64
+ strcpy (readIn , "\n" );
65
+ fgets (readIn , 2048 , stdin ); /*Take in user input*/
66
+ int count = 0 ;
67
+ char fileIN [100 ] = {0 }, fileOUT [100 ] = {0 }; /*Input, output file names*/
68
+
69
+ char * token = strtok (readIn , " " );
70
+ while ( token != NULL ) { /*Iterate through each word in the line and parse it*/
71
+ if (strcmp (token , "<" ) == 0 ) {
72
+ token = strtok (NULL , " " ); /*File input*/
73
+ sscanf (token , "%s" , fileIN );
74
+ token = strtok (NULL , " " );
75
+ }
76
+ else if (strcmp (token , ">" ) == 0 ) { /*File output */
77
+ token = strtok (NULL , " " );
78
+ sscanf (token , "%s" , fileOUT );
79
+ token = strtok (NULL , " " );
80
+ }
81
+ else if (strstr (token , "$$" ) != NULL ) { /*Replace the $$ token with the pid*/
82
+ sscanf (token , "%s" , str );
83
+ commandList [count ++ ] = strdup (findAndReplace (str , getpid ()));
84
+ token = strtok (NULL , " " );
85
+ }
86
+ else {
87
+ sscanf (token , "%s" , str ); /*All other tokens go into the command list*/
88
+ commandList [count ++ ] = strdup (str );
89
+ token = strtok (NULL , " " );
90
+ }
91
+ }
92
+
93
+ if (readIn [0 ] == '\n' ) /*If user typed in nothing, set command list to null*/
94
+ commandList [0 ] = NULL ;
95
+
96
+ if (commandList [0 ] != NULL && commandList [0 ][0 ] != '#' ){ /*If not comment or empty*/
97
+ if (strcmp (commandList [count - 1 ], "&" ) == 0 ) { /*Check to see if it should be a background process*/
98
+ commandList [count - 1 ] = NULL ; /*Remove & from the command list*/
99
+ bg = 1 ;
100
+ }
101
+ else {
102
+ commandList [count ++ ] = NULL ;
103
+ bg = 0 ;
104
+ }
105
+
106
+ if (strcmp (commandList [0 ], "exit" ) == 0 ) /*Check to see if user typed exit*/
107
+ exit (0 );
108
+ else if (strcmp (commandList [0 ], "cd" ) == 0 ) { /*Check to see if user typed cd*/
109
+ if (count - 1 == 1 )
110
+ chdir (getenv ("HOME" ));
111
+ else
112
+ chdir (commandList [1 ]);
113
+ }
114
+ else if (strcmp (commandList [0 ], "status" ) == 0 ) { /*Return the status of the last command is user typed status*/
115
+ if (WIFEXITED (childExitStatus ))
116
+ printf ("exit value %i\n" , WEXITSTATUS (childExitStatus ));
117
+ else
118
+ printf ("terminated by signal %i\n" , childExitStatus );
119
+ }
120
+ else {
121
+ spawnPID = fork (); /*Fork the command if it is not recognized*/
122
+ switch (spawnPID ) {
123
+ case -1 : {
124
+ perror ("Hull Breach!\n" ); /*Fork failure*/
125
+ _Exit (1 ); break ;
126
+ }
127
+ case 0 : {
128
+ if (bg == 0 ) { /*Check to see if it is background process, and enable ctr-c*/
129
+ action .sa_handler = SIG_DFL ;
130
+ sigaction (SIGINT , & action , NULL );
131
+ }
132
+
133
+ if (fileIN [0 ] != 0 ){ /*If file input it given*/
134
+ int inDisc = open (fileIN , O_RDONLY );
135
+ if (inDisc == -1 ) { /*Error if file does not exist*/
136
+ printf ("FILE DNE: %s\n" , fileIN );
137
+ fflush (stdout );
138
+ _Exit (1 );
139
+ }
140
+ if (dup2 (inDisc , 0 ) == -1 ) { /*Print error if dup2 failed*/
141
+ perror ("dup2 error" );
142
+ _Exit (1 );
143
+ }
144
+ close (inDisc );
145
+ }
146
+
147
+ if (fileOUT [0 ] != 0 ) { /*Check to see if file output is given*/
148
+ int outDisc = open (fileOUT , O_WRONLY | O_CREAT | O_TRUNC , 0777 );
149
+ if (outDisc == -1 ) {
150
+ printf ("smallsh: cannot open %s\n" , fileOUT );
151
+ fflush (stdout );
152
+ _Exit (1 );
153
+ }
154
+ if (dup2 (outDisc , 1 ) == -1 ){ /*Print error if dup2 failed*/
155
+ perror ("dup2" );
156
+ _Exit (1 );
157
+ }
158
+ close (outDisc );
159
+ }
160
+
161
+ if (execvp (commandList [0 ], commandList ) < 0 ){ /*Run command list in terminal*/
162
+ printf ("Sorry, command \"%s\" is not a valid command\n" , commandList [0 ]);
163
+ fflush (stdout );
164
+ _Exit (1 );
165
+ }
166
+ break ;
167
+ }
168
+ default : {
169
+ if (bg == 0 || fgONLY == 1 ) /*If foreground process, wait for the process to finish*/
170
+ waitpid (spawnPID , & childExitStatus , 0 );
171
+ else if (bg == 1 ) {
172
+ printf ("background pid is %d\n" , spawnPID ); /*If background process, run in the background with WNOGANG*/
173
+ fflush (stdout );
174
+ }
175
+ }
176
+ }
177
+ }
178
+ spawnPID = waitpid (-1 , & childExitStatus , WNOHANG ); /*WNOHANG process*/
179
+ while (spawnPID > 0 ){ /*Print status when it has been completed*/
180
+ printf ("background process, %i, is done: " , spawnPID );
181
+ fflush (stdout );
182
+ if (WIFEXITED (childExitStatus )) {
183
+ printf ("exit value %i\n" , WEXITSTATUS (childExitStatus ));
184
+ fflush (stdout );
185
+ }
186
+ else {
187
+ printf ("terminated by signal %i\n" , childExitStatus );
188
+ fflush (stdout );
189
+ }
190
+ spawnPID = waitpid (-1 , & childExitStatus , WNOHANG );
191
+ }
192
+ }
193
+ }
194
+ }
195
+
196
+ // Find and replace function used to replace the $$ token
197
+ char * findAndReplace (char * str , int PID ) {
198
+ char newW [100 ], * result ; //put PID into string
199
+ sprintf (newW , "%d" , PID );
200
+ int i , count = 0 , newWlen = strlen (newW );
201
+
202
+ for (i = 0 ; str [i ] != '\0' ; i ++ ) {
203
+ if (strstr (& str [i ], "$$" ) == & str [i ]) {
204
+ count ++ ;
205
+ i ++ ;
206
+ }
207
+ }
208
+
209
+ /*walk through the word, and replace every instance of $$*/
210
+ result = (char * )malloc (i + count * (newWlen - 2 ) + 1 );
211
+
212
+ i = 0 ;
213
+ while (* str ) {
214
+ if (strstr (str , "$$" ) == str ) {
215
+ strcpy (& result [i ], newW );
216
+ i += newWlen ;
217
+ str += 2 ;
218
+ }
219
+ else
220
+ result [i ++ ] = * str ++ ;
221
+ }
222
+
223
+ result [i ] = '\0' ;
224
+ return result ;
64
225
}
0 commit comments