void run_minishell2(t_struc *s, char **tab) { int i; char **tab2; i = 0; while (tab[i]) { tab2 = ft_strdoublesplit(tab[i], ' ', '\t'); if (replace_tild(s, &tab2) == -1) break ; s->argc = get_argc(tab2); s->cmd = tab2[0]; if (!s->cmd) break ; s->argv = tab2; if (!ft_strcmp(s->cmd, "exit")) exec_exit(s); g_ctrl_c = 1; !is_builtin(s) ? exec_cmd(s, s->env) : exec_builtin(s, s->env); free(s->cmd); i++; } }
/*parse command to linked list and send to exec function*/ void parse_command(){ int EXIT; int i=0,j,d; int test = 0; int length = strlen(buffer); int count = 1; int start = 0; int temp = 0; int currarg = 0; struct Node* head = malloc(sizeof(struct Node)); memset(head->args,0,sizeof(int) * 50); head->next = NULL; struct Node* ptr = head; for(i = 0; i < length; i++){ char c = buffer[i]; if(currarg >= 50){ fprintf(stderr,"Too many arguements\n"); test = 2; break; } if(!temp){ if(c == '|'){ count++; currarg = 0; ptr->next = malloc(sizeof(struct Node)); ptr = ptr->next; memset(ptr->args,0,sizeof(int) * 50); ptr->next = NULL; }else if(c == '\''){ temp = 1; start = i; }else if(c == '\"'){ temp = 2; start = i; }else if(c != ' ' && c!= '\t'){ temp = 3; start = i; } }else if((temp == 1 && c == '\'') || (temp == 2 && c == '\"')){ temp = 0; ptr->args[currarg] = malloc(sizeof(char) * (i - start + 2)); memcpy(ptr->args[currarg],buffer + sizeof(char) * (start + 1), sizeof(char) * ((i - 1) - start)); ptr->args[currarg][(i - 1) - start] = '\0'; currarg++; }else if(temp == 3 && (c == ' ' || i == length - 1)){ temp = 0; ptr->args[currarg] = malloc(sizeof(char) * (i - start + 2)); memcpy(ptr->args[currarg],buffer + sizeof(char) * start, sizeof(char) * (i - start)); ptr->args[currarg][i - start] = '\0'; currarg++; }else if(temp == 3 && c == '|'){ temp = 0; ptr->args[currarg] = malloc(sizeof(char) * (i - start + 2)); memcpy(ptr->args[currarg],buffer + sizeof(char) * start, sizeof(char) * (i - start)); ptr->args[currarg][i - start] = '\0'; count++; currarg = 0; ptr->next = malloc(sizeof(struct Node)); ptr = ptr->next; memset(ptr->args,0,sizeof(int) * 50); ptr->next = NULL; }else if(c == '\'' || c == '\"'){ fprintf(stderr,"error: quote mismatch\n"); test = 1; break; } } /*send to cd function*/ if(!strcmp(head->args[0], "cd")){ exec_cd(2, head->args); freeList(head); return; } /*send to exit function*/ if(!strcmp(head->args[0], "exit")){ exec_exit(2, head->args); freeList(head); return; } if(!test && (temp == 1 || temp == 2)){ fprintf(stderr,"error: quote mismatch\n"); test = 1; } if(head->args[0] == NULL){ test = 1; } if(!test){ exec_command(head, -1); int status; int pid; while((pid = wait(&status)) != -1) printf("process %i exits with %i\n",pid,status); } freeList(head); }
int nt_execve(const char *prog, const char *const *args, const char *const *envir) { STARTUPINFO si; PROCESS_INFORMATION pi; enum {none, directex, shellex} execmode; DWORD exitcode; DWORD dwCreationflags; int priority; char *argv0; char *cmdstr, *cmdend; unsigned int cmdsize; size_t prognamelen, cmdlen; int hasext; char extension[_MAX_FNAME]; const char *begin, *end, *extptr; static char exts[MAX_PATH]; UNREFERENCED_PARAMETER(envir); /* get default PATHEXT or use empty exts */ if (!*exts) { DWORD rc; /* not initialized */ rc = GetEnvironmentVariable("PATHEXT", exts, sizeof(exts)); if ((rc == 0) || (rc >= sizeof(exts))) /* if error or PATHEXT too big will retry at the next call */ *exts = 0; } /* if prog has an extension initialize begin end to skip PATHEXT search */ prognamelen = strlen(prog); extptr = prog + prognamelen - 1; hasext = 0; while (extptr > prog && !ISPATHSEP(*extptr)) { if (*extptr == '.' && *(extptr - 1) != ':' && !ISPATHSEP(*(extptr - 1))) { hasext++; break; } extptr--; } if (hasext) { begin = "."; end = ""; strcpy(extension, extptr); } else { begin = exts; end = exts; *extension = '\0'; } argv0 = (char *)heap_alloc(MAX_PATH); /* (prognamelen + 1) does not really matter, argv0 is '\0' filled */ memcpy(argv0, prog, prognamelen + 1); errno = 0; execmode = none; /* NOTE: loops over PATHEXT if no extension found */ while (*begin) { size_t extlen; if (GetBinaryType(argv0, &exitcode)) { /* exists and is executable NOTE: an "xxx.exe" without a correct PE header (i.e. a text file) has type "DOS binary", but execution will generate a WOW error */ execmode = directex; break; } if (GetLastError() == ERROR_BAD_EXE_FORMAT) { /* exists but is not "executable" */ execmode = shellex; break; } if (hasext) break; /* get next PATHEXT extension */ while (*begin && (*begin != '.')) begin++; while (*end && (*end != ';')) end++; if (!*begin) break; extlen = end - begin; if (extlen < sizeof(extension)) { memcpy(extension, begin, extlen); extension[extlen] = '\0'; /* prognamelen ignores the last '\r' if present */ memcpy(argv0, prog, prognamelen); /* update argv0 adding the extension to prog */ memcpy(argv0 + prognamelen, extension, extlen + 1); } begin = end; /* skip sequences of ';' */ while (*end && *end == ';') end++; }; cmdstr = (char *)heap_alloc(MAX_PATH << 2); cmdsize = MAX_PATH << 2; cmdlen = 0; cmdend = cmdstr; dbgprintf(PR_VERBOSE, "%s(): execute [%s] extension=[%s] mode=%d hasext=%d\n", __FUNCTION__, argv0, extension, execmode, hasext); /* skip over program name */ args++; /* the file (after PATHEXT search) exists, but it's not "executable" */ if (execmode == shellex) { /* if prog had no extension or has the extension associated to shell scripts */ if ((hasext == 0 && *extension == '\0') || is_shell_script(extension)) { int res = process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize); if (res < 0) { execmode = none; } else if (res == 0) { char *newargv[2]; cmdlen = copy_quote_and_fix_slashes(gModuleName, cmdstr); cmdend = cmdstr + cmdlen; newargv[0] = path_to_slash(argv0); newargv[1] = NULL; concat_args_and_quote((const char *const *)newargv, &cmdstr, &cmdlen, &cmdend, &cmdsize); *cmdend = 0; argv0 = gModuleName; execmode = directex; } else { cmdend = cmdstr + cmdlen; execmode = directex; } } else { unsigned long shflags = 0L; /* if the file extension is in pathext, use the same console and wait for child. StrStrI() is from shlwapi */ if (StrStrI(exts, extension)) shflags = SEE_MASK_NO_CONSOLE | SEE_MASK_NOCLOSEPROCESS; if (try_shell_ex(argv0, args, shflags, &cmdstr, &cmdsize)) return (0); /* ShellExecute failed, the file has an unknown extension, but it may be a shell script with a shebang */ if (process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize) > 0) { cmdend = cmdstr + cmdlen; execmode = directex; } else { /* the file extension is NOT known and the file has NO shebang: returns EPERM, see NOTES */ errno = EPERM; return (-1); } } } else if (execmode == directex) { cmdlen = copy_quote_and_fix_slashes(prog, cmdstr); cmdend = cmdstr + cmdlen; } if (execmode == none) { /* error: prog not found even after trying PATHEXT extensions */ errno = ENOENT; return (-1); } concat_args_and_quote(args, &cmdstr, &cmdlen, &cmdend, &cmdsize); if (*cmdstr == ' ') { /* if we left a ' ' for the quote and there is no quote */ cmdstr++; cmdlen--; } *cmdend = 0; init_startupinfo(&si); dwCreationflags = GetPriorityClass(GetCurrentProcess()); priority = GetThreadPriority(GetCurrentThread()); #if defined(W32DEBUG) /* DebugView output is very difficult to read with overlong lines */ if (cmdlen < 128) dbgprintf(PR_EXEC, "%s(): CreateProcess(%s, ..) cmdstr=[%s]\n", __FUNCTION__, argv0, cmdstr); else { char shortbuf[128+4]; memcpy(shortbuf, cmdstr, 128); memcpy(shortbuf + 128, "...", 4); dbgprintf(PR_EXEC, "nt_execve(): CreateProcess(%s, ..) cmdstr=[%s]\n", argv0, shortbuf); } #endif if (!CreateProcess(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles dwCreationflags | CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { exitcode = GetLastError(); if (exitcode == ERROR_BAD_EXE_FORMAT) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error BAD_EXE_FORMAT in %s\n", argv0, __FUNCTION__); errno = ENOEXEC; } else if (exitcode == ERROR_INVALID_PARAMETER) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error INVALID_PARAMETER in %s, cmdstr len=%u\n", argv0, __FUNCTION__, strlen(cmdstr)); /* exceeded command line */ /* return NOT found, ENAMETOOLONG is correct but not understood by the shell that will retry with another path ... */ errno = ENOENT; } else { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error %ld in %s\n", argv0, exitcode, __FUNCTION__); errno = ENOENT; } goto fail_return; } else { exitcode = 0; if (!SetThreadPriority(pi.hThread, priority)) dbgprintf(PR_ERROR, "!!! SetThreadPriority(0x%p) failed, error %ld\n", pi.hThread, GetLastError()); ResumeThread(pi.hThread); if (!is_gui(argv0)) { if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) dbgprintf(PR_ERROR, "!!! error %ld waiting for process %ld\n", GetLastError(), pi.dwProcessId); if (!GetExitCodeProcess(pi.hProcess, &exitcode)) dbgprintf(PR_ERROR, "!!! GetExitCodeProcess(0x%p, ..) error %ld in %s\n", pi.hProcess, GetLastError(), __FUNCTION__); } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close_si_handles(); /* @@@@ should wait for the clipboard ? if (is_dev_clipboard_active) { CloseHandle((HANDLE)_get_osfhandle(0)); CloseHandle((HANDLE)_get_osfhandle(1)); CloseHandle((HANDLE)_get_osfhandle(2)); ... WaitForSingleObject(ghdevclipthread,60*1000); } */ dbgprintf(PR_ALL, "--- %s(): Exec'd process %ld terminated with exitcode %ld\n", __FUNCTION__, pi.dwProcessId, exitcode); exec_exit((int)exitcode); } fail_return: heap_free(cmdstr); close_si_handles(); exec_exit(-1); return (-1); }
void sys_exit(void) { exec_exit(); }
static int try_shell_ex(char *argv0, const char *const *argv, unsigned long shellexflags, char **cmdstr, unsigned int *cmdsize) { char *cmdend; size_t cmdlen; SHELLEXECUTEINFO shinfo; BOOL nocmd = 0; path_to_backslash(argv0); /* @@@@ is this code really needed ? when ? */ if ((!*argv) && (argv0[0] == '\\') && (argv0[1] == '\\')) { shellexflags |= SEE_MASK_CONNECTNETDRV; nocmd = 1; goto noargs; } cmdend = *cmdstr; cmdlen = 0; concat_args_and_quote(argv, cmdstr, &cmdlen, &cmdend, cmdsize); *cmdend = '\0'; noargs: dbgprintf(PR_EXEC, "ShellExecute(%s, ..) with cmdstr [%s]\n", argv0, *cmdstr); memset(&shinfo, 0, sizeof(shinfo)); shinfo.cbSize = sizeof(shinfo); shinfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_DDEWAIT | shellexflags; shinfo.hwnd = NULL; shinfo.lpVerb = NULL; shinfo.lpFile = argv0; shinfo.lpParameters = nocmd ? NULL : *cmdstr; shinfo.lpDirectory = 0; shinfo.nShow = SW_SHOWDEFAULT; if (ShellExecuteEx(&shinfo)) { DWORD retval = 255; dbgprintf(PR_EXEC, "ShellExecute() created process handle 0x%p\n", shinfo.hProcess); /* may happen if "executing" a file associated to a running program, i.e. "execute" a .html file with an already opened browser window */ if (shinfo.hProcess != (HANDLE)0) { if (shellexflags & SEE_MASK_NOCLOSEPROCESS) { if ((intptr_t)(shinfo.hInstApp) > 32) { if (WaitForSingleObject(shinfo.hProcess, INFINITE) == WAIT_OBJECT_0) { /* try to get the return value */ GetExitCodeProcess(shinfo.hProcess, &retval); } else { dbgprintf(PR_ERROR, "!!! ShellExecute() [%s] WaitForSingleObject() error %ld\n", argv0, GetLastError()); } } else { dbgprintf(PR_ERROR, "!!! ShellExecute() [%s] error %p\n", argv0, shinfo.hInstApp); } } /* try to close, it may fail but .. what else could we do */ CloseHandle(shinfo.hProcess); } dbgprintf(PR_ALL, "--- %s(): ShellExecute() OK, exiting with code %ld\n", __FUNCTION__, retval); exec_exit((int)retval); } else { dbgprintf(PR_EXEC, "ShellExecute() failed\n"); } return (0); }