/** * egg_desktop_file_parse_exec: * @desktop_file: a #EggDesktopFile * @documents: a list of document paths or URIs * @error: error pointer * * Parses @desktop_file's Exec key, inserting @documents into it, and * returns the result. * * If @documents contains non-file: URIs and @desktop_file does not * accept URIs, those URIs will be ignored. Likewise, if @documents * contains more elements than @desktop_file accepts, the extra * documents will be ignored. * * Return value: the parsed Exec string **/ char * egg_desktop_file_parse_exec (EggDesktopFile * desktop_file, GSList * documents, GError ** error) { GSList *translated, *docs; char *command; docs = translated = translate_document_list (desktop_file, documents); command = parse_exec (desktop_file, &docs, error); free_document_list (translated); return command; }
int main(int argc, char *argv[], char *envp[]){ root = NULL; history = NULL; exit_num = 0; size_t buff = BUFFSIZE; int bytes_read; char * cmd_line; cmd_line = (char*)malloc(buff + 1); for(;;){ #ifdef PROMPT printf("==>"); #endif bytes_read = getline(&cmd_line,&buff,stdin);//yeah prompt but stupid trailing newline if (bytes_read == -1){return 1;} else if(cmd_line[strlen(cmd_line) -1] == '\n'){ cmd_line[strlen(cmd_line) -1] = '\0'; } history = stack_push(history,cmd_line); cmd_line = sub_q(cmd_line); exit_num = parse_exec(cmd_line); } printf("goodbye\n"); return 1; }
static gboolean egg_desktop_file_launchv (EggDesktopFile *desktop_file, GSList *documents, va_list args, GError **error) { EggDesktopFileLaunchOption option; GSList *translated_documents = NULL, *docs = NULL; char *command, **argv; int argc, i, screen_num; gboolean success, current_success; GdkDisplay *display; char *startup_id; GPtrArray *env = NULL; char **variables = NULL; GdkScreen *screen = NULL; int workspace = -1; const char *directory = NULL; guint32 launch_time = (guint32)-1; GSpawnFlags flags = G_SPAWN_SEARCH_PATH; GSpawnChildSetupFunc setup_func = NULL; gpointer setup_data = NULL; GPid *ret_pid = NULL; int *ret_stdin = NULL, *ret_stdout = NULL, *ret_stderr = NULL; char **ret_startup_id = NULL; if (documents && desktop_file->document_code == 0) { g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE, _("Application does not accept documents on command line")); return FALSE; } /* Read the options: technically it's incorrect for the caller to * NULL-terminate the list of options (rather than 0-terminating * it), but NULL-terminating lets us use G_GNUC_NULL_TERMINATED, * it's more consistent with other glib/gtk methods, and it will * work as long as sizeof (int) <= sizeof (NULL), and NULL is * represented as 0. (Which is true everywhere we care about.) */ while ((option = va_arg (args, EggDesktopFileLaunchOption))) { switch (option) { case EGG_DESKTOP_FILE_LAUNCH_CLEARENV: if (env) g_ptr_array_free (env, TRUE); env = g_ptr_array_new (); break; case EGG_DESKTOP_FILE_LAUNCH_PUTENV: variables = va_arg (args, char **); for (i = 0; variables[i]; i++) env = array_putenv (env, variables[i]); break; case EGG_DESKTOP_FILE_LAUNCH_SCREEN: screen = va_arg (args, GdkScreen *); break; case EGG_DESKTOP_FILE_LAUNCH_WORKSPACE: workspace = va_arg (args, int); break; case EGG_DESKTOP_FILE_LAUNCH_DIRECTORY: directory = va_arg (args, const char *); break; case EGG_DESKTOP_FILE_LAUNCH_TIME: launch_time = va_arg (args, guint32); break; case EGG_DESKTOP_FILE_LAUNCH_FLAGS: flags |= va_arg (args, GSpawnFlags); /* Make sure they didn't set any flags that don't make sense. */ flags &= ~G_SPAWN_FILE_AND_ARGV_ZERO; break; case EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC: setup_func = va_arg (args, GSpawnChildSetupFunc); setup_data = va_arg (args, gpointer); break; case EGG_DESKTOP_FILE_LAUNCH_RETURN_PID: ret_pid = va_arg (args, GPid *); break; case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE: ret_stdin = va_arg (args, int *); break; case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE: ret_stdout = va_arg (args, int *); break; case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE: ret_stderr = va_arg (args, int *); break; case EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID: ret_startup_id = va_arg (args, char **); break; default: g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION, _("Unrecognized launch option: %d"), GPOINTER_TO_INT (option)); success = FALSE; goto out; } } if (screen) { char *display_name = gdk_screen_make_display_name (screen); char *display_env = g_strdup_printf ("DISPLAY=%s", display_name); env = array_putenv (env, display_env); g_free (display_name); g_free (display_env); display = gdk_screen_get_display (screen); } else { display = gdk_display_get_default (); screen = gdk_display_get_default_screen (display); } screen_num = gdk_screen_get_number (screen); translated_documents = translate_document_list (desktop_file, documents); docs = translated_documents; success = FALSE; do { command = parse_exec (desktop_file, &docs, error); if (!command) goto out; if (!g_shell_parse_argv (command, &argc, &argv, error)) { g_free (command); goto out; } g_free (command); #if GTK_CHECK_VERSION (2, 12, 0) startup_id = start_startup_notification (display, desktop_file, argv[0], screen_num, workspace, launch_time); if (startup_id) { char *startup_id_env = g_strdup_printf ("DESKTOP_STARTUP_ID=%s", startup_id); env = array_putenv (env, startup_id_env); g_free (startup_id_env); } #else startup_id = NULL; #endif /* GTK 2.12 */ if (env != NULL) g_ptr_array_add (env, NULL); current_success = g_spawn_async_with_pipes (directory, argv, env ? (char **)(env->pdata) : NULL, flags, setup_func, setup_data, ret_pid, ret_stdin, ret_stdout, ret_stderr, error); g_strfreev (argv); if (startup_id) { #if GTK_CHECK_VERSION (2, 12, 0) if (current_success) { set_startup_notification_timeout (display, startup_id); if (ret_startup_id) *ret_startup_id = startup_id; else g_free (startup_id); } else #endif /* GTK 2.12 */ g_free (startup_id); } else if (ret_startup_id) *ret_startup_id = NULL; if (current_success) { /* If we successfully launch any instances of the app, make * sure we return TRUE and don't set @error. */ success = TRUE; error = NULL; /* Also, only set the output params on the first one */ ret_pid = NULL; ret_stdin = ret_stdout = ret_stderr = NULL; ret_startup_id = NULL; } } while (docs && current_success); out: if (env) { g_ptr_array_foreach (env, (GFunc)g_free, NULL); g_ptr_array_free (env, TRUE); } free_document_list (translated_documents); return success; }
int parse_exec(const char* input){ if(input[0] == '\0'){return 1;} int ret = 0; int head = 0; int pipev = NO_PIPE; int pipeline = 0; char * parsable = (char *)strdup(input); if (parsable == NULL){ return 1; } char * command = NULL; char * params = NULL; char * file = NULL; for(;parsable[head] == ' ' || parsable[head] == '\t';head++){} int tail = head; for(;parsable[head] != '\0';head++){ if((parsable[head] == ' ' || parsable[head] == '\t') && command == NULL && pipev == NO_PIPE){//first word terminated by space character command = (char *)malloc(sizeof(char) *(head - tail + 1)); if (command == NULL){return 1;} if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;} command[head-tail] = '\0'; for(;parsable[head] == ' ' || parsable[head] == '\t';head++){}//discard any extra spaces after the first one tail = head; head--;//the head is at the next character but is going to get incremented so we must decrement first } else if((parsable[head] == '<' || parsable[head] == '>') && pipev == NO_PIPE){ if (parsable[head] == '<'){// this has a bug that I don't need to fix because the spec changed pipev = PIPE_IN; } else { pipev = PIPE_OUT; } if (tail != head){ if(command == NULL){//the first word is terminated with a pipe rather than a space command = (char *)malloc(head - tail + 1); if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;} command[head-tail] = '\0'; tail = head + 1;//We set the tail ahead of the head so that we don't include the current character } else { int back = head; for(;parsable[back] == ' ' || parsable[back] == '\t' || parsable[back] == '>'|| parsable[back] == '<';back--){} back++; params = (char *)malloc(back - tail + 1); if (strncpy(params,parsable + tail,back-tail) == NULL){return 1;} params[back-tail] = '\0'; tail = head + 1; } } } else if(parsable[head] == '|'){ if (pipev != NO_PIPE){//redirect was found first for(;parsable[tail] == ' ' || parsable[tail] == '\t';tail++);//no reason to have spaces at head of the redirect file if (head != tail){//redirect was not the previous character file = (char *)malloc(head - tail + 1); if (strncpy(file,parsable + tail,head-tail) == NULL){return 1;} file[head-tail] = '\0'; } } else if(command == NULL){ if(tail != head){//the first word is terminated with a pipe rather than a space command = (char *)malloc(head - tail + 1); if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;} command[head-tail] = '\0'; } //this "branch" denotes that the pipe is the first character } else {// input with params and no redirect or a few other things int back = head; for(;parsable[back] == ' ' || parsable[back] == '\t' || parsable[back] == '|';back--){} back++; if(tail < back){ params = (char *)malloc(back - tail + 1); if (strncpy(params,parsable + tail,back-tail) == NULL){return 1;} params[back-tail] = '\0'; } } pipeline = 1; head++; tail = head;//Now both head and tail should be set ahead of the pipe break; } } if(tail != head){ if(parsable[tail] == '<' || parsable[tail] == '>' || parsable[tail] == '|'){tail++;} for(;tail < strlen(parsable) && (parsable[tail] == ' ' || parsable[tail] == '\t');tail++); } if(tail != head && pipeline == 0){ if(pipev == PIPE_IN || pipev == PIPE_OUT){ file = (char *)malloc(head - tail + 1); if (strncpy(file,parsable + tail,head-tail) == NULL){return 1;} file[head-tail] = '\0'; tail = head; } else if(command == NULL){ command = (char *)malloc(head - tail + 1); if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;} command[head-tail] = '\0'; tail = head; } else { int num = head-tail; params = (char *)malloc(sizeof(char)*(head - tail + 1)); if (strncpy(params,parsable + tail,num) == NULL){return 1;} params[head-tail] = '\0'; tail = head; } } if(DEBUG == 1){ if(command != NULL){ printf("Command is: %s\n", command); } if(params != NULL){ printf("Params are: %s\n", params); } if(file != NULL){ printf("File is: %s\n", file); } printf("pipev: %d\n",pipev); printf("pipeline: %d\n",pipeline); } int oldredir; int pipefile; if(pipev == PIPE_IN){ oldredir = dup(STDIN_FILENO); if(file != NULL){ pipefile = open(file,O_RDONLY);//add file check dup2(pipefile,STDIN_FILENO); close(pipefile); } } else if(pipev == PIPE_OUT){ oldredir = dup(STDOUT_FILENO); fflush(stdout); if(file != NULL){ pipefile = open(file,O_WRONLY|O_CREAT,0777); dup2(pipefile,STDOUT_FILENO); close(pipefile); } else { dup2(STDIN_FILENO,STDOUT_FILENO); } } if(pipeline == 1){ int oldredir2; int tubing[2]; pid_t pid; if (pipe(tubing) < 0) {return 1;} if ((pid = fork()) < 0) {return 1;} else if (pid == 0){ close(tubing[1]); oldredir2 = dup(STDIN_FILENO); dup2(tubing[0], STDIN_FILENO); ret = parse_exec(&parsable[head]); close(tubing[0]); dup2(oldredir2, STDIN_FILENO); exit(ret); } else { fflush(stdout); close(tubing[0]); oldredir2 = dup(STDOUT_FILENO); dup2(tubing[1], STDOUT_FILENO); find_and_exec(command,params); fflush(stdout); close(tubing[1]); dup2(oldredir2, STDOUT_FILENO); wait(&ret); } } else{ ret = find_and_exec(command,params); } if(pipev == PIPE_IN){ dup2(oldredir,STDIN_FILENO); } else if(pipev == PIPE_OUT){ fflush(stdout); dup2(oldredir,STDOUT_FILENO); } return ret; }