Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
- #include <dirent.h>
- #include <fcntl.h>
- #include <glob.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <ctype.h>
- #include <errno.h>
- #define LOGOUT 50
- #define MAXNUM 40
- #define MAXLEN 500
- #define MAXSIZE 500
- #define BUFSIZE 200
- #define TRUE 1
- #define FALSE 0
- typedef struct command_history
- {
- char *command;
- struct command_history *next;
- } history;
- void sighandler(int sig)
- {
- printf("\nauto logout\n");
- exit(0);
- }
- /* left_child --- do the work for the left child */
- void left_child(char *args[MAXNUM], int pipefd[2])
- {
- close(pipefd[0]);
- dup2(pipefd[1], STDOUT_FILENO);
- execvp(args[0], args);
- _exit(errno == ENOENT ? 127 : 126);
- }
- /* right_child --- do the work for the right child */
- void right_child(char *args2[MAXNUM],int pipefd[2])
- {
- close(pipefd[1]);
- dup2(pipefd[0], STDIN_FILENO);
- execvp(args2[0], args2);
- perror("execv");
- _exit(errno == ENOENT ? 127 : 126);
- }
- int SinglePipe2(char *args[MAXNUM], char *args2[MAXNUM], int redir_in, int redir_out, int fd){
- int pipefd[2];
- pid_t left_pid, right_pid;
- pid_t ret;
- pid_t pid;
- int status;
- if (pipe(pipefd) < 0) { /* create pipe, very first thing */
- perror("pipe");
- exit(1);
- }
- if ((left_pid = fork()) < 0) { /* fork left-hand child */
- perror("fork");
- exit(1);
- } else if (left_pid == 0)
- left_child(args, pipefd);
- if ((right_pid = fork()) < 0) { /* fork right-hand child */
- perror("fork");
- exit(1);
- } else if (right_pid == 0)
- right_child(args2, pipefd);
- close(pipefd[0]); /* close parent's copy of pipe */
- close(pipefd[1]);
- while ((ret = wait(& status)) > 0) { /* wait for children */
- if (ret == left_pid)
- printf("left child terminated, status: %x\n", status);
- else if (ret == right_pid)
- printf("right child terminated, status: %x\n", status);
- else
- printf("yow! unknown child %d terminated, status %x\n",
- ret, status);
- }
- switch (pid = fork()) {
- case -1:
- perror("fork");
- case 0:/* child process, exec() */
- if(redir_out){ //redirection to output file
- dup2(fd, STDOUT_FILENO);
- close(fd);
- }
- else if(redir_in){ //redirection to input file
- dup2(fd, STDIN_FILENO);
- close(fd);
- }
- if (execvp(args[0], args))
- perror("execv");
- exit(1);
- }
- return 1;
- }
- /* Main */
- int main(void)
- {
- char *currentpath, *cmd, line[MAXLEN], *args[MAXNUM], *args2[MAXNUM], *args3[MAXNUM];
- int background, i, j, t, wildcard, opts;
- int redir_in, redir_out;
- int fd;
- long size;
- char *buf;
- /*pid_t pid, pid2; */
- struct sigaction act;
- char *history[MAXSIZE], command[MAXSIZE], command_number[MAXSIZE], *temp;
- int history_count = 0, length, number, offs;
- int pipefd[2], pipefd2[2];
- int numberofpipes, pipesuccess;
- char buffer[BUFSIZE];
- FILE *fp;
- size = pathconf(".", _PC_PATH_MAX);
- buf = (char*)malloc((size_t)size);
- /* set the signal handler for alarm */
- signal(SIGALRM, sighandler);
- /*get default working directory as current path*/
- currentpath = getenv("PWD");
- while (1)
- {
- /* initialize */
- glob_t globbuf;
- background = FALSE;
- wildcard = FALSE;
- opts = FALSE;
- /*redir_in = FALSE; redir_out = FALSE;*/
- pipesuccess = FALSE;
- numberofpipes = 0, t = 0, offs = 0;
- globbuf.gl_offs = 0;
- /* print the prompt */
- fprintf(stdout, "%s > ", currentpath);
- /* set the timeout for autologout, function alarm() */
- alarm(LOGOUT);
- /* read the users command */
- if (fgets(line,MAXLEN,stdin) == NULL) {
- fprintf(stdout, "\nlogout\n");
- exit(0);
- }
- line[strlen(line) - 1] = '\0';
- if (strlen(line) == 0)
- continue;
- /* start to background? (check if the last character is '&') */
- if(line[strlen(line)-1] == '&')
- {
- line[strlen(line)-1] = '\0'; //remove '&'
- background = TRUE;
- }
- /* saving the user command into history list */
- if(line[0] != '!'){
- if (history_count < MAXSIZE){
- history[history_count] = strdup(line);
- history_count++;
- }
- }
- /* split the command line to args[]*/
- i = 0; //number of arguments
- cmd = line;
- while((args[i] = strtok(cmd, " ")) != NULL)
- {
- i++; //argument count
- cmd = NULL;
- }
- /* history usage */
- if(line[0] == '!')
- {
- // find right command index from history
- j = 0;
- while (isdigit(line[j+1])){
- command_number[j] = line[j+1];
- j++;
- }
- number = atoi(command_number);
- if (number <= history_count)
- {
- // parsing the history commands back into args
- t = 0;
- temp = history[number-1];
- while((args[t] = strtok(temp, " ")) != NULL)
- {
- t++;
- temp = NULL;
- }
- }
- else
- {
- printf("Out of range of array.\n");
- }
- }
- /* find and open redirected files*/
- for(j = 0; j < i; j++)
- {
- if(strcmp(args[j], ">") == 0){
- args[j] = NULL;
- fd = open(args[j+1], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
- redir_out = TRUE;
- if (fd < 0) {
- perror("open");
- exit(0);
- }
- }
- else if(strcmp(args[j], "<") == 0){
- args[j] = NULL;
- fd = open(args[j+1], O_RDONLY, S_IRUSR | S_IWUSR);
- redir_in = TRUE;
- if (fd < 0) {
- perror("open");
- exit(0);
- }
- }
- }
- /* exit? */
- if (strcmp(args[0], "exit") == 0) {
- exit(0);
- }
- /* wildcards */
- for(j = 0; j < i; j++) {
- // see if there're options
- if(!strncmp(args[j], "-", 1)) { opts = TRUE; }
- // enable and count the wildcards
- if(!strncmp(args[j], "*", 1) || !strncmp(args[j], "?", 1) || !strncmp(args[j], "[", 1)) {
- wildcard = TRUE;
- offs++;
- }
- }
- if(wildcard) {
- if(opts) // cmd with options
- {
- globbuf.gl_offs = 2;
- glob(args[2], GLOB_DOOFFS, NULL, &globbuf);
- for(j = 3; j < (offs+offs); j++)
- {
- glob(args[j], GLOB_DOOFFS|GLOB_APPEND, NULL, &globbuf);
- }
- globbuf.gl_pathv[0] = args[0];
- globbuf.gl_pathv[1] = args[1];
- }
- else // cmd without options
- {
- globbuf.gl_offs = 1;
- glob(args[1], GLOB_DOOFFS, NULL, &globbuf);
- for(j = 2; j < (offs+1); j++)
- {
- glob(args[j], GLOB_DOOFFS|GLOB_APPEND, NULL, &globbuf);
- }
- globbuf.gl_pathv[0] = args[0];
- }
- }
- /* cd */
- if (strcmp(args[0], "cd") == 0)
- {
- if(i > 1)
- {
- if(chdir(args[1]) != 0) //change to inputted directory
- {
- perror("chdir");
- }
- currentpath = getcwd(buf, (size_t)size); //set currentpath to cwd
- }
- else
- {
- currentpath = getenv("HOME"); // change to homedir
- }
- continue;
- }
- /* history */
- if(strcmp(args[0], "history") == 0)
- {
- printf("Command history: \n");
- for (j = 0; j < history_count; j++) {
- printf("[%d] %s \n", j+1, history[j]);
- }
- continue;
- }
- /* find pipe marks for single and double pipe*/
- int k=0, z=0, y=0;
- if(!redir_out && !redir_in){
- for (j = 0; j < i; j++) //i == argument count
- {
- if(strncmp(args[j], "|", 1) == 0){
- args[j] = NULL; // make it null, so exec will stop there
- numberofpipes++;
- continue;
- }
- if(numberofpipes == 1){
- args2[z] = args[j]; //copy other part of args to args2
- args2[z+1] = NULL; //make sure last args2 is (null)
- z++;
- continue;
- }
- if(numberofpipes == 2){
- args3[y] = args[j]; //copy other part of args to args3
- args3[y+1] = NULL; //make sure last args3 is (null)
- y++;
- }
- }
- }
- /* single pipe */
- if(numberofpipes == 1){
- SinglePipe2(args, args2, redir_in, redir_out, fd);
- }
- /* pipe(pipefd);
- if((pid = fork()) == -1){
- perror("fork");
- exit(1);
- }
- if(pid == 0) { /* child, args2
- close(pipefd[0]);
- dup2(pipefd[1], STDOUT_FILENO);
- close(pipefd[1]);
- execvp(args[0], args);
- }
- else { parent, args /*
- close(pipefd[1]);
- dup2(pipefd[0], STDIN_FILENO);
- close(pipefd[0]);
- execvp(args2[0], args2);
- perror("execv");
- }
- } */
- /* double pipe
- if(numberofpipes == 2){
- pipe(pipefd);
- pipe(pipefd2);
- if((pid = fork()) == -1){
- perror("fork");
- exit(1);
- }
- if(pid == 0) {
- if((pid2 = fork()) == -1){
- perror("fork 2");
- exit(1);
- }
- if(pid2 == 0){ /* grandchild, args3
- close(pipefd[0]);
- close(pipefd[1]);
- close(pipefd2[1]);
- dup2(pipefd2[0], STDIN_FILENO);
- close(pipefd2[0]);
- execvp(args3[0], args3);
- perror("execv");
- }
- else { /* child, args2
- close(pipefd[1]);
- dup2(pipefd[0], STDIN_FILENO);
- close(pipefd[0]);
- close(pipefd2[0]);
- dup2(pipefd2[1], STDOUT_FILENO);
- close(pipefd2[0]);
- execvp(args2[0], args2);
- perror("execv");
- }
- }
- else{ /* parent, args
- close(pipefd[0]);
- dup2(pipefd[1], STDOUT_FILENO);
- close(pipefd[1]);
- execvp(args[0], args);
- }
- } */
- /* fork to run the command
- switch (pid = fork()) {
- case -1:
- /* error
- perror("fork");
- continue;
- case 0:/* child process, exec()
- if(redir_out){ //redirection to output file
- dup2(fd, STDOUT_FILENO);
- close(fd);
- }
- else if(redir_in){ //redirection to input file
- dup2(fd, STDIN_FILENO);
- close(fd);
- }
- else if (wildcard) {
- execvp(globbuf.gl_pathv[0], globbuf.gl_pathv);
- perror("execv");
- globfree(&globbuf);
- exit(1);
- }
- else if (execvp(args[0], args)) {
- perror("execv");
- exit(1);
- }
- default:
- /* parent (shell), wait() if not background process
- if(!background){
- alarm(0);
- while(wait(NULL) != pid)
- {
- printf("please.");
- }
- }
- continue;
- } */
- }
- //globfree(&globbuf);
- free(buf);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement