int Process::join(int pid) { int status; if(pid < 1) return -1; #ifdef HAVE_WAITPID waitpid(pid, &status, 0); #else #ifdef HAVE_WAIT4 wait4(pid, &status, 0, NULL); #else int result; while((result = wait(&status)) != pid && result != -1) ; #endif #endif if(WIFEXITED(status)) return WEXITSTATUS(status); else if(WIFSIGNALLED(status)) return -WTERMSIG(status); else return -1; }
int execCommand(char *cmd) { if (*cmd == '#') return 0; // remove comments int currentlyInString = 0; char *commentScan = cmd; while (*commentScan != 0) { if ((*commentScan) == '"') currentlyInString = !currentlyInString; else if (((*commentScan) == '#') && (!currentlyInString)) { *commentScan = 0; break; }; commentScan++; }; if (*cmd == 0) return 0; char processedCommand[1024]; char *put = processedCommand; char *scan = cmd; while (*scan != 0) { if (*scan == '\\') { scan++; if (*scan == 0) break; *put++ = *scan++; continue; } else if (*scan == '$') { char envname[256]; char *envnameput = envname; scan++; while (isalnum(*scan)) { *envnameput++ = *scan++; }; *envnameput = 0; char *value = getenv(envname); if (value != NULL) { strcpy(put, value); put += strlen(value); }; } else { *put++ = *scan++; }; }; *put = 0; int argc = 0; char **argv = NULL; char *nextToStrtok = processedCommand; while (1) { //char *token = strtok(nextToStrtok, nextSplitString); char *token = nextToStrtok; #if 0 nextToStrtok = NULL; if (token != NULL) { if (strlen(token) == 0) continue; }; #endif if (token != NULL) { while (isspace(*token)) token++; if (*token == 0) { token = NULL; } else { const char *termString = " \t"; if (*token == '"') { termString = "\""; token++; }; char *endpos = strpbrk(token, termString); if (endpos == NULL) { nextToStrtok = NULL; } else { *endpos = 0; nextToStrtok = endpos+1; }; }; }; int shouldAdd = 0; if (token == NULL) { shouldAdd = 1; } else { if (strlen(token) > 0) { shouldAdd = 1; }; }; if (shouldAdd) { argv = realloc(argv, sizeof(char*)*(argc+1)); argv[argc++] = token; }; if (token == NULL) break; }; if (argc == 1) return 0; if (strcmp(argv[0], "cd") == 0) { int status = cmd_cd(argc-1, argv); free(argv); return status; } else if (strcmp(argv[0], "exit") == 0) { int status = cmd_exit(argc-1, argv); free(argv); return status; } else if (strcmp(argv[0], "echo") == 0) { int status = cmd_echo(argc-1, argv); free(argv); return status; } else if (strcmp(argv[0], "diag") == 0) { _glidix_diag(); free(argv); return 0; }; char execpath[256]; if (findCommand(execpath, argv[0]) == -1) { free(argv); fprintf(stderr, "%s: command not found\n", argv[0]); return 1; }; pid_t pid = fork(); if (pid == 0) { if (execv(execpath, argv) != 0) { perror(argv[0]); return 1; }; // the compiler won't stop moaning otherwise. // even though execv() obviously doesn't return. return 0; } else { free(argv); shellChildPid = pid; int status; while (1) { int ret = waitpid(pid, &status, 0); // EINTR is the only possible error here, so if it occurs, try again. if (ret != -1) { break; }; }; shellChildPid = 0; if (WIFSIGNALLED(status)) { int termsig = WTERMSIG(status); switch (termsig) { case SIGSEGV: fprintf(stderr, "Invalid memory access\n"); break; case SIGSYS: fprintf(stderr, "Invalid system call\n"); break; }; }; return status; }; };