/* shell0.c - collect argv array from command line and execvp * 2009.09.24 Neal Nelson * * This version does not use strspn or strcspn, only strcpy. * * BUGS: This version has a memory leak because we malloc and do not free * each time through a shell command loop. * */ #include #include #include #include #define MAXLINE 80 #define MAXWORDS 3 char *getArg(char *buf, char *word); void *malloc(); /* should probably use calloc in general */ main() { char buf[MAXLINE]; /* fgets reads only MAXLINE-1 and adds zero */ char word[MAXLINE+1]; /* add one for zero at end of line */ char *argv[MAXWORDS+1]; /* make room for zero at end of argv array */ char *p; int i,argc; int pid; /* Display argv for command lines until EOF (^d) at begin of line */ printf("Entering new shell... enter ^d in first column to exit\n"); while (fgets(buf, MAXLINE, stdin) != NULL) { /* fill up argv */ p = buf; for (argc = 0; (p = getArg(p,word)) != NULL && argc < MAXWORDS; argc++) { printf(" >%s\n", word); argv[argc] = (char *)malloc(strlen(word) + 1); strcpy(argv[argc],word); /* an extra copy operation */ } argv[argc] = (char *)0; /* Put NULL pointer to char at end of argv array */ /* Print out argv */ printf("The words in argv (max %d) ...\n",MAXWORDS); for (i = 0; i < argc; i++) { printf("%s\n",argv[i]); } /* Now fork a child to run the command */ pid = fork(); if (pid < 0) { perror("fork failed"); exit(-1); } /* Child */ else if (pid == 0) { printf(" Child Process\n"); printf(" Executing %s command\n", argv[0]); printf("-----------------------------------------------------------\n"); execvp(argv[0],&argv[0]); /* If execvp returns, the call has failed */ perror("execvp failed to run"); exit(-1); } /* Parent */ else { wait( NULL ); printf("-----------------------------------------------------------\n"); printf("Parent Process\n"); printf("--child has completed the %s command\n",argv[0]); } } printf("Leaving new shell...\n"); } /* Copy next word after bufptr to word array (allocated by caller). * Return new bufptr or NULL if no word found */ char* getArg(char *bufptr, char *word) { char *p; int i; for (p = bufptr; isspace(*p); p++); /* skip leading spaces */ for (i = 0; !isspace(*p) && *p != '\0'; ) /* get next word */ { word[i++] = *p++; } word[i] = '\0'; return ( (i == 0) ? NULL : p ); /* if (i == 0) return NULL; else return p; */ }