c - Why can't my shell start firefox? -
i'm writing small shell exercis learn c. can execute custom commands ls
, date
when try run firefox doesn't start. why? session
$ ./a.out minishell>> ls ls a.out digenv2.c~ digenv.c.orig minishell.c readme.md test digenv digenv.c digenv.old.c minishell.c~ smallshell.c digenv2.c digenv.c~ license minishell.c.orig smallshell.c.orig minishell>> date date tue may 12 09:38:27 cest 2015 minishell>> firefox firefox minishell>>
my program is
#include <sys/stat.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <dirent.h> #include <errno.h> #include <stdarg.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> #define buffer_len 1024 #define buffersize 1024 pid_t foreground = -1; int mystrcmp(char const *, char const *); struct command { char * const *argv; }; void err_syserr(char *fmt, ...) { int errnum = errno; va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); if (errnum != 0) fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum)); exit(exit_failure); } int startswith(const char *a, const char *b) { if(strncmp(a, b, strlen(b)) == 0) return 1; return 0; } /* helper function spawns processes */ /*static int spawn_proc(int in, int out, struct command *cmd) { pid_t pid; if ((pid = fork()) == 0) { if (in != 0) { if (dup2(in, 0) < 0) err_syserr("dup2() failed on stdin %s: ", cmd->argv[0]); ; close(in); } if (out != 1) { if (dup2(out, 1) < 0) err_syserr("dup2() failed on stdout %s: ", cmd->argv[0]); close(out); } fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd->argv[0]); execvp(cmd->argv[0], cmd->argv); err_syserr("failed execute %s: ", cmd->argv[0]); } else if (pid < 0) { err_syserr("fork failed: "); } return pid; }*/ /* helper function forks pipes */ /*static void fork_pipes(int n, struct command *cmd) { int i; int in = 0; int fd[2]; (i = 0; < n - 1; ++i) { pipe(fd); spawn_proc(in, fd[1], cmd + i); close(fd[1]); in = fd[0]; } if (dup2(in, 0) < 0) { err_syserr("dup2() failed on stdin %s: ", cmd[i].argv[0]); } fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd[i].argv[0]); execvp(cmd[i].argv[0], cmd[i].argv); err_syserr("failed execute %s: ", cmd[i].argv[0]); }*/ /*remove zoombie processes*/ /*return if background process terminated*/ /* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html */ void janitor(int status) { if(status==sigchld) { /*child process terminated, stopped, or continued*/ int = 1; while(a) { pid_t pid_my1 = waitpid(-1, &status, wnohang); /*wnohang = return if no child has exited*/ /*wait*/ /*http://linux.die.net/man/2/waitpid*/ if(0<pid_my1) { /*still things clean up*/ if(pid_my1!=foreground) { /*don't stop me since it's foregound process*/ /*http://linux.die.net/man/3/wait*/ if(wifexited(status)) { /*child process terminated*/ printf("%d terminated", pid_my1); } } } else { /*all work done, now*/ = 0; } } } } int main() { char line[buffer_len]; char* argv[100]; char* path= "/bin/"; char progpath[20]; int argc; size_t length; char *token; int i=0; int pid; char *tokenstr; char *search = " "; int issignal = 0; int isbackground = 0; #ifdef sigdet #if sigdet == 1 issignal = 1; /*termination detected signals*/ #endif #endif while(1) { = 0; int built_in_command = 0; printf("minishell>> "); if(!fgets(line, buffer_len, stdin)) { break; } length = strlen(line); if (line[length - 1] == '\n') { line[length - 1] = '\0'; } if(strcmp(line, "exit")==0) { break; } if(startswith(line, "cd")) { built_in_command=1; printf("change directory\n"); tokenstr = strtok(line, search); tokenstr = strtok(null, search); chdir(tokenstr); /*todo maybe have check whether argument exist, if not go home directory*/ } token = strtok(line," "); while(token!=null) { argv[i]=token; token = strtok(null," "); i++; } if(startswith(line, "checkenv")) { built_in_command=1; if (0==i) { char *printenv[] = { "printenv", 0}; char *sort[] = { "sort", 0 }; char *less[] = { "less", 0 }; struct command cmd[] = { {printenv}, {sort}, {less} }; fork(); } else { char *tmp; int len = 1; (i = 1; < argc; i++) { len += strlen(argv[i]) + 2; } tmp = (char *) malloc(len); tmp[0] = '\0'; int pos = 0; (i = 1; < argc; i++) { pos += sprintf(tmp + pos, "%s%s", (i == 1 ? "" : "|"), argv[i]); } char *printenv[] = { "printenv", 0}; char *grep[] = { "grep", "-e", tmp, null}; char *sort[] = { "sort", 0 }; char *less[] = { "less", 0 }; struct command cmd[] = { {printenv}, {grep}, {sort}, {less} }; fork(); free(tmp); } } if(0==built_in_command) { /*not built in command, let execute it*/ argv[i]=null; argc=i; for(i=0; i<argc; i++) { printf("%s\n", argv[i]); } strcpy(progpath, path); strcat(progpath, argv[0]); for(i=0; i<strlen(progpath); i++) { if(progpath[i]=='\n') { progpath[i]='\0'; } } isbackground = 0; sigset_t my_sig; pid_t pid_temp; int lastelem = (sizeof(line)/sizeof(line[0]))-1; /*last input argument index*/ /*todo check if background process*/ /*todo store time forground process started*/ int fd[2]; if (isbackground == 1) { //if backgroundprocess pipe(fd); /*(two new file descriptors)*/ /*fixme pid_temp = fork_pipes(2, .....);*/ pid_temp = fork(); } else if (isbackground == 0) { //if foreground process int issignal = 0; /*fixme*/ if (1 == issignal) { /*if using signaldetection*/ sigemptyset(&my_sig); /*empty , initialising signal set*/ sigaddset(&my_sig, sigchld); /*adds signal signal set (my_sig)*/ /*http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigprocmask.html*/ sigprocmask(sig_block, &my_sig, null); } /*fixme pid_temp = fork_pipes(2, .....);*/ pid_temp = fork(); foreground = pid_temp; /*set pid foreground process*/ } if (0<pid_temp) { /*parent process*/ } else if (0>pid_temp) { /*error*/ } else { /*child process*/ if (1 == isbackground) { //backgroundprocess dup2(fd[stdin_fileno], stdin_fileno); close(fd[0]); close(fd[1]); } execvp(progpath,argv); /*todo execute command here, working*/ } if (0 == isbackground) { //foregroundprocess /*write here, emil*/ int status = 0; waitpid(pid_temp, &status, 0); /*foregroundprocess terminated*/ /*todo how long time total execution time*/ int issignal = 0; /*fixme*/ if (1 == issignal) { /*if using signaldetection*/ int = sigprocmask(sig_unblock, &my_sig, null); /*http://man7.org/linux/man-pages/man2/sigprocmask.2.html*/ if (0 == a) { /*sigprocmask successfull*/ } else { /*sigprocmask not successfull, return=-1*/ } janitor(sigchld); } } else if (1==isbackground) { close(fd[0]); close(fd[1]); } } /* pid= fork(); if(pid==0) { execvp(progpath,argv); fprintf(stderr, "child process not execvp\n"); } else { wait(null); printf("child exited\n"); }*/ } return (0); } int mystrcmp(char const *p, char const *q) { int = 0; for(i = 0; q[i]; i++) { if(p[i] != q[i]) return -1; } return 0; } int cd(char *pth) { char path[buffersize]; char cwd[buffersize]; char * return_value; int other_return; strcpy(path,pth); if(pth[0] != '/') { return_value = getcwd(cwd,sizeof(cwd)); strcat(cwd,"/"); strcat(cwd,path); other_return = chdir(cwd); } else { other_return = chdir(pth); } printf("spawned foreground process: %d\n", getpid()); return 0; }
the issue path. assume command in /bin/
whereas firefox
in /usr/bin/
. child going exec /bin/firefox
, fail. checking return code of execvp
have helped finding this. on success, execvp
family functions don't return. if do, know why.
Comments
Post a Comment