int check_builtin(char *cmd) { /* Arguments: cmd = program to run Purpose: this function checks to see if the cmd specified is a built in command (in this case only "cd" is built-in) Returns: 0 -- if the cmd is built in -1 -- if the cmd is NOT built in */ if(!strcmp(cmd,"cd")) { //command was "cd" which is a builtin, so //lets handle it add_nav_history(fullPath); chdir(args[1]); //change directory to first argument get_path(); } else if(cmd[0] == '!') { //theyre requesting some sort of history exec_history(cmd); //execute the argument number } else if(cmd[0] == '@') { //requesting nav history exec_nav_history(cmd); get_path(); } else if(!strcmp(cmd,"history")) { print_history(); } else if(!strcmp(cmd, "navhist")) { print_nav_history(); } else if(!strcmp(cmd,"alias")) { //trying to set an alias if(args[1] == NULL) { //no argument, so just print all print_aliases(); } else { add_alias(args[1]); } } else if(!strcmp(cmd,"unalias")) { //trying to remove an alias (args[1] is what is being removed) remove_alias(args[1]); } else if(!strcmp(cmd,"cinterp")) { //want to use the C interpreter //quit raw mode first (will make the cinterp easier) quit_raw_mode(); cinterp(); tty_raw_mode(); //reenter raw mode } else { return -1; } return 0; }
int main(int argc, char ** argv) { tty_raw_mode(); while (1) { char ch; read(0, &ch, 1); printf("%d\n", ch); } }
void tty_init (gboolean mouse_enable, gboolean is_xterm) { initscr (); #ifdef HAVE_ESCDELAY /* * If ncurses exports the ESCDELAY variable, it should be set to * a low value, or you'll experience a delay in processing escape * sequences that are recognized by mc (e.g. Esc-Esc). On the other * hand, making ESCDELAY too small can result in some sequences * (e.g. cursor arrows) being reported as separate keys under heavy * processor load, and this can be a problem if mc hasn't learned * them in the "Learn Keys" dialog. The value is in milliseconds. */ ESCDELAY = 200; #endif /* HAVE_ESCDELAY */ #ifdef NCURSES_VERSION /* use Ctrl-g to generate SIGINT */ cur_term->Nttyb.c_cc[VINTR] = CTRL ('g'); /* ^g */ /* disable SIGQUIT to allow use Ctrl-\ key */ cur_term->Nttyb.c_cc[VQUIT] = NULL_VALUE; tcsetattr (cur_term->Filedes, TCSANOW, &cur_term->Nttyb); #else /* other curses implementation (bsd curses, ...) */ { struct termios mode; tcgetattr (STDIN_FILENO, &mode); /* use Ctrl-g to generate SIGINT */ mode.c_cc[VINTR] = CTRL ('g'); /* ^g */ /* disable SIGQUIT to allow use Ctrl-\ key */ mode.c_cc[VQUIT] = NULL_VALUE; tcsetattr (STDIN_FILENO, TCSANOW, &mode); } #endif /* NCURSES_VERSION */ tty_start_interrupt_key (); if (!mouse_enable) use_mouse_p = MOUSE_DISABLED; tty_init_xterm_support (is_xterm); /* do it before tty_enter_ca_mode() call */ tty_enter_ca_mode (); tty_raw_mode (); noecho (); keypad (stdscr, TRUE); nodelay (stdscr, FALSE); tty_setup_sigwinch (sigwinch_handler); }
static void edition_post_exec (void) { do_enter_ca_mode (); /* FIXME: Missing on slang endwin? */ tty_reset_prog_mode (); tty_flush_input (); tty_keypad (TRUE); tty_raw_mode (); channels_up (); enable_mouse (); enable_bracketed_paste (); if (mc_global.tty.alternate_plus_minus) application_keypad_mode (); }
/* * Input a line with some basic editing. */ char *read_line() { // Set terminal in raw mode tty_raw_mode(); // Initialize the parameters line_length = 0; cursor_position = 0; if (history == NULL) { // whiout the check, up-arrow will give seg fault history = (char **)malloc(HIST_MAX * sizeof(char *)); } // Read one line until enter is typed while (1) { // Read one character in raw mode. char ch; read(0, &ch, 1); // for all printable character. if (ch >= 32 && ch <= 126) { // Do echo write(1, &ch, 1); // If max number of character reached return. if (line_length == MAX_BUFFER_LINE - 2) break; // if in the middle of what typed if (cursor_position != line_length) { char temp; int i; line_length++; //shift the content to the right of cursor for (i = line_length; i > cursor_position; i--) { line_buffer[i] = line_buffer[i - 1]; } //let the content to be written in the buffer be stored line_buffer[cursor_position] = ch; //print the chars to the right of cursor for (i = cursor_position + 1; i < line_length; i++) { ch = line_buffer[i]; write(1, &ch, 1); } //put the cursor back to the right position. ch = 8; for (i = cursor_position + 1; i < line_length; i++) { write(1, &ch, 1); } } else { // at the end, just add char to buffer. line_buffer[line_length] = ch; line_length++; } cursor_position++; } else if (ch == 10) { // <Enter> was typed. Return line // Print newline write(1, &ch, 1); if (history_length == HIST_MAX) { HIST_MAX *= 2; history = (char **)realloc(history, HIST_MAX * sizeof(char *)); } line_buffer[line_length] = 0; if (line_buffer[0] != 0) { history[history_length] = strdup(line_buffer); history_length++; } break; } else if (ch == 1) { // CTRL-A : Move to beginning of line int i; for (i = cursor_position; i > 0; i--) { ch = 8; write(1, &ch, 1); cursor_position--; } } else if (ch == 31) { // ctrl-? read_line_print_usage(); line_buffer[0] = 0; break; } else if ((ch == 8 || ch == 127) && line_length != 0) { // <backspace> was typed. Remove previous character read. // Go back one character ch = 8; write(1, &ch, 1); // Write a space to erase the last character read ch = ' '; write(1, &ch, 1); // Go back one character ch = 8; write(1, &ch, 1); // Remove one character from buffer line_length--; cursor_position--; } else if (ch == 27) { // Escape sequence. Read two chars more // // HINT: Use the program "keyboard-example" to // see the ascii code for the different chars typed. // char ch1; char ch2; read(0, &ch1, 1); read(0, &ch2, 1); // left arrow if (ch1 == 91 && ch2 == 68) { if (cursor_position > 0) { ch = 8; write(1, &ch, 1); cursor_position--; } } // right arrow if (ch1 == 91 && ch2 == 67) { if (cursor_position < line_length) { // char ch = line_buffer[cursor_position]; // write(1, &ch, 1); write(1, &ch, 1); write(1, &ch1, 1); write(1, &ch2, 1); cursor_position++; } } // Up arrow. Print next line in history. if (ch1 == 91 && ch2 == 65 && history_length > 0) { // Erase old line // Print backspaces int i = 0; for (i = 0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } // Print spaces on top for (i = 0; i < line_length; i++) { ch = ' '; write(1, &ch, 1); } // Print backspaces for (i = 0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } // Copy line from history strcpy(line_buffer, history[history_index]); line_length = strlen(line_buffer); history_index = (history_index + 1) % history_length; // echo line write(1, line_buffer, line_length); cursor_position = line_length; } // down arrow, similar to UP if (ch1 == 91 && ch2 == 66) { // down arrow. Print next line in history. // Erase old line // Print backspaces int i = 0; for (i = line_length - cursor_position; i < line_length; i++) { ch = 8; write(1, &ch, 1); } // Print spaces on top for (i = 0; i < line_length; i++) { ch = ' '; write(1, &ch, 1); } // Print backspaces for (i = 0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } if (history_index > 0) { // Copy line from history strcpy(line_buffer, history[history_index]); line_length = strlen(line_buffer); history_index = (history_index - 1) % history_length; // echo line write(1, line_buffer, line_length); cursor_position = line_length; } else { // Copy line from history strcpy(line_buffer, ""); line_length = strlen(line_buffer); // echo line write(1, line_buffer, line_length); cursor_position = line_length; } } } } // Add eol and null char at the end of string line_buffer[line_length] = 10; line_length++; line_buffer[line_length] = 0; return line_buffer; }
/* * Input a line with some basic editing. */ char * read_line() { // save terminal settings struct termios orig_attr; tcgetattr(0, &orig_attr); // Set terminal in raw mode tty_raw_mode(); line_length = 0; line_pos = 0; // reset the line buffer int t = 0; for (t = 0; t < MAX_BUFFER_LINE; t++) { line_buffer[t] = '\0'; } // Read one line until enter is typed while (1) { // init history if necessary if (history == NULL) { init_hist(); } // Read one character in raw mode. char ch; read(0, &ch, 1); if (ch>=32 && ch < 127) { // It is a printable character. if (line_pos == line_length) { // we're at the end of the line // Do echo write(1,&ch,1); // If max number of character reached return. if (line_length==MAX_BUFFER_LINE-2) break; // add char to buffer. line_buffer[line_pos]=ch; line_length++; line_pos++; } else { // in the middle of the line somewhere char * temp = (char*)malloc(MAX_BUFFER_LINE * sizeof(char)); int i; // copy all the characters after where we're at for ( i = 0; i < MAX_BUFFER_LINE; i++) { if (line_buffer[line_pos + i] == '\0' ) { // if we see the null char, we've gotten it all break; } temp[i] = line_buffer[line_pos + i]; } // write the character we want to add write (1, &ch, 1); // If max number of character reached return. if (line_length==MAX_BUFFER_LINE-2) break; // add char to buffer. line_buffer[line_pos]=ch; line_length++; line_pos++; // print all the rest of the characters afterwards int chars_added = 0; for (i = 0; i < MAX_BUFFER_LINE; i++) { chars_added+=1; write(1, &temp[i], 1); if (line_buffer[line_pos + i] == '\0' ) { // if we see the null char, we've gotten it all break; } } // go back to where we were backspace(chars_added); } } else if (ch==10) { // <Enter> was typed. Return line // add line to history linked list if it's not empty if ( strlen(line_buffer) != 0 ) { add_hist_line(line_buffer); } // Print newline write(1,&ch,1); break; } else if (ch == 31) { // ctrl-? read_line_print_usage(); line_buffer[0]=0; break; } else if (ch == 127) { // <backspace> was typed. Remove previous character read. // don't do anything if we're already at the beginning if (line_pos <= 0) { continue; } // Go back one character backspace(1); // Write a space to erase the last character read ch = ' '; write(1,&ch,1); // Go back one character backspace(1); // Remove one character from buffer line_buffer[ line_pos ] = '\0'; line_length--; line_pos--; } else if (ch==27) { // Escape sequence. Read two chars more // // HINT: Use the program "keyboard-example" to // see the ascii code for the different chars typed. // char ch1; char ch2; read(0, &ch1, 1); read(0, &ch2, 1); if (ch1==91 && ch2==65) { // Up arrow. Print next line in history. // Erase old line // Print backspaces int i = 0; for (i =0; i < line_length; i++) { ch = 8; write(1,&ch,1); } // Print spaces on top for (i =0; i < line_length; i++) { ch = ' '; write(1,&ch,1); } // Print backspaces for (i =0; i < line_length; i++) { ch = 8; write(1,&ch,1); } // if history is uninitialized, do nothing // Copy line from history history_index -= 1; if (history_index <= 0) { // loop back to the most recent command history_index = history_length - 1; } if (history[history_index] == NULL) { const char * empty = ""; strcpy(line_buffer, empty); } else { strcpy(line_buffer, history[history_index]); } line_length = strlen(line_buffer); // echo line write(1, line_buffer, line_length); } else if (ch1 == 91 && ch2 == 66) { // down arrow. print previous line in history // Erase old line // Print backspaces backspace( line_length ); // Print spaces on top int i = 0; for (i =0; i < line_length; i++) { ch = ' '; write(1,&ch,1); } // Print backspaces backspace( line_length ); // increment index accordingly if (history_index <= 0) { // stay at 0 history_index = 0; } else { history_index += 1; if (history_index >= history_length ) { history_index = 0; } } // Copy line from history if (history[history_index] == NULL) { const char * empty = ""; strcpy(line_buffer, empty); } else { strcpy(line_buffer, history[history_index]); } line_length = strlen(line_buffer); // echo line write(1, line_buffer, line_length); } else if (ch1 == 91 && ch2 == 68) { // left arrow if (line_pos > 0) { line_pos--; backspace(1); } } else if (ch1 == 91 && ch2 == 67) { // right arrow if (line_pos < line_length) { // grab current char char c = line_buffer[line_pos]; // print grabbed char write( 1, &c, 1); line_pos++; } } } } // Add eol and null char at the end of string line_buffer[line_length]=10; line_length++; line_buffer[line_length]=0; // set the terminal back to orig settings tcsetattr(0, TCSANOW, &orig_attr); return line_buffer; }
/* * Input a line with some basic editing. */ char * read_line() { // Set terminal in raw mode tty_raw_mode(); line_length = 0; pos = 0; // Read one line until enter is typed while (1) { // Read one character in raw mode. char ch; read(0, &ch, 1); if (ch>=32) { // It is a printable character. // Do echo write(1,&ch,1); // If max number of character reached return. if (line_length==MAX_BUFFER_LINE-2) break; // add char to buffer. line_buffer[line_length]=ch; line_length++; } else if (ch==10) { // <Enter> was typed. Return line // Print newline write(1,&ch,1); break; } else if (ch == 31) { // ctrl-? read_line_print_usage(); line_buffer[0]=0; break; } else if (ch == 8) { // <backspace> was typed. Remove previous character read. // Go back one character ch = 8; write(1,&ch,1); // Write a space to erase the last character read ch = ' '; write(1,&ch,1); // Go back one character ch = 8; write(1,&ch,1); // Remove one character from buffer line_length--; } else if (ch==27) { // Escape sequence. Read two chars more // // HINT: Use the program "keyboard-example" to // see the ascii code for the different chars typed. // char ch1; char ch2; read(0, &ch1, 1); read(0, &ch2, 1); if (ch1==91 && ch2==65) { // Up arrow. Print next line in history. // Erase old line // Print backspaces int i = 0; for (i =0; i < line_length; i++) { ch = 8; write(1,&ch,1); } // Print spaces on top for (i =0; i < line_length; i++) { ch = ' '; write(1,&ch,1); } // Print backspaces for (i =0; i < line_length; i++) { ch = 8; write(1,&ch,1); } // Copy line from history strcpy(line_buffer, history[history_index]); line_length = strlen(line_buffer); history_index=(history_index+1)%history_length; // echo line write(1, line_buffer, line_length); } } } // Add eol and null char at the end of string line_buffer[line_length]=10; line_length++; line_buffer[line_length]=0; return line_buffer; }
void toggle_panels (void) { #ifdef ENABLE_SUBSHELL vfs_path_t *new_dir_vpath = NULL; #endif /* ENABLE_SUBSHELL */ SIG_ATOMIC_VOLATILE_T was_sigwinch = 0; channels_down (); disable_mouse (); disable_bracketed_paste (); if (clear_before_exec) clr_scr (); if (mc_global.tty.alternate_plus_minus) numeric_keypad_mode (); #ifndef HAVE_SLANG /* With slang we don't want any of this, since there * is no raw_mode supported */ tty_reset_shell_mode (); #endif /* !HAVE_SLANG */ tty_noecho (); tty_keypad (FALSE); tty_reset_screen (); do_exit_ca_mode (); tty_raw_mode (); if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_RESTORE); #ifdef ENABLE_SUBSHELL if (mc_global.tty.use_subshell) { vfs_path_t **new_dir_p; new_dir_p = vfs_current_is_local ()? &new_dir_vpath : NULL; invoke_subshell (NULL, VISIBLY, new_dir_p); } else #endif /* ENABLE_SUBSHELL */ { if (output_starts_shell) { fprintf (stderr, _("Type 'exit' to return to the Midnight Commander")); fprintf (stderr, "\n\r\n\r"); my_system (EXECUTE_INTERNAL, mc_global.tty.shell, NULL); } else get_key_code (0); } if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_SAVE); do_enter_ca_mode (); tty_reset_prog_mode (); tty_keypad (TRUE); /* Prevent screen flash when user did 'exit' or 'logout' within subshell */ if ((quit & SUBSHELL_EXIT) != 0) { /* User did 'exit' or 'logout': quit MC */ if (quiet_quit_cmd ()) return; quit = 0; #ifdef ENABLE_SUBSHELL /* restart subshell */ if (mc_global.tty.use_subshell) init_subshell (); #endif /* ENABLE_SUBSHELL */ } enable_mouse (); enable_bracketed_paste (); channels_up (); if (mc_global.tty.alternate_plus_minus) application_keypad_mode (); /* HACK: * Save sigwinch flag that will be reset in mc_refresh() called via update_panels(). * There is some problem with screen redraw in ncurses-based mc in this situation. */ was_sigwinch = mc_global.tty.winch_flag; mc_global.tty.winch_flag = 0; #ifdef ENABLE_SUBSHELL if (mc_global.tty.use_subshell) { do_load_prompt (); if (new_dir_vpath != NULL) do_possible_cd (new_dir_vpath); if (mc_global.tty.console_flag != '\0' && output_lines) show_console_contents (output_start_y, LINES - mc_global.keybar_visible - output_lines - 1, LINES - mc_global.keybar_visible - 1); } vfs_path_free (new_dir_vpath); #endif /* ENABLE_SUBSHELL */ if (mc_global.mc_run_mode == MC_RUN_FULL) { update_panels (UP_OPTIMIZE, UP_KEEPSEL); update_xterm_title_path (); } if (was_sigwinch != 0 || mc_global.tty.winch_flag != 0) dialog_change_screen_size (); else repaint_screen (); }
void do_executev (const char *shell, int flags, char *const argv[]) { #ifdef ENABLE_SUBSHELL vfs_path_t *new_dir_vpath = NULL; #endif /* ENABLE_SUBSHELL */ vfs_path_t *old_vfs_dir_vpath = NULL; if (!vfs_current_is_local ()) old_vfs_dir_vpath = vfs_path_clone (vfs_get_raw_current_dir ()); if (mc_global.mc_run_mode == MC_RUN_FULL) save_cwds_stat (); pre_exec (); if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_RESTORE); if (!mc_global.tty.use_subshell && *argv != NULL && (flags & EXECUTE_INTERNAL) == 0) { printf ("%s%s\n", mc_prompt, *argv); fflush (stdout); } #ifdef ENABLE_SUBSHELL if (mc_global.tty.use_subshell && (flags & EXECUTE_INTERNAL) == 0) { do_update_prompt (); /* We don't care if it died, higher level takes care of this */ invoke_subshell (*argv, VISIBLY, old_vfs_dir_vpath != NULL ? NULL : &new_dir_vpath); } else #endif /* ENABLE_SUBSHELL */ my_systemv_flags (flags, shell, argv); if ((flags & EXECUTE_INTERNAL) == 0) { if ((pause_after_run == pause_always || (pause_after_run == pause_on_dumb_terminals && !mc_global.tty.xterm_flag && mc_global.tty.console_flag == '\0')) && quit == 0 #ifdef ENABLE_SUBSHELL && subshell_state != RUNNING_COMMAND #endif /* ENABLE_SUBSHELL */ ) { printf (_("Press any key to continue...")); fflush (stdout); tty_raw_mode (); get_key_code (0); printf ("\r\n"); fflush (stdout); } if (mc_global.tty.console_flag != '\0' && output_lines != 0 && mc_global.keybar_visible) { putchar ('\n'); fflush (stdout); } } if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_SAVE); edition_post_exec (); #ifdef ENABLE_SUBSHELL if (new_dir_vpath != NULL) { do_possible_cd (new_dir_vpath); vfs_path_free (new_dir_vpath); } #endif /* ENABLE_SUBSHELL */ if (old_vfs_dir_vpath != NULL) { mc_chdir (old_vfs_dir_vpath); vfs_path_free (old_vfs_dir_vpath); } if (mc_global.mc_run_mode == MC_RUN_FULL) { update_panels (UP_OPTIMIZE, UP_KEEPSEL); update_xterm_title_path (); } do_refresh (); use_dash (TRUE); }
char * read_line() { int itr; if(debug_mode) for(itr = history_index; itr > 0; itr--) fprintf(stderr, "\nhistory[%d]=%s", itr, history[itr]); // Set terminal in raw mode tty_raw_mode(); line_length = 0; while (1) { // Read one character in raw mode. char ch; read(0, &ch, 1); if (ch>=32 && ch != ESC && ch < 127 ) { // It is a printable character. display it back write(1,&ch,1); // If max number of character reached return. if (line_length==MAX_BUFFER_LINE-2) break; // add char to buffer. line_buffer[line_length]=ch; line_length++; position++; } else if (ch==10) { // <Enter> was typed. Return line. add current line to history if(line_length > 0) { history[history_index] = strdup(line_buffer); if(history_index == 29) history_index = 0; else history_index++; if(debug_mode) for(itr = 0; itr < history_index; itr++) fprintf(stderr, "\nhistory[%d]=%s\n", itr, history[itr]); } write(1,&ch,1); break; } else if (ch == 31) { // ctrl-? read_line_print_usage(); line_buffer[0]=0; break; } else if (ch == BACKSPACE || ch==127) { if(line_length>0 && position> 0) { // <backspace> or ctrl-H was typed. Remove previous character read. // Go back one character if(position == line_length) { ch = BACKSPACE; write(1,&ch,1); // Write a space to erase the last character read ch = ' '; write(1,&ch,1); // Go back one character ch = BACKSPACE; write(1,&ch,1); // Remove one character from buffer line_length--; position--; } else delete_and_shift(1); } } else if(ch == 4) { /* ctrl-D: Removes the character at the cursor. The characters in the right side are shifted to the left. */ delete_and_shift(0); } else if(ch == 1) { /*Home key (or ctrl-A): The cursor moves to the beginning of the line */ if(position != 0 && position < line_length+1 && position > 0) { while(position != 0 ) { ch = BACKSPACE; write(1, &ch, 1); position--; } } } else if(ch == 12) { /* Clear line (or ctrl-l): clear current line */ clear_line(); } else if(ch==5) { /*End key (or ctrl-E): The cursor moves to the end of the line */ if( position < line_length && position >= 0) { while(position != line_length ) { ch = line_buffer[position]; write(1, &ch, 1); position++; } } } else if (ch==ESC) // Esc. Read two chars more { char ch1; char ch2; read(0, &ch1, 1); read(0, &ch2, 1); if (ch1==91 && ch2==65) // up { // Print previous line in history. // Erase old line clear_line(); // Copy line from history if(history_access > history_index) history_access = history_index-1; else if(history_access < 0) history_access = 0; if( history_access >= 0 && history[history_access] ) { memset(line_buffer,0,sizeof(line_buffer)); strcpy(line_buffer, history[history_access]); line_length = strlen(line_buffer); position= line_length-1; history_access--; if(debug_mode) fprintf(stderr, "history_index after <up>=%d\n", history_index); // echo line write(1, line_buffer, line_length); } } else if(ch1==91 && ch2==66) //down { // Shows the next command in the history list // Print next line in history. // Erase old line clear_line(); // Copy line from history if(history_access > history_index) history_access = history_index-1; else if(history_access < 0) history_access = 0; if(history_access >= 0 && history[history_access]) { memset(line_buffer,0,sizeof(line_buffer)); strcpy(line_buffer, history[history_access]); line_length = strlen(line_buffer); position= line_length-1; history_access++; if(debug_mode) fprintf(stderr, "history_index=%d\n", history_index); write(1, line_buffer, line_length); } } else if(ch1==91 && ch2==67) //right { /* Move the cursor to the right and allow insertion at that position. If the cursor is at the end of the line it does nothing. */ if(position >= 0 && position < line_length && line_length > 0 ) { ch= line_buffer[position]; write(1, &ch, 1); position++; } } else if(ch1==91 && ch2==68) //left { /* Move the cursor to the left and allow insertion at that position. If the cursor is at the beginning of the line it does nothing. */ if(position > 0 && position <= line_length && line_length > 0) { ch=BACKSPACE; write(1, &ch, 1); position--; } } else if(ch1==91 && ch2==52) // <end> { //read char because end is ESC+91+52+126 read(0, &ch1, 1); /* end key */ if( position < line_length && position >= 0) { while(position != line_length ) { ch = line_buffer[position]; write(1, &ch, 1); position++; } } } else if(ch1==91 && ch2==51) // <del> { //read char because del is ESC+91+51+126 read(0, &ch1, 1); /* del key */ delete_and_shift(0); } else if(ch1==91 && ch2==49) // <HOME> { //read char because home is ESC+91+49+126 read(0, &ch1, 1); /* home key */ if(position > 0 && position <= line_length ) { while(position != 0 ) { ch = BACKSPACE; write(1, &ch, 1); position--; } } } } } // Add eol and null char at the end of string if(line_length < 0) return ""; line_buffer[line_length]=10; line_length++; line_buffer[line_length]=0; position = 0; return line_buffer; }
/* * Input a line with some basic editing. */ char * read_line() { struct termios orig_attr; tcgetattr(0, &orig_attr); // Set terminal in raw mode tty_raw_mode(); line_length = 0; line_pos = 0; // Read one line until enter is typed while (1) { // Read one character in raw mode. char ch; read(0, &ch, 1); if (ch >= 32 && ch != 127) { // It is a printable character. int i; for (i = line_length; i > line_pos; i--) { line_buffer[i] = line_buffer[i - 1]; } line_buffer[i] = ch; line_length++; if (line_length == MAX_BUFFER_LINE - 2) break; for (i = line_pos; i < line_length; i++) { ch = line_buffer[i]; write(1, &ch, 1); } ch = 8; for (i = line_length; i > line_pos + 1; i--) { write(1, &ch, 1); } line_pos++; } else if (ch == 10) { // <Enter> was typed. Return line // Print newline write(1,&ch,1); break; } else if (ch == 31) { // ctrl-? read_line_print_usage(); line_buffer[0]=0; break; } else if (ch == 8 || ch == 127) { // <backspace> was typed. Remove previous character read. if (line_length == 0 || line_pos == 0) { continue; } else { int i; for (i = line_pos - 1; i < line_length - 1; i++) { line_buffer[i] = line_buffer[i + 1]; } ch = 8; write(1, &ch, 1); for (i = line_pos; i < line_length; i++) { ch = line_buffer[i - 1]; write(1, &ch, 1); } ch = ' '; write(1, &ch, 1); ch = 8; write(1, &ch, 1); for (i = line_pos; i < line_length; i++) { write(1, &ch, 1); } line_pos--; line_length--; } } else if (ch == 27) { // Escape sequence. Read two chars more // // HINT: Use the program "keyboard-example" to // see the ascii code for the different chars typed. // char ch1; char ch2; read(0, &ch1, 1); read(0, &ch2, 1); if (ch1 == 91 && ch2 == 65) { // Up arrow. Print next line in history. if (history_count == 0 || history_index == 0) { continue; } // Erase old line // Print backspaces int i = 0; for (i =0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } // Print spaces on top for (i =0; i < line_length; i++) { ch = ' '; write(1, &ch, 1); } // Print backspaces for (i =0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } // Copy line from history if (history_index > 0) { history_index--; } strcpy(line_buffer, history[history_index]); line_length = strlen(line_buffer); // echo line write(1, line_buffer, line_length); line_pos = line_length; } else if (ch1 == 91 && ch2 == 66) { // Down arrow. Print previous line in history if (history_count == 0 || history_index == history_count) { line_pos = 0; line_length = 0; continue; } int i = 0; for (i = 0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } for (i = 0; i < line_length; i++) { ch = ' '; write(1, &ch, 1); } for (i = 0; i < line_length; i++) { ch = 8; write(1, &ch, 1); } history_index++; if (history_index == history_count) { line_pos = 0; line_length = 0; continue; } strcpy(line_buffer,history[history_index]); line_length = strlen(line_buffer); write(1, line_buffer, line_length); line_pos = line_length; } else if (ch1 == 91 && ch2 == 67) { // Right arrow. Move line position to the right if (line_pos < line_length) { ch = line_buffer[line_pos++]; write(1, &ch, 1); } } else if (ch1 == 91 && ch2 == 68) { // Left arrow. Move line position to the left if (line_pos > 0) { ch = 8; write(1, &ch, 1); line_pos--; } } else if (ch1 == 79 && ch2 == 72) { ch = 8; while (line_pos > 0) { write(1, &ch, 1); line_pos--; } } else if (ch1 == 79 && ch2 == 70) { while (line_pos < line_length + 1) { ch = line_buffer[line_pos - 1]; write(1, &ch, 1); line_pos++; } line_pos--; } } else if (ch == 1) { // Home button. Move line position to start ch = 8; while (line_pos > 0) { write(1, &ch, 1); line_pos--; } } else if (ch == 5) { // End button. Move line position to end while (line_pos < line_length + 1) { ch = line_buffer[line_pos - 1]; write(1, &ch, 1); line_pos++; } line_pos--; } else if (ch == 4) { // Delete. Move characters following current position to the left one if (line_length == 0 || line_pos == line_length) { continue; } else { int i; for (i = line_pos; i < line_length - 1; i++) { line_buffer[i] = line_buffer[i + 1]; } line_length--; for (i = line_pos; i < line_length; i++) { ch = line_buffer[i]; write(1, &ch, 1); } ch = ' '; write(1, &ch, 1); ch = 8; write(1, &ch, 1); for (i = line_pos; i < line_length; i++) { write(1, &ch, 1); } } } else if (ch == 9) { // Tab. Path completion // TODO: extra credit if (tablistset == 0) { char * regex = (char *)malloc(sizeof(char) * (line_length + 5)); regex[0] = '^'; int i; for (i = line_length - 1; i >= 0; i--) { if (line_buffer[i] == ' ') { spaceindex = i; break; } } if (spaceindex != 0) { int copysize = (line_buffer + line_length) - (line_buffer + spaceindex) - 1; strncpy(regex + 1, line_buffer + spaceindex + 1, copysize); regex[copysize + 1] = '.'; regex[copysize + 2] = '*'; regex[copysize + 3] = '$'; regex[copysize + 4] = '\0'; } else { strncpy(regex + 1, line_buffer, line_length); regex[line_length] = '.'; regex[line_length + 1] = '*'; regex[line_length + 2] = '$'; regex[line_length + 3] = '\0'; } regex_t re; int regexbuf = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB); if (regexbuf != 0) { perror("regcomp"); return; } char * d = (char *)malloc(sizeof(char) * 2); d[0] = '.'; d[1] = '\0'; DIR * dir = opendir(d); if (dir == NULL) { perror("opendir"); return; } free(d); struct dirent * ent; regmatch_t match; int maxEntries = 10; tablistsize = 0; tablist = (char **)malloc(maxEntries * sizeof(char *)); while ((ent = readdir(dir)) != NULL) { if (regexec(&re, ent->d_name, 1, &match, 0) == 0) { if (tablistsize == maxEntries) { maxEntries *= 2; tablist = (char **)realloc(tablist, maxEntries * sizeof(char *)); } tablist[tablistsize++] = strdup(ent->d_name); } } tablistset = 1; } int i; ch = 8; for (i = 0; i < line_length; i++) { write(1, &ch, 1); } ch = ' '; for (i = 0; i < line_length; i++) { write(1, &ch, 1); } ch = 8; for (i = 0; i < line_length; i++) { write(1, &ch, 1); } if (spaceindex == 0) { strcpy(line_buffer, tablist[tablistindex]); line_length = strlen(line_buffer); } else { char * tmptab = tablist[tablistindex]; for (i = 0; i < strlen(tmptab); i++) { line_buffer[spaceindex + i + 1] = tmptab[i]; } line_length = spaceindex + strlen(tablist[tablistindex]) + 1; } write(1, line_buffer, line_length); line_pos = line_length; if (tablistindex < tablistsize - 1) { tablistindex++; } } } if (strlen(line_buffer) > 1) { char * tmpbuf = (char *)malloc(sizeof(char) * (line_length + 2)); strncpy(tmpbuf, line_buffer, line_length); tmpbuf[line_length] = 0; history[history_count++] = strdup(tmpbuf); free(tmpbuf); } history_index = history_count; // Add eol and null char at the end of string line_buffer[line_length] = 10; line_length++; line_buffer[line_length] = 0; if (tablistset) { spaceindex = 0; tablistset = 0; tablistindex = 0; free(tablist); } tcsetattr(0, TCSANOW, &orig_attr); return line_buffer; }
int main(int argc, char *argv[], char *envp[]) { read_config(); //read the config file char c; //reading one letter at time here //building a command line which will eventually get parsed line = (char *)malloc(sizeof(char) * 100); memset(line,0,100); char *cmd = (char *)malloc(sizeof(char) * 100); //the program (command w/o args) char *printBuff = (char *)malloc(sizeof(char)*100); //a printing buffer (for use with raw tty) //holder for history if stuff is typed, then history is used to go back to typed stuff char *historyHold = (char *)malloc(sizeof(char)*100); path = (char*)malloc(sizeof(char)*100); fullPath = (char*)malloc(sizeof(char)*100); memset(printBuff,0,100); memset(historyHold,0,100); memset(cmd,0,100); signal(SIGINT, handle_sig); //register interrupt signal (for CTRL+C) int promptLen; //making sure we dont backspace the prompt int fromHistory = 0; //a type of check to see if our line is from history (not user typed) if(fork() == 0) { execve("/usr/bin/clear", argv, envp); //simply clear the screen exit(1); } else { wait(NULL); //wait to clear screen } get_path(); //gets the 2dir path for prompt tty_raw_mode();//set terminal into raw mode sprintf(printBuff,"%s:%s",path,PROMPT); //build print buff promptLen = strlen(printBuff); curPos = promptLen; //leave a space write(1,printBuff,promptLen); //print initial prompt memset(printBuff,0,100); //clear printBuff clear_args(); //just get any initial crap out /* MAIN LOOP */ while(1) { read(0,&c,1); //read 1 character from stdin if(((c >= 32) && c!=127) || c == 10) { //here, we only want to process characters that are //"readable" (or enter). special characters will be //handled differently tabPressNo = 0; //they didnt press tab write(1,&c,1); //write char (echo is off for raw mode) ++curPos; switch(c) { case '\n': //end of the line (enter was pressed after input) if(line[0] == '\0') { //they didnt type anything sprintf(printBuff,"%s:%s",path,PROMPT); write(1,printBuff,promptLen); } else if(strcmp(line,"exit")==0) { printf("\n"); //for niceness quit_raw_mode(); //play nice and restore term state return 0; //quit if they type "exit" } else { //prepare to actually process strncat(line,"\0",1); if(line[0] != '!') { add_history(line); //add command to history } int pipe = 0; int separ = check_separ(line); if(!separ){ pipe = check_pipe(line); } if(!separ && !pipe){ //try to execute the command if there werent pipes or semicolons parse_args(line); //build array of arguments strcpy(cmd, args[0]); //cmd = program to run execute(cmd); clear_args(); //resets all arg array strings } c = '\0'; memset(cmd, 0, 100); //clear the cmd array //reprint prompt sprintf(printBuff,"%s:%s",path,PROMPT); promptLen = strlen(printBuff); curPos = promptLen; write(1,printBuff,promptLen); } memset(line,0,100); //clear line array memset(historyHold,0,100);//clear history hold break; default: strncat(line, &c, 1);//build the line break; } } else if(c == 8) { //backspace pressed if(curPos > promptLen) { backspace(); //backspace until we reach prompt line[strlen(line)-1] = 0; //thank god this finally works --curPos; } } else if(c == 27) { //the user pressed some sort of //escape sequence char c1; char c2; read(0,&c1,1); read(0,&c2,1); //ok, we have the two parts of the //escape sequence in c1 and c2 if(c1 == 91 && c2 == 65) { //this is the escape for the up arrow //which we want to use for history //browsing char *tmpLine; tmpLine = prev_history(); if(tmpLine != 0) { if(line[0] != '\0' && fromHistory==0) { //store what user currently has typed (if anything) memset(historyHold,0,100); strncpy(historyHold,line,strlen(line)); } clear_line(strlen(line)); //clears whatever is at the prompt memset(line,0,100); strncpy(line,tmpLine,strlen(tmpLine)); //copy this command free(tmpLine); //play nice write(1,line,strlen(line)); //write old command fromHistory = 1; //current line has been replaced by history curPos = strlen(line) + promptLen; //so we know where are } } else if(c1 == 91 && c2 == 66) { //this is the escape for the down arrow //which should make us go "forward" //in history (if we are back in it) char *tmpLine; tmpLine = next_history(); //get the next history if(tmpLine != 0) { //next_history gave us a line clear_line(strlen(line)); //clear old line from screen memset(line,0,100); //clear old line in mem strncpy(line,tmpLine,strlen(tmpLine)); //copy new line to old line write(1,line,strlen(line)); //write new line to screen curPos = strlen(line) + promptLen; //update pos free(tmpLine); } else if(historyHold[0] != '\0') { //if we dont have a next_line, lets see if //we had some buffer before browsing history clear_line(strlen(line)); memset(line,0,100); strncpy(line,historyHold,strlen(historyHold)); write(1,line,strlen(line)); curPos = strlen(line) +promptLen; fromHistory = 0; //back to user typed } else { //it was blank before history was browsed clear_line(strlen(line)); memset(line,0,100); curPos = promptLen; } } } else if(c == '\t') { //tab press. should i dare try to do tab //completion? i guess... //if this is the 2nd time in a row pressing tab //they want a listing of everything that can be //completed if(tabPressNo) { //print everything in tabHold tabPressNo = 0; if(tabCompHold[0] != NULL) { int i = 1; char *x = tabCompHold[0]; char *tmp = (char*)malloc(sizeof(char)*100); memset(tmp,0,100); write(1,"\n",1); while(x != NULL) { sprintf(tmp,"%s\t",x); write(1,tmp,strlen(tmp)); memset(tmp,0,100); x = tabCompHold[i]; ++i; } write(1,"\n",1); //reprint prompt sprintf(printBuff,"%s:%s",path,PROMPT); promptLen = strlen(printBuff); curPos = promptLen + strlen(line); write(1,printBuff,promptLen); //write the line again write(1,line,strlen(line)); clear_tab_hold(); } } else { //otherwise just let tab_complete //print a single completion char *tabcomp; tabcomp = tab_complete(line); if(tabcomp != NULL) { //tab comp found a single thing, so //lets just complete it int i = 1; char c = tabcomp[0]; while(c!='\0') { write(1,&c,1); strncat(line,&c,1); c = tabcomp[i]; ++i; } curPos += strlen(tabcomp); //set our new position free(tabcomp); } ++tabPressNo; } } else if(c == '\177') { //other form of backspace if(curPos > promptLen) { backspace(); //backspace until we reach prompt line[strlen(line)-1] = 0; //thank god this finally works --curPos; } } memset(printBuff,0,100); //clear printing buffer } printf("\n"); //for niceness quit_raw_mode(); //so we dont get stuck in it return 0; //goodbye }