Ejemplo n.º 1
0
void start_client() {
  status = S_INIT;
  while (true) {
    switch(status) {
      case S_INIT:
        handle_init(); 
        break;
      case S_EXIT:
        handle_exit();
        return;
      case S_LOGIN:
        handle_login();
        break;
      case S_REGISTER:
        handle_register();
        break;
      case S_VERIFIED:
        handle_verified();
        break;
      case S_ORDER:
        handle_order();
        break;
      case S_QUERY_ORDER:
        handle_query_orders();
        break;
      case S_QUERY:
        handle_query();
      default:
        break;
    }
  }
}
Ejemplo n.º 2
0
/* 
 * Runs commands in sequential mode.
 */
char sequential_mode(char **pointers_to_commands, Node *head) {
    char mode = 's';
    pid_t cpid, w;
    char **command;
    char return_char = 's';
    int i = 0;
    while (pointers_to_commands[i] != NULL) {
        command = tokenify(pointers_to_commands[i], " \n\t");
        if (command[0] == NULL) {
            i++;
            free_tokens(command);
            continue;
        } 
        if (handle_exit(command) != 'n') {
            free_tokens(command);
            return 'e';
        }
        if (return_char != 'e' && is_mode(command)) {
            return_char = handle_mode(command, mode, return_char);
            i++;
            free_tokens(command);
            continue;
        }
        handle_parallel_builtins(command, NULL, NULL, mode);
        cpid = fork();
        if (cpid == 0) {
            char *tempcommand;
            tempcommand = prepend_path(command, head);
            command[0] = tempcommand;   
            if (execv(command[0], command) < 0) {
                fprintf(stderr, "execv failed: %s\n", strerror(errno));
                printf("That's not a valid command! \n");
                free_tokens(command);
                exit(EXIT_FAILURE);
            }
            free(tempcommand);
            }
        else {
            int status = 0;
            w = wait(&status);
            i++;
        }
        free_tokens(command);

    }
    return return_char;
}
Ejemplo n.º 3
0
void LeaderNode::handle_requests() {
#ifdef DEBUG
   printf("LeaderNode entering handle_requests!\n");
#endif
   while (true) {
      while (msg_ready() == false) {
         message_select();
      }

      while (msg_ready() == true) {
         msg_info = msg_queue.front();
         msg_queue.pop_front();
#ifdef DEBUG
         printf("msg_queue.size: %u\n", msg_queue.size());
#endif

         switch (msg_info.tag) {
            case SPAWN_JOB:
               handle_spawn_job();
               break;

            case SPAWN_CACHE:
               handle_spawn_cache();
               break;

            case EXIT:
               handle_exit();
               break;

            case EXIT_ACK:
               handle_exit_ack();
               break;

            default:
               printf("===== DEFAULT =====\n");
               printf("LeaderNode %d\n", local_rank);
               print_msg_info(&msg_info);
               MPI_ASSERT(FAILURE);
               break;
         }
      }
   }
}
int main(int ac, char **av)
{
    char *mode;
    int res;

    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);

    signal(SIGINT, sig_handler);

    conf_parse(av[1]);
    conf_read(NULL);

    mode = getenv("MENUCONFIG_MODE");
    if (mode) {
        if (!strcasecmp(mode, "single_menu"))
            single_menu_mode = 1;
    }

    initscr();

    getyx(stdscr, saved_y, saved_x);
    if (init_dialog(NULL)) {
        fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
        fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
        return 1;
    }

    set_config_filename(conf_get_configname());
    do {
        conf(&rootmenu);
        res = handle_exit();
    } while (res == KEY_ESC);

    return res;
}
static DBusHandlerResult message_func(DBusConnection *connection,
					DBusMessage *message, void *user_data)
{
	struct generic_data *data = user_data;
	LOG("message_func");
	LOG("got dbus message sent to %s %s %s",
		dbus_message_get_destination(message),
		dbus_message_get_interface(message),
		dbus_message_get_path(message));

	struct interface_data *iface;
	const GDBusMethodTable *method;
	const char *interface;

	interface = dbus_message_get_interface(message);

	iface = find_interface(data->interfaces, interface);
	if (iface == NULL)
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

	for (method = iface->methods; method &&
			method->name && method->function; method++) {
		if (dbus_message_is_method_call(message, iface->name,
							method->name) == FALSE)
			continue;

		if (g_dbus_args_have_signature(method->in_args,
							message) == FALSE)
			continue;

		return process_message(connection, message, method,
							iface->user_data);
	}
	handle_exit(NULL);
	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
Ejemplo n.º 6
0
/*
 * System call handler
 *
 * retrieves system call number from user space
 * and invokes the requested method
 */
static void
syscall_handler (struct intr_frame *f)
{

        /* retrieve system call number
        and switch to corresponding method */
        unsigned int syscall_number = *((unsigned int*) syscall_get_kernel_address(f->esp));

        switch(syscall_number)
        {
                /* process system calls */
                case SYS_HALT:
                        handle_halt(f);
                        break;

                case SYS_EXIT:
                        handle_exit(f);
                        break;

                case SYS_EXEC:
                        handle_exec(f);
                        break;

                case SYS_WAIT:
                        handle_wait(f);
                        break;

                /* file system calls */
                case SYS_CREATE:
                        handle_create(f);
                        break;
 
                case SYS_REMOVE:
                        handle_remove(f);
                        break;

                case SYS_OPEN:
                        handle_open(f);
                        break;

                case SYS_FILESIZE:
                        handle_filesize(f);
                        break;

                case SYS_READ:
                        handle_read(f);
                        break;

                case SYS_WRITE:
                        handle_write(f);
                        break;

                case SYS_SEEK:
                        handle_seek(f);
                        break;

                case SYS_TELL:
                        handle_tell(f);
                        break;

                case SYS_CLOSE:
                        handle_close(f);
                        break;

                case SYS_CHDIR:
                        handle_chdir(f);
                        break;

                case SYS_MKDIR:
                        handle_mkdir(f);
                        break;

                case SYS_READDIR:
                        handle_readdir(f);
                        break;

                case SYS_ISDIR:
                        handle_isdir(f);
                        break;

                case SYS_INUMBER:
                        handle_inumber(f);
                        break;

                default: /* SYSCALL_ERROR: */
                        handle_no_such_syscall(f);
                        break;
        }
}
Ejemplo n.º 7
0
void
handle_event(Event *event) {
	if (exiting == 1) {
		exiting = 2;
		debug(1, "ltrace about to exit");
		ltrace_exiting();
	}
	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
	      event->proc ? event->proc->pid : -1, event->type);

	/* If the thread group or an individual task define an
	   overriding event handler, give them a chance to kick in.
	   We will end up calling both handlers, if the first one
	   doesn't sink the event.  */
	if (event->proc != NULL) {
		event = call_handler(event->proc, event);
		if (event == NULL)
			/* It was handled.  */
			return;

		/* Note: the previous handler has a chance to alter
		 * the event.  */
		if (event->proc != NULL
		    && event->proc->leader != NULL
		    && event->proc != event->proc->leader) {
			event = call_handler(event->proc->leader, event);
			if (event == NULL)
				return;
		}
	}

	switch (event->type) {
	case EVENT_NONE:
		debug(1, "event: none");
		return;
	case EVENT_SIGNAL:
		debug(1, "event: signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_signal(event);
		return;
	case EVENT_EXIT:
		debug(1, "event: exit (%d)", event->e_un.ret_val);
		handle_exit(event);
		return;
	case EVENT_EXIT_SIGNAL:
		debug(1, "event: exit signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_exit_signal(event);
		return;
	case EVENT_SYSCALL:
		debug(1, "event: syscall (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_syscall(event);
		return;
	case EVENT_SYSRET:
		debug(1, "event: sysret (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_sysret(event);
		return;
	case EVENT_ARCH_SYSCALL:
		debug(1, "event: arch_syscall (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_syscall(event);
		return;
	case EVENT_ARCH_SYSRET:
		debug(1, "event: arch_sysret (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_sysret(event);
		return;
	case EVENT_CLONE:
	case EVENT_VFORK:
		debug(1, "event: clone (%u)", event->e_un.newpid);
		handle_clone(event);
		return;
	case EVENT_EXEC:
		debug(1, "event: exec()");
		handle_exec(event);
		return;
	case EVENT_BREAKPOINT:
		debug(1, "event: breakpoint");
		handle_breakpoint(event);
		return;
	case EVENT_NEW:
		debug(1, "event: new process");
		handle_new(event);
		return;
	default:
		fprintf(stderr, "Error! unknown event?\n");
		exit(1);
	}
}
Ejemplo n.º 8
0
int handle_event(struct task *task)
{
	int ret;

	if (!task)
		return 0;

	debug(DEBUG_EVENT, "+++ process pid=%d event: %d", task->pid, task->event.type);

	assert(task->stopped);

	if (task->defer_func) {
		ret = task->defer_func(task, task->defer_data);

		if (ret == RET_DELETED)
			return 1;

		task->defer_func = NULL;
		task->defer_data = NULL;
		goto out2;
	}

	struct event *event = &task->event;
	enum event_type type = event->type;

	switch (type) {
	case EVENT_NONE:
		ret = continue_task(task, task->event.e_un.signum);
		break;
	case EVENT_SIGNAL:
		ret = handle_signal(task);
		break;
	case EVENT_ABOUT_EXIT:
		ret = handle_about_exit(task);
		goto out1;
	case EVENT_EXIT:
		ret = handle_exit(task);
		break;
	case EVENT_EXIT_SIGNAL:
		ret = handle_exit_signal(task);
		break;
	case EVENT_FORK:
	case EVENT_VFORK:
	case EVENT_CLONE:
		ret = handle_child(task);
		break;
	case EVENT_EXEC:
		ret = handle_exec(task);
		break;
	case EVENT_BREAKPOINT:
		ret = handle_breakpoint(task);
		goto out2;
	case EVENT_NEW:
		ret = handle_new(task);
		break;
	default:
		fprintf(stderr, "fatal error, unknown event %d\n", type);
		abort();
	}

	if (ret == RET_DELETED)
		return 1;

	if (ret != RET_DEFERED) {
		assert(task->event.type == EVENT_NONE);
		assert(task->stopped == 0);
	}
out2:
	assert(task->is_new == 0);
out1:
	return (ret < 0) ? ret : 0;
}
static void sig_handler(int signo)
{
    exit(handle_exit());
}
Ejemplo n.º 10
0
Wallpaper::~Wallpaper()
{
    handle_exit();
}
Ejemplo n.º 11
0
/* 
 * Runs commands in parallel mode, with support for background processes.  
 */
char parallel_mode(char **pointers_to_commands, Node *head, Node **paused_list, Node **cpidlist) {

    int count = 0; // counts the no. of times we've been in the loop; 
                    // if more than 1, we need to free
                    // pointers_to_commands, which is different from what we got from main.
    while (1) {
        count++;
        char mode = 'p';
        pid_t cpid;
        char **command;
        char return_char = 'p';
        int i = 0;

        while (pointers_to_commands[i] != NULL) {
            command = tokenify(pointers_to_commands[i], " \n\t");
            if (command[0] == NULL) {
                i++;
                free_tokens(command);
                continue;
            }
            if (handle_exit(command) != 'n') {
                if (*cpidlist == NULL && pointers_to_commands[i+1] == NULL) {
                    return_char = 'e';
                }
                else {
                    printf("There are processes still running. You cannot exit yet. \n");
                }
                free_tokens(command);
                i++;
                continue;
            }
            if (is_mode(command)) {
                return_char = handle_mode(command, mode, return_char);
                if (return_char == 's') {
                    if (*cpidlist != NULL || pointers_to_commands[i+1] != NULL) {
                        printf("There are processes running. You cannot switch modes yet.\n");
                        return_char = 'p';
                    }
                }
                free_tokens(command);
                i++;
                continue;
            }
            if (handle_parallel_builtins(command, paused_list, cpidlist, mode) == 1) {
                i++;
                free_tokens(command);
                continue;
            }
            cpid = fork();
            if (cpid == 0) {
                char *tempcommand;
                tempcommand = prepend_path(command, head);
                command[0]= tempcommand;
                if (execv(command[0], command) < 0) {
                    fprintf(stderr, "execv failed: %s\n", strerror(errno));
                    printf("That's not a valid command! \n");
                    free_tokens(command);
                    exit(EXIT_FAILURE);
                }        
            }
            else {
                char whole_command[128];
                memset(whole_command, '\0', 128);
                strcat(whole_command, command[0]);
                if (command[1] != NULL) {
                    strcat(whole_command, " ");
                    strcat(whole_command, command[1]);
                }
                char cpidstr[128];
                sprintf(cpidstr, "%d", cpid);
                list_append(cpidstr, whole_command, cpidlist);
            }
            i++;
            free_tokens(command);
        }  
        if (count > 1) {
            free_tokens(pointers_to_commands);
        }
        if (return_char != 'p') {
            return return_char;
        }
        
        struct pollfd pfd[1];
        pfd[0].fd = 0;
        pfd[0].events = POLLIN;
        pfd[0].revents = 0;

        display_prompt();     
        int some_process_completed = 0;
        while (1) {
            int status;
            int rv = poll(&pfd[0], 1, 800);
            Node *to_delete_list = NULL;
            Node *tempcpidlist = *cpidlist;
            pid_t w;
            if (rv == 0) {
                some_process_completed = 0;
                while (tempcpidlist != NULL) {
                    w = atoi(tempcpidlist->data);
                    // I know that the ideal way to check for child process death is to use a macro such as WIFEXITED on status, 
                    // but it wasn't working for me.
                    // status always had the value 0. So I'm doing this instead to check for process completion.
                    if (waitpid(w, &status, WUNTRACED|WNOHANG) == -1) { 
                        list_append(tempcpidlist->data, "", &to_delete_list);
                        printf("\nProcess %s (%s) completed.\n", tempcpidlist->data, tempcpidlist->additional_data); 
                        some_process_completed = 1;
                    }
                    tempcpidlist = tempcpidlist->next;                 
                }
                Node *curr = to_delete_list;
                while (curr != NULL) {
                    list_delete(curr->data, cpidlist);
                    curr = curr->next;
                }
                list_clear(to_delete_list);
                if (some_process_completed == 1) {
                    display_prompt();

                }
            }
            else if (rv > 0) {
                char buffer[1024];
                if (fgets(buffer, 1024, stdin) == NULL) {
                    if (*cpidlist != NULL) {
                        printf("There are processes still running. You can't exit now.\n");
                        display_prompt();
                    }
                    else {
                        return_char = 'e';
                        return return_char;
                    }
                }
                else {
                    char *newbuffer = replace_pound(buffer);
                    newbuffer[strlen(newbuffer)-1] = '\0'; 
                    pointers_to_commands = tokenify(newbuffer, ";");
                    free(newbuffer);
                    break;
                }
            }
            else {
                printf("there was some kind of error: %s \n", strerror(errno));
            }
        }
    }
}
Ejemplo n.º 12
0
static void
do_input(FILE *ifp)
{
    int c;
    char escape;

    /*
     *  Processing user input.
     *  Basically we stuff the user input to a temp. file until
     *  an escape char. is detected, after which we switch
     *  to the appropriate routine to handle the escape.
     */

    if (ifp == stdin) {
	if (Verbose)
	    fprintf(stdout,"\nGo \n* ");
	else {
	    if (!Silent)
		fprintf(stdout, "* ");
	}
    }
    while ((c = getc(ifp)) != EOF ) {
	if ( c == '\\') {
	    /* handle escapes */
	    escape = getc(ifp);
	    switch( escape ) {
	      case 'e':
		handle_editor();
		break;
	      case 'g':
		handle_send();
		break;
	      case 'i':
		{
		    bool oldVerbose;

		    if (SingleStepMode) {
			oldVerbose = Verbose;
			Verbose = false;
		    }
		    handle_file_insert(ifp);
		    if (SingleStepMode)
			Verbose = oldVerbose;
		}
		break;
	      case 'p':
		handle_print();
		break;
	      case 'q':
		handle_exit(0);
		break;
	      case 'r':
		handle_clear();
		break;
	      case 's':
		handle_shell();
		break;
	      case 't':
		handle_print_time();
		break;
	      case 'w':
		handle_write_to_file();
		break;
	      case '?':
	      case 'h':
		handle_help();
		break;
	      case '\\':
		c = escape;
		stuff_buffer(c); 
		break;
	      case ';':
		c = escape;
		stuff_buffer(c);
		break;
	      default:
		fprintf(stderr, "unknown escape given\n");
		break;
	    } /* end-of-switch */
	    if (ifp == stdin && escape != '\\') {
		if (Verbose)
		    fprintf(stdout,"\nGo \n* ");
		else {
		    if (!Silent)
			fprintf(stdout, "* ");
		}
	    }
	} else {
	    stuff_buffer(c);
	    if (c == ';' && SemicolonIsGo) {
		handle_send();
		if (Verbose)
		    fprintf(stdout,"\nGo \n* ");
		else {
		    if (!Silent)
			fprintf(stdout, "* ");
		}
	    }
	}
    }
}
Ejemplo n.º 13
0
void
main(int argc, char **argv)
{
    int c;
    int errflag = 0;
    char *progname;
    char *debug_file;
    char *dbname;
    char *command;
    int exit_status = 0;
    char errbuf[ERROR_MSG_LENGTH];
    char *username, usernamebuf[NAMEDATALEN + 1];

    char *pghost = NULL;
    char *pgtty = NULL;
    char *pgoptions = NULL;
    char *pgport = NULL;
    int  pgtracep = 0;

    /* 
     * Processing command line arguments.
     *
     * h : sets the hostname.
     * p : sets the coom. port
     * t : sets the tty.
     * o : sets the other options. (see doc/libpq)
     * d : enable debugging mode.
     * q : run in quiet mode
     * Q : run in VERY quiet mode (no output except on errors)
     * c : monitor will run one POSTQUEL command and exit
     *
     * s : step mode (pauses after each command)
     * S : don't use semi colon as \g
     *
     * T : terse mode - no formatting
     * N : no attribute names - only columns of data
     *     (these two options are useful in conjunction with the "-c" option
     *      in scripts.)
     */

    progname = *argv;
    Debugging = false;
    Verbose = true;
    Silent = false;

    /* prepend PGOPTION, if any */
    argsetup(&argc, &argv);

    while ((c = getopt(argc, argv, "a:h:f:p:t:d:qsSTNQc:")) != EOF) {
	switch (c) {
	    case 'a':
	      fe_setauthsvc(optarg, errbuf);
	      break;
	    case 'h' :
	      pghost = optarg;
	      break;
	    case 'f' :
	      RunOneFile = optarg;
	      break;
	    case 'p' :
	      pgport = optarg;
	      break;
	    case 't' :
	      pgtty = optarg;
	      break;
	    case 'T' :
	      TerseOutput = true;
	      break;
	    case 'N' :
	      PrintAttNames = false;
	      break;
	    case 'd' :

	      /*
	       *  When debugging is turned on, the debugging messages
	       *  will be sent to the specified debug file, which
	       *  can be a tty ..
	       */

	      Debugging = true;
	      debug_file = optarg;
	      debug_port = fopen(debug_file,"w+");
	      if (debug_port == NULL) {
		  fprintf(stderr,"Unable to open debug file %s \n", debug_file);
		  exit(1);
	      }
	      pgtracep = 1;
	      break;
	    case 'q' :
	      Verbose = false;
	      break;
	    case 's' :
	      SingleStepMode = true;
	      SemicolonIsGo = true;
	      break;
	    case 'S' :
	      SemicolonIsGo = false;
	      break;
	    case 'Q' :
	      Verbose = false;
	      Silent = true;
	      break;
	    case 'c' :
	      Verbose = false;
	      Silent = true;
	      RunOneCommand = true;
	      command = optarg;
	      break;
	    case '?' :
	    default :
	      errflag++;
	      break;
	}
    }

    if (errflag ) {
      fprintf(stderr, "usage: %s [options...] [dbname]\n", progname);
      fprintf(stderr, "\t-a authsvc\tset authentication service\n");
      fprintf(stderr, "\t-c command\t\texecute one command\n");
      fprintf(stderr, "\t-d debugfile\t\tdebugging output file\n");
      fprintf(stderr, "\t-h host\t\t\tserver host name\n");
      fprintf(stderr, "\t-f file\t\t\trun query from file\n");
      fprintf(stderr, "\t-p port\t\t\tserver port number\n");
      fprintf(stderr, "\t-q\t\t\tquiet output\n");
      fprintf(stderr, "\t-t logfile\t\terror-logging tty\n");
      fprintf(stderr, "\t-N\t\t\toutput without attribute names\n");
      fprintf(stderr, "\t-Q\t\t\tREALLY quiet output\n");
      fprintf(stderr, "\t-T\t\t\tterse output\n");
      exit(2);
    }

    /* Determine our username (according to the authentication system, if
     * there is one).
     */
    if ((username = fe_getauthname(errbuf)) == (char *) NULL) {
	    fprintf(stderr, "%s: could not find a valid user name\n",
		    progname);
	    exit(2);
    }
    memset(usernamebuf, 0, sizeof(usernamebuf));
    (void) strncpy(usernamebuf, username, NAMEDATALEN);
    username = usernamebuf;
    
    /* find database */
    if (!(dbname = argv[optind]) &&
	!(dbname = getenv("DATABASE")) &&
	!(dbname = username)) {
	    fprintf(stderr, "%s: no database name specified\n", progname);
	    exit (2);
    }

    conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbname);
    if (PQstatus(conn) == CONNECTION_BAD) {
      fprintf(stderr,"Connection to database '%s' failed.\n", dbname);
      fprintf(stderr,"%s",PQerrorMessage(conn));
      exit(1);
    }

    if (pgtracep)
      PQtrace(conn,debug_port);

    /* print out welcome message and start up */
    welcome();
    init_tmon(); 

    /* parse input */
    if (RunOneCommand) {
	exit_status = handle_execution(command);
    } else if (RunOneFile) {
	bool oldVerbose;
	FILE *ifp;

	if ((ifp = fopen(RunOneFile, "r")) == NULL) {
	    fprintf(stderr, "Cannot open %s\n", RunOneFile);
	}
	
	if (SingleStepMode) {
	    oldVerbose = Verbose;
	    Verbose = false;
	}
	do_input(ifp);
	fclose(ifp);
	if (SingleStepMode)
	    Verbose = oldVerbose;
    } else {
	do_input(stdin);
    }

    handle_exit(exit_status);
}
Ejemplo n.º 14
0
int main(int argc, char *argv[]) {

    /* The shell process itself ignores SIGINT. */
    struct sigaction action;
    action.sa_handler = SIG_IGN;
    action.sa_flags = 0;
    sigemptyset(&action.sa_mask);
    if (sigaction(SIGINT, &action, NULL) == -1) {
        perror("sigaction");
        return EXIT_FAILURE;
    }

    while (1) {
        // Read the next command.
        command_t *command = read_command();

        // Check for finished background processes.
        int status;
        pid_t pid;
        while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
            printf("Background process %d finished\n", pid);
        }

        if (!command)
            continue; // Ignore empty commands.

        if (match(command->argv[0], "exit")) {
            // Handle built-in exit command.
            if (handle_exit(command)) {
                free_command(command);
                break;
            }
        } else if (match(command->argv[0], "cd")) {
            // Handle built-in cd command.
            handle_cd(command);
        } else {
            // Fork a child process.
            pid = fork();
            if (pid == -1) {
                perror("fork");
            } else if (pid == 0) {
                // Execute command.
                execvp(command->argv[0], command->argv);
                perror(command->argv[0]);
                exit(EXIT_FAILURE);
            } else {
                if (command->type == FOREGROUND) {
                    printf("Spawned foreground process pid: %d\n", pid);

                    struct timeval t0, t1;

                    // Wait for foreground process.
                    gettimeofday(&t0, NULL);
                    waitpid(pid, &status, 0);
                    gettimeofday(&t1, NULL);

                    printf("Foreground process %d terminated\n", pid);
                    printf("wallclock time: %.3f msec\n", elapsed_ms(&t0, &t1));
                } else {
                    printf("Spawned background process pid: %d\n", pid);
                }
            }
        }

        free_command(command);
    }

    clear_history(); // Clear GNU readline history.

    return EXIT_SUCCESS;
}