Пример #1
0
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;
}
Пример #2
0
int main(int argc, char ** argv) 
{
  tty_raw_mode();

  while (1) {
    char ch;
    read(0, &ch, 1);
    printf("%d\n", ch);
  }
}
Пример #3
0
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);
}
Пример #4
0
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 ();
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
/* 
 * 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;
}
Пример #7
0
/* 
 * 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;
}
Пример #8
0
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 ();
}
Пример #9
0
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);
}
Пример #10
0
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;
}
Пример #11
0
/* 
 * 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;
}
Пример #12
0
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
}