Skip to content

Commit 25a4b65

Browse files
committed
Completed files for Program 3
1 parent babfe55 commit 25a4b65

File tree

2 files changed

+228
-67
lines changed

2 files changed

+228
-67
lines changed

Program 3 - smallsh/makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
sh: smallsh.c
2-
gcc -o smallsh smallsh.c
3-
clean:
4-
rm -rf *.o smallsh
1+
sh: smallsh.c
2+
gcc -o smallsh smallsh.c
3+
clean:
4+
rm -rf *.o smallsh

Program 3 - smallsh/smallsh.c

Lines changed: 224 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,225 @@
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;
64225
}

0 commit comments

Comments
 (0)