1 #include 2 #include "definitions.h" 3 #include "utilities.h" 4 #define MAXLINE 4096 5 void handleUserCommand() 6 { 7 // if( chk_pipe()==1) 8 // { 9 10 if (checkBuiltInCommands() == 0) { 11 //printf("%d",commandArgc); 12 13 launchJob(commandArgv, "STANDARD", 0, FOREGROUND); 14 //puts(commandArgv[1]); 15 } 16 } 17 18 //int check_pipe() 19 //{ 20 void pipelining(int flag) 21 { 22 char line[MAXLINE]; 23 FILE *fpin, *fpout; 24 char arg1[50],arg2[50]; 25 int i; 26 if(flag==2) 27 { 28 strcat(arg1,commandArgv[0]); 29 strcpy(arg2,commandArgv[2]); 30 } 31 else 32 { 33 for(i=0;istatus == SUSPENDED || job->status == WAITING_INPUT) 102 putJobForeground(job, TRUE); 103 else // status = BACKGROUND 104 putJobForeground(job, FALSE); 105 return 1; 106 } 107 if (strcmp("jobs", commandArgv[0]) == 0) { 108 printJobs(); 109 return 1; 110 } 111 if (strcmp("kill", commandArgv[0]) == 0) 112 { 113 if (commandArgv[1] == NULL) 114 return 0; 115 killJob(atoi(commandArgv[1])); 116 return 1; 117 } 118 //int i; 119 ////for( i=0;i<=commandArgc;i++) 120 //{ 121 //char *str; 122 //strcpy(str,commandArgv); 123 if( commandArgc == 3 ) 124 { 125 if(strcmp("|", commandArgv[1]) == 0 ) 126 { 127 pipelining(2); 128 return 1; 129 } 130 //return 1; 131 } 132 if( commandArgc > 3 ) 133 { 134 if(strcmp("|", commandArgv[commandArgc-2]) == 0 ) 135 { 136 //puts("works"); 137 //printf("%d",commandArgc); 138 pipelining(commandArgc-1); 139 return 1; 140 } 141 } 142 //break; 143 //} 144 145 146 147 return 0; 148 } 149 150 void executeCommand(char *command[], char *file, int newDescriptor, 151 int executionMode) 152 { 153 int commandDescriptor; 154 if (newDescriptor == STDIN) { 155 commandDescriptor = open(file, O_RDONLY, 0600); 156 dup2(commandDescriptor, STDIN_FILENO); 157 close(commandDescriptor); 158 } 159 if (newDescriptor == STDOUT) { 160 commandDescriptor = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600); 161 dup2(commandDescriptor, STDOUT_FILENO); 162 close(commandDescriptor); 163 } 164 if (execvp(*command, command) == -1) 165 perror("MSH"); 166 } 167 168 void launchJob(char *command[], char *file, int newDescriptor, 169 int executionMode) 170 { 171 pid_t pid; 172 pid = fork(); 173 switch (pid) { 174 case -1: 175 perror("MSH"); 176 exit(EXIT_FAILURE); 177 break; 178 case 0: 179 signal(SIGINT, SIG_DFL); 180 signal(SIGQUIT, SIG_DFL); 181 signal(SIGTSTP, SIG_DFL); 182 signal(SIGCHLD, &signalHandler_child); 183 signal(SIGTTIN, SIG_DFL); 184 usleep(20000); 185 setpgrp(); 186 if (executionMode == FOREGROUND) 187 tcsetpgrp(MSH_TERMINAL, getpid()); 188 if (executionMode == BACKGROUND) 189 printf("[%d] %d\n", ++numActiveJobs, (int) getpid()); 190 191 executeCommand(command, file, newDescriptor, executionMode); 192 193 exit(EXIT_SUCCESS); 194 break; 195 default: 196 setpgid(pid, pid); 197 198 jobsList = insertJob(pid, pid, *(command), file, (int) executionMode); 199 200 t_job* job = getJob(pid, BY_PROCESS_ID); 201 202 if (executionMode == FOREGROUND) { 203 putJobForeground(job, FALSE); 204 } 205 if (executionMode == BACKGROUND) 206 putJobBackground(job, FALSE); 207 break; 208 } 209 } 210 211 void putJobForeground(t_job* job, int continueJob) 212 { 213 job->status = FOREGROUND; 214 tcsetpgrp(MSH_TERMINAL, job->pgid); 215 if (continueJob) { 216 if (kill(-job->pgid, SIGCONT) < 0) 217 perror("kill (SIGCONT)"); 218 } 219 220 waitJob(job); 221 tcsetpgrp(MSH_TERMINAL, MSH_PGID); 222 } 223 224 void putJobBackground(t_job* job, int continueJob) 225 { 226 if (job == NULL) 227 return; 228 229 if (continueJob && job->status != WAITING_INPUT) 230 job->status = WAITING_INPUT; 231 if (continueJob) 232 if (kill(-job->pgid, SIGCONT) < 0) 233 perror("kill (SIGCONT)"); 234 235 tcsetpgrp(MSH_TERMINAL, MSH_PGID); 236 } 237 238 void waitJob(t_job* job) 239 { 240 int terminationStatus; 241 while (waitpid(job->pid, &terminationStatus, WNOHANG) == 0) { 242 if (job->status == SUSPENDED) 243 return; 244 } 245 jobsList = delJob(job); 246 } 247 248 void killJob(int jobId) 249 { 250 t_job *job = getJob(jobId, BY_JOB_ID); 251 kill(job->pid, SIGKILL); 252 } 253 254 void changeDirectory() 255 { 256 if (commandArgv[1] == NULL) { 257 chdir(getenv("HOME")); 258 } else { 259 if (chdir(commandArgv[1]) == -1) { 260 printf(" %s: no such directory\n", commandArgv[1]); 261 } 262 } 263 } 264 265 266 void init() 267 { 268 MSH_PID = getpid(); 269 MSH_TERMINAL = STDIN_FILENO; 270 MSH_IS_INTERACTIVE = isatty(MSH_TERMINAL); 271 272 if (MSH_IS_INTERACTIVE) { 273 while (tcgetpgrp(MSH_TERMINAL) != (MSH_PGID = getpgrp())) 274 kill(MSH_PID, SIGTTIN); 275 276 signal(SIGQUIT, SIG_IGN); 277 signal(SIGTTOU, SIG_IGN); 278 signal(SIGTTIN, SIG_IGN); 279 signal(SIGTSTP, SIG_IGN); 280 signal(SIGINT, SIG_IGN); 281 signal(SIGCHLD, &signalHandler_child); 282 283 setpgid(MSH_PID, MSH_PID); 284 MSH_PGID = getpgrp(); 285 if (MSH_PID != MSH_PGID) { 286 printf("Error, the shell is not process group leader"); 287 exit(EXIT_FAILURE); 288 } 289 if (tcsetpgrp(MSH_TERMINAL, MSH_PGID) == -1) 290 tcgetattr(MSH_TERMINAL, &MSH_TMODES); 291 292 currentDirectory = (char*) calloc(1024, sizeof(char)); 293 } else { 294 printf("Could not make MSH interactive. Exiting..\n"); 295 exit(EXIT_FAILURE); 296 } 297 } 298 299 int main(int argc, char **argv, char **envp) 300 { 301 init(); 302 welcomeScreen(); 303 shellPrompt(); 304 while (TRUE) { 305 userInput = getchar(); 306 switch (userInput) { 307 case '\n': 308 shellPrompt(); 309 break; 310 default: 311 getTextLine(); 312 handleUserCommand(); 313 shellPrompt(); 314 break; 315 } 316 } 317 printf("\n"); 318 return 0; 319 } 320 321 void signalHandler_child(int p) 322 { 323 pid_t pid; 324 int terminationStatus; 325 pid = waitpid(WAIT_ANY, &terminationStatus, WUNTRACED | WNOHANG); 326 if (pid > 0) { 327 t_job* job = getJob(pid, BY_PROCESS_ID); 328 if (job == NULL) 329 return; 330 if (WIFEXITED(terminationStatus)) { 331 if (job->status == BACKGROUND) { 332 printf("\n[%d]+ Done\t %s\n", job->id, job->name); 333 jobsList = delJob(job); 334 } 335 } else if (WIFSIGNALED(terminationStatus)) { 336 printf("\n[%d]+ KILLED\t %s\n", job->id, job->name); 337 jobsList = delJob(job); 338 } else if (WIFSTOPPED(terminationStatus)) { 339 if (job->status == BACKGROUND) { 340 tcsetpgrp(MSH_TERMINAL, MSH_PGID); 341 changeJobStatus(pid, WAITING_INPUT); 342 printf("\n[%d]+ suspended [wants input]\t %s\n", 343 numActiveJobs, job->name); 344 } else { 345 tcsetpgrp(MSH_TERMINAL, job->pgid); 346 changeJobStatus(pid, SUSPENDED); 347 printf("\n[%d]+ stopped\t %s\n", numActiveJobs, job->name); 348 } 349 return; 350 } else { 351 if (job->status == BACKGROUND) { 352 jobsList = delJob(job); 353 } 354 } 355 tcsetpgrp(MSH_TERMINAL, MSH_PGID); 356 } 357 }