Exemple #1
0
int less_main(int argc, char **argv)
{
    int keypress;

    INIT_G();

    /* TODO: -x: do not interpret backspace, -xx: tab also */
    /* -xxx: newline also */
    /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
    getopt32(argv, "EMmN~");
    argc -= optind;
    argv += optind;
    num_files = argc;
    files = argv;

    /* Another popular pager, most, detects when stdout
     * is not a tty and turns into cat. This makes sense. */
    if (!isatty(STDOUT_FILENO))
        return bb_cat(argv);
    kbd_fd = open(CURRENT_TTY, O_RDONLY);
    if (kbd_fd < 0)
        return bb_cat(argv);
    ndelay_on(kbd_fd);

    if (!num_files) {
        if (isatty(STDIN_FILENO)) {
            /* Just "less"? No args and no redirection? */
            bb_error_msg("missing filename");
            bb_show_usage();
        }
    } else
        filename = xstrdup(files[0]);

    get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
    /* 20: two tabstops + 4 */
    if (width < 20 || max_displayed_line < 3)
        return bb_cat(argv);
    max_displayed_line -= 2;

    buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
    if (option_mask32 & FLAG_TILDE)
        empty_line_marker = "";

    tcgetattr(kbd_fd, &term_orig);
    term_less = term_orig;
    term_less.c_lflag &= ~(ICANON | ECHO);
    term_less.c_iflag &= ~(IXON | ICRNL);
    /*term_less.c_oflag &= ~ONLCR;*/
    term_less.c_cc[VMIN] = 1;
    term_less.c_cc[VTIME] = 0;

    /* We want to restore term_orig on exit */
    bb_signals(BB_FATAL_SIGS, sig_catcher);

    reinitialize();
    while (1) {
        keypress = less_getch(-1); /* -1: do not position cursor */
        keypress_process(keypress);
    }
}
Exemple #2
0
static void win_changed(int nsig)
{
	int width;
	get_terminal_width_height(0, &width, NULL);
	cmdedit_setwidth(width, nsig /* - just a yes/no flag */);
	if (nsig == SIGWINCH)
		signal(SIGWINCH, win_changed); /* rearm ourself */
}
Exemple #3
0
int watch_main(int argc, char **argv)
{
	unsigned opt;
	unsigned period = 2;
	unsigned cmdlen;
	char *header = NULL;
	char *cmd;
	char *tmp;
	char **p;

	opt_complementary = "-1"; // at least one param please
	opt = getopt32(argv, "+dtn:", &tmp);
	//if (opt & 0x1) // -d (ignore)
	//if (opt & 0x2) // -t
	if (opt & 0x4) period = xatou(tmp);
	argv += optind;

	p = argv;
	cmdlen = 1; // 1 for terminal NUL
	while (*p)
		cmdlen += strlen(*p++) + 1;
	tmp = cmd = xmalloc(cmdlen);
	while (*argv) {
		tmp += sprintf(tmp, " %s", *argv);
		argv++;
	}
	cmd++; // skip initial space

	while (1) {
		printf("\033[H\033[J");
		if (!(opt & 0x2)) { // no -t
			int width, len;
			char *thyme;
			time_t t;

			get_terminal_width_height(STDIN_FILENO, &width, 0);
			header = xrealloc(header, width--);
			// '%-*s' pads header with spaces to the full width
			snprintf(header, width, "Every %ds: %-*s", period, width, cmd);
			time(&t);
			thyme = ctime(&t);
			len = strlen(thyme);
			if (len < width)
				strcpy(header + width - len, thyme);
			puts(header);
		}
		fflush(stdout);
		// TODO: 'real' watch pipes cmd's output to itself
		// and does not allow it to overflow the screen
		// (taking into account linewrap!)
		system(cmd);
		sleep(period);
	}
	return 0; // gcc thinks we can reach this :)
}
Exemple #4
0
static void display_window_size(int fancy)
{
	const char *fmt_str = "%s\0%s: no size information for this device";
	unsigned width, height;

	if (get_terminal_width_height(STDIN_FILENO, &width, &height)) {
		if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
			perror_on_device(fmt_str);
		}
	} else {
		wrapf(fancy ? "rows %u; columns %u;" : "%u %u\n",
				height, width);
	}
}
int watch_main(int argc ATTRIBUTE_UNUSED, char **argv)
{
    unsigned opt;
    unsigned period = 2;
    unsigned width, new_width;
    char *header;
    char *cmd;

    opt_complementary = "-1:n+"; // at least one param; -n NUM
    // "+": stop at first non-option (procps 3.x only)
    opt = getopt32(argv, "+dtn:", &period);
    argv += optind;

    // watch from both procps 2.x and 3.x does concatenation. Example:
    // watch ls -l "a /tmp" "2>&1" -- ls won't see "a /tmp" as one param
    cmd = *argv;
    while (*++argv)
        cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd

    width = (unsigned)-1; // make sure first time new_width != width
    header = NULL;
    while (1) {
        printf("\033[H\033[J");
        if (!(opt & 0x2)) { // no -t
            const unsigned time_len = sizeof("1234-67-90 23:56:89");
            time_t t;

            get_terminal_width_height(STDIN_FILENO, &new_width, NULL);
            if (new_width != width) {
                width = new_width;
                free(header);
                header = xasprintf("Every %us: %-*s", period, (int)width, cmd);
            }
            time(&t);
            if (time_len < width)
                strftime(header + width - time_len, time_len,
                         "%Y-%m-%d %H:%M:%S", localtime(&t));

            puts(header);
        }
        fflush(stdout);
        // TODO: 'real' watch pipes cmd's output to itself
        // and does not allow it to overflow the screen
        // (taking into account linewrap!)
        system(cmd);
        sleep(period);
    }
    return 0; // gcc thinks we can reach this :)
}
Exemple #6
0
static void win_changed(int nsig)
{
	static sighandler_t previous_SIGWINCH_handler;  /* for reset */

	/* emulate || signal call */
	if (nsig == -SIGWINCH || nsig == SIGWINCH) {
		int width = 0;
		get_terminal_width_height(0, &width, NULL);
		cmdedit_setwidth(width, nsig == SIGWINCH);
	}
	/* Unix not all standard in recall signal */

	if (nsig == -SIGWINCH)          /* save previous handler   */
		previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
	else if (nsig == SIGWINCH)      /* signaled called handler */
		signal(SIGWINCH, win_changed);  /* set for next call       */
	else                                            /* nsig == 0 */
		/* set previous handler    */
		signal(SIGWINCH, previous_SIGWINCH_handler);    /* reset    */
}
Exemple #7
0
int less_main(int argc, char **argv) {

	int keypress;

	flags = bb_getopt_ulflags(argc, argv, "EMmN~");

	argc -= optind;
	argv += optind;
	files = argv;
	num_files = argc;

	if (!num_files) {
		if (ttyname(STDIN_FILENO) == NULL)
			inp_stdin = 1;
		else {
			bb_error_msg("Missing filename");
			bb_show_usage();
		}
	}

	strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]);
	get_terminal_width_height(0, &width, &height);
	data_readlines();
	tcgetattr(fileno(inp), &term_orig);
	term_vi = term_orig;
	term_vi.c_lflag &= (~ICANON & ~ECHO);
	term_vi.c_iflag &= (~IXON & ~ICRNL);
	term_vi.c_oflag &= (~ONLCR);
	term_vi.c_cc[VMIN] = 1;
	term_vi.c_cc[VTIME] = 0;
	buffer_init();
	buffer_print();

	while (1) {
		keypress = tless_getch();
		keypress_process(keypress);
	}
}
extern int telnet_main(int argc, char** argv)
{
	int len;
	struct sockaddr_in s_in;
#ifdef USE_POLL
	struct pollfd ufds[2];
#else
	fd_set readfds;
	int maxfd;
#endif

#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
	int opt;
#endif

#ifdef CONFIG_FEATURE_AUTOWIDTH
	get_terminal_width_height(0, &win_width, &win_height);
#endif

#ifdef CONFIG_FEATURE_TELNET_TTYPE
    ttype = getenv("TERM");
#endif

	memset(&G, 0, sizeof G);

	if (tcgetattr(0, &G.termios_def) < 0)
		exit(1);

	G.termios_raw = G.termios_def;
	cfmakeraw(&G.termios_raw);

	if (argc < 2)
		bb_show_usage();

#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
	autologin = NULL;
	while ((opt = getopt(argc, argv, "al:")) != EOF) {
		switch (opt) {
			case 'l':
				autologin = optarg;
				break;
			case 'a':
				autologin = getenv("USER");
				break;
			case '?':
				bb_show_usage();
				break;
		}
	}
	if (optind < argc) {
		bb_lookup_host(&s_in, argv[optind++]);
		s_in.sin_port = bb_lookup_port((optind < argc) ? argv[optind++] :
				"telnet", "tcp", 23);
		if (optind < argc)
			bb_show_usage();
	} else
		bb_show_usage();
#else
	bb_lookup_host(&s_in, argv[1]);
	s_in.sin_port = bb_lookup_port((argc == 3) ? argv[2] : "telnet", "tcp", 23);
#endif

	G.netfd = xconnect(&s_in);

	setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);

	signal(SIGINT, fgotsig);

#ifdef USE_POLL
	ufds[0].fd = 0; ufds[1].fd = G.netfd;
	ufds[0].events = ufds[1].events = POLLIN;
#else
	FD_ZERO(&readfds);
	FD_SET(0, &readfds);
	FD_SET(G.netfd, &readfds);
	maxfd = G.netfd + 1;
#endif

	while (1)
	{
#ifndef USE_POLL
		fd_set rfds = readfds;

		switch (select(maxfd, &rfds, NULL, NULL, NULL))
#else
		switch (poll(ufds, 2, -1))
#endif
		{
		case 0:
			/* timeout */
		case -1:
			/* error, ignore and/or log something, bay go to loop */
			if (G.gotsig)
				conescape();
			else
				sleep(1);
			break;
		default:

#ifdef USE_POLL
			if (ufds[0].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(0, &rfds))
#endif
			{
				len = read(0, G.buf, DATABUFSIZE);

				if (len <= 0)
					doexit(0);

				TRACE(0, ("Read con: %d\n", len));

				handlenetoutput(len);
			}

#ifdef USE_POLL
			if (ufds[1].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(G.netfd, &rfds))
#endif
			{
				len = read(G.netfd, G.buf, DATABUFSIZE);

				if (len <= 0)
				{
					WriteCS(1, "Connection closed by foreign host.\r\n");
					doexit(1);
				}
				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));

				handlenetinput(len);
			}
		}
	}
}
Exemple #9
0
int more_main(int argc UNUSED_PARAM, char **argv)
{
	int c = c; /* for compiler */
	int lines;
	int input = 0;
	int spaces = 0;
	int please_display_more_prompt;
	struct stat st;
	FILE *file;
	FILE *cin;
	int len;
	unsigned terminal_width;
	unsigned terminal_height;

	INIT_G();

	argv++;
	/* Another popular pager, most, detects when stdout
	 * is not a tty and turns into cat. This makes sense. */
	if (!isatty(STDOUT_FILENO))
		return bb_cat(argv);
	cin = fopen_for_read(CURRENT_TTY);
	if (!cin)
		return bb_cat(argv);

	if (ENABLE_FEATURE_USE_TERMIOS) {
		cin_fileno = fileno(cin);
		getTermSettings(cin_fileno, &initial_settings);
		new_settings = initial_settings;
		new_settings.c_lflag &= ~(ICANON | ECHO);
		new_settings.c_cc[VMIN] = 1;
		new_settings.c_cc[VTIME] = 0;
		setTermSettings(cin_fileno, &new_settings);
		bb_signals(0
			+ (1 << SIGINT)
			+ (1 << SIGQUIT)
			+ (1 << SIGTERM)
			, gotsig);
	}

	do {
		file = stdin;
		if (*argv) {
			file = fopen_or_warn(*argv, "r");
			if (!file)
				continue;
		}
		st.st_size = 0;
		fstat(fileno(file), &st);

		please_display_more_prompt = 0;
		/* never returns w, h <= 1 */
		get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
		terminal_height -= 1;

		len = 0;
		lines = 0;
		while (spaces || (c = getc(file)) != EOF) {
			int wrap;
			if (spaces)
				spaces--;
 loop_top:
			if (input != 'r' && please_display_more_prompt) {
				len = printf("--More-- ");
				if (st.st_size != 0) {
					uoff_t d = (uoff_t)st.st_size / 100;
					if (d == 0)
						d = 1;
					len += printf("(%u%% of %"OFF_FMT"u bytes)",
						(int) ((uoff_t)ftello(file) / d),
						st.st_size);
				}
				fflush_all();

				/*
				 * We've just displayed the "--More--" prompt, so now we need
				 * to get input from the user.
				 */
				for (;;) {
					input = getc(cin);
					input = tolower(input);
					if (!ENABLE_FEATURE_USE_TERMIOS)
						printf("\033[A"); /* cursor up */
					/* Erase the last message */
					printf("\r%*s\r", len, "");

					/* Due to various multibyte escape
					 * sequences, it's not ok to accept
					 * any input as a command to scroll
					 * the screen. We only allow known
					 * commands, else we show help msg. */
					if (input == ' ' || input == '\n' || input == 'q' || input == 'r')
						break;
					len = printf("(Enter:next line Space:next page Q:quit R:show the rest)");
				}
				len = 0;
				lines = 0;
				please_display_more_prompt = 0;

				if (input == 'q')
					goto end;

				/* The user may have resized the terminal.
				 * Re-read the dimensions. */
				if (ENABLE_FEATURE_USE_TERMIOS) {
					get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
					terminal_height -= 1;
				}
			}

			/* Crudely convert tabs into spaces, which are
			 * a bajillion times easier to deal with. */
			if (c == '\t') {
				spaces = ((unsigned)~len) % CONVERTED_TAB_SIZE;
				c = ' ';
			}

			/*
			 * There are two input streams to worry about here:
			 *
			 * c    : the character we are reading from the file being "mored"
			 * input: a character received from the keyboard
			 *
			 * If we hit a newline in the _file_ stream, we want to test and
			 * see if any characters have been hit in the _input_ stream. This
			 * allows the user to quit while in the middle of a file.
			 */
			wrap = (++len > terminal_width);
			if (c == '\n' || wrap) {
				/* Then outputting this character
				 * will move us to a new line. */
				if (++lines >= terminal_height || input == '\n')
					please_display_more_prompt = 1;
				len = 0;
			}
			if (c != '\n' && wrap) {
				/* Then outputting this will also put a character on
				 * the beginning of that new line. Thus we first want to
				 * display the prompt (if any), so we skip the putchar()
				 * and go back to the top of the loop, without reading
				 * a new character. */
				putchar('\n');
				goto loop_top;
			}
			/* My small mind cannot fathom backspaces and UTF-8 */
			putchar(c);
			die_if_ferror_stdout(); /* if tty was destroyed (closed xterm, etc) */
		}
		fclose(file);
		fflush_all();
	} while (*argv && *++argv);
 end:
	setTermSettings(cin_fileno, &initial_settings);
	return 0;
}
Exemple #10
0
int stty_main(int argc, char **argv)
{
	struct termios mode;
	void (*output_func)(const struct termios *, const int);
	const char *file_name = NULL;
	int display_all = 0;
	int stty_state;
	int k;

	stty_state = STTY_noargs;
	output_func = do_display;

	/* First pass: only parse/verify command line params */
	k = 0;
	while (argv[++k]) {
		const struct mode_info *mp;
		const struct control_info *cp;
		const char *arg = argv[k];
		const char *argnext = argv[k+1];
		int param;

		if (arg[0] == '-') {
			int i;
			mp = find_mode(arg+1);
			if (mp) {
				if (!(mp->flags & REV))
					goto invalid_argument;
				stty_state &= ~STTY_noargs;
				continue;
			}
			/* It is an option - parse it */
			i = 0;
			while (arg[++i]) {
				switch (arg[i]) {
				case 'a':
					stty_state |= STTY_verbose_output;
					output_func = do_display;
					display_all = 1;
					break;
				case 'g':
					stty_state |= STTY_recoverable_output;
					output_func = display_recoverable;
					break;
				case 'F':
					if (file_name)
						bb_error_msg_and_die("only one device may be specified");
					file_name = &arg[i+1]; /* "-Fdevice" ? */
					if (!file_name[0]) { /* nope, "-F device" */
						int p = k+1; /* argv[p] is argnext */
						file_name = argnext;
						if (!file_name)
							bb_error_msg_and_die(bb_msg_requires_arg, "-F");
						/* remove -F param from arg[vc] */
						--argc;
						while (argv[p]) { argv[p] = argv[p+1]; ++p; }
					}
					goto end_option;
				default:
					goto invalid_argument;
				}
			}
end_option:
			continue;
		}

		mp = find_mode(arg);
		if (mp) {
			stty_state &= ~STTY_noargs;
			continue;
		}

		cp = find_control(arg);
		if (cp) {
			if (!argnext)
				bb_error_msg_and_die(bb_msg_requires_arg, arg);
			/* called for the side effect of xfunc death only */
			set_control_char_or_die(cp, argnext, &mode);
			stty_state &= ~STTY_noargs;
			++k;
			continue;
		}

		param = find_param(arg);
		if (param & param_need_arg) {
			if (!argnext)
				bb_error_msg_and_die(bb_msg_requires_arg, arg);
			++k;
		}

		switch (param) {
#ifdef HAVE_C_LINE
		case param_line:
# ifndef TIOCGWINSZ
			xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes);
			break;
# endif /* else fall-through */
#endif
#ifdef TIOCGWINSZ
		case param_rows:
		case param_cols:
			xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes);
			break;
		case param_size:
#endif
		case param_speed:
			break;
		case param_ispeed:
			/* called for the side effect of xfunc death only */
			set_speed_or_die(input_speed, argnext, &mode);
			break;
		case param_ospeed:
			/* called for the side effect of xfunc death only */
			set_speed_or_die(output_speed, argnext, &mode);
			break;
		default:
			if (recover_mode(arg, &mode) == 1) break;
			if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break;
invalid_argument:
			bb_error_msg_and_die("invalid argument '%s'", arg);
		}
		stty_state &= ~STTY_noargs;
	}

	/* Specifying both -a and -g is an error */
	if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) ==
		(STTY_verbose_output | STTY_recoverable_output))
		bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive");
	/* Specifying -a or -g with non-options is an error */
	if (!(stty_state & STTY_noargs) &&
		(stty_state & (STTY_verbose_output | STTY_recoverable_output)))
		bb_error_msg_and_die("modes may not be set when specifying an output style");

	/* Now it is safe to start doing things */
	if (file_name) {
		int fd, fdflags;
		device_name = file_name;
		fd = xopen(device_name, O_RDONLY | O_NONBLOCK);
		if (fd != STDIN_FILENO) {
			dup2(fd, STDIN_FILENO);
			close(fd);
		}
		fdflags = fcntl(STDIN_FILENO, F_GETFL);
		if (fdflags < 0 ||
			fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
			perror_on_device_and_die("%s: cannot reset non-blocking mode");
	}

	/* Initialize to all zeroes so there is no risk memcmp will report a
	   spurious difference in an uninitialized portion of the structure */
	memset(&mode, 0, sizeof(mode));
	if (tcgetattr(STDIN_FILENO, &mode))
		perror_on_device_and_die("%s");

	if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) {
		get_terminal_width_height(STDOUT_FILENO, &max_col, NULL);
		output_func(&mode, display_all);
		return EXIT_SUCCESS;
	}

	/* Second pass: perform actions */
	k = 0;
	while (argv[++k]) {
		const struct mode_info *mp;
		const struct control_info *cp;
		const char *arg = argv[k];
		const char *argnext = argv[k+1];
		int param;

		if (arg[0] == '-') {
			mp = find_mode(arg+1);
			if (mp) {
				set_mode(mp, 1 /* reversed */, &mode);
				stty_state |= STTY_require_set_attr;
			}
			/* It is an option - already parsed. Skip it */
			continue;
		}

		mp = find_mode(arg);
		if (mp) {
			set_mode(mp, 0 /* non-reversed */, &mode);
			stty_state |= STTY_require_set_attr;
			continue;
		}

		cp = find_control(arg);
		if (cp) {
			++k;
			set_control_char_or_die(cp, argnext, &mode);
			stty_state |= STTY_require_set_attr;
			continue;
		}

		param = find_param(arg);
		if (param & param_need_arg) {
			++k;
		}

		switch (param) {
#ifdef HAVE_C_LINE
		case param_line:
			mode.c_line = xatoul_sfx(argnext, stty_suffixes);
			stty_state |= STTY_require_set_attr;
			break;
#endif
#ifdef TIOCGWINSZ
		case param_cols:
			set_window_size(-1, xatoul_sfx(argnext, stty_suffixes));
			break;
		case param_size:
			display_window_size(0);
			break;
		case param_rows:
			set_window_size(xatoul_sfx(argnext, stty_suffixes), -1);
			break;
#endif
		case param_speed:
			display_speed(&mode, 0);
			break;
		case param_ispeed:
			set_speed_or_die(input_speed, argnext, &mode);
			stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
			break;
		case param_ospeed:
			set_speed_or_die(output_speed, argnext, &mode);
			stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
			break;
		default:
			if (recover_mode(arg, &mode) == 1)
				stty_state |= STTY_require_set_attr;
			else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{
				set_speed_or_die(both_speeds, arg, &mode);
				stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
			} /* else - impossible (caught in the first pass):
				bb_error_msg_and_die("invalid argument '%s'", arg); */
		}
	}

	if (stty_state & STTY_require_set_attr) {
		struct termios new_mode;

		if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode))
			perror_on_device_and_die("%s");

		/* POSIX (according to Zlotnick's book) tcsetattr returns zero if
		   it performs *any* of the requested operations.  This means it
		   can report 'success' when it has actually failed to perform
		   some proper subset of the requested operations.  To detect
		   this partial failure, get the current terminal attributes and
		   compare them to the requested ones */

		/* Initialize to all zeroes so there is no risk memcmp will report a
		   spurious difference in an uninitialized portion of the structure */
		memset(&new_mode, 0, sizeof(new_mode));
		if (tcgetattr(STDIN_FILENO, &new_mode))
			perror_on_device_and_die("%s");

		if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
#ifdef CIBAUD
			/* SunOS 4.1.3 (at least) has the problem that after this sequence,
			   tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
			   sometimes (m1 != m2).  The only difference is in the four bits
			   of the c_cflag field corresponding to the baud rate.  To save
			   Sun users a little confusion, don't report an error if this
			   happens.  But suppress the error only if we haven't tried to
			   set the baud rate explicitly -- otherwise we'd never give an
			   error for a true failure to set the baud rate */

			new_mode.c_cflag &= (~CIBAUD);
			if ((stty_state & STTY_speed_was_set)
			 || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
#endif
				perror_on_device_and_die("%s: cannot perform all requested operations");
		}
	}

	return EXIT_SUCCESS;
}
int telnet_main(int argc, char **argv)
{
	char *host;
	int port;
	int len;
#ifdef USE_POLL
	struct pollfd ufds[2];
#else
	fd_set readfds;
	int maxfd;
#endif

	INIT_G();

#if ENABLE_FEATURE_AUTOWIDTH
	get_terminal_width_height(0, &G.win_width, &G.win_height);
#endif

#if ENABLE_FEATURE_TELNET_TTYPE
	G.ttype = getenv("TERM");
#endif

	if (tcgetattr(0, &G.termios_def) >= 0) {
		G.do_termios = 1;
		G.termios_raw = G.termios_def;
		cfmakeraw(&G.termios_raw);
	}

	if (argc < 2)
		bb_show_usage();

#if ENABLE_FEATURE_TELNET_AUTOLOGIN
	if (1 & getopt32(argv, "al:", &G.autologin))
		G.autologin = getenv("USER");
	argv += optind;
#else
	argv++;
#endif
	if (!*argv)
		bb_show_usage();
	host = *argv++;
	port = bb_lookup_port(*argv ? *argv++ : "telnet", "tcp", 23);
	if (*argv) /* extra params?? */
		bb_show_usage();

	G.netfd = create_and_connect_stream_or_die(host, port);

	setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));

	signal(SIGINT, fgotsig);

#ifdef USE_POLL
	ufds[0].fd = 0; ufds[1].fd = G.netfd;
	ufds[0].events = ufds[1].events = POLLIN;
#else
	FD_ZERO(&readfds);
	FD_SET(STDIN_FILENO, &readfds);
	FD_SET(G.netfd, &readfds);
	maxfd = G.netfd + 1;
#endif

	while (1) {
#ifndef USE_POLL
		fd_set rfds = readfds;

		switch (select(maxfd, &rfds, NULL, NULL, NULL))
#else
		switch (poll(ufds, 2, -1))
#endif
		{
		case 0:
			/* timeout */
		case -1:
			/* error, ignore and/or log something, bay go to loop */
			if (G.gotsig)
				conescape();
			else
				sleep(1);
			break;
		default:

#ifdef USE_POLL
			if (ufds[0].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(STDIN_FILENO, &rfds))
#endif
			{
				len = read(STDIN_FILENO, G.buf, DATABUFSIZE);
				if (len <= 0)
					doexit(EXIT_SUCCESS);
				TRACE(0, ("Read con: %d\n", len));
				handlenetoutput(len);
			}

#ifdef USE_POLL
			if (ufds[1].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(G.netfd, &rfds))
#endif
			{
				len = read(G.netfd, G.buf, DATABUFSIZE);
				if (len <= 0) {
					write_str(1, "Connection closed by foreign host\r\n");
					doexit(EXIT_FAILURE);
				}
				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
				handlenetinput(len);
			}
		}
	}
}
Exemple #12
0
int more_main(int argc, char **argv)
{
    int c, lines, input = 0;
    int please_display_more_prompt = 0;
    struct stat st;
    FILE *file;
    FILE *cin;
    int len, page_height;
    int terminal_width;
    int terminal_height;

    INIT_G();

    argv++;
    /* Another popular pager, most, detects when stdout
     * is not a tty and turns into cat. This makes sense. */
    if (!isatty(STDOUT_FILENO))
        return bb_cat(argv);
    cin = fopen(CURRENT_TTY, "r");
    if (!cin)
        return bb_cat(argv);

#if ENABLE_FEATURE_USE_TERMIOS
    cin_fileno = fileno(cin);
    getTermSettings(cin_fileno, &initial_settings);
    new_settings = initial_settings;
    new_settings.c_lflag &= ~ICANON;
    new_settings.c_lflag &= ~ECHO;
    new_settings.c_cc[VMIN] = 1;
    new_settings.c_cc[VTIME] = 0;
    setTermSettings(cin_fileno, &new_settings);
    signal(SIGINT, gotsig);
    signal(SIGQUIT, gotsig);
    signal(SIGTERM, gotsig);
#endif
    please_display_more_prompt = 2;

    do {
        file = stdin;
        if (*argv) {
            file = fopen_or_warn(*argv, "r");
            if (!file)
                continue;
        }
        st.st_size = 0;
        fstat(fileno(file), &st);

        please_display_more_prompt &= ~1;
        /* never returns w, h <= 1 */
        get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
        terminal_width -= 1;
        terminal_height -= 1;

        len = 0;
        lines = 0;
        page_height = terminal_height;
        while ((c = getc(file)) != EOF) {
            if ((please_display_more_prompt & 3) == 3) {
                len = printf("--More-- ");
                if (/*file != stdin &&*/ st.st_size > 0) {
                    len += printf("(%d%% of %"OFF_FMT"d bytes)",
                                  (int) (ftello(file)*100 / st.st_size),
                                  st.st_size);
                }
                fflush(stdout);

                /*
                 * We've just displayed the "--More--" prompt, so now we need
                 * to get input from the user.
                 */
                input = getc(cin);
#if !ENABLE_FEATURE_USE_TERMIOS
                printf("\033[A"); /* up cursor */
#endif
                /* Erase the "More" message */
                printf("\r%*s\r", len, "");
                len = 0;
                lines = 0;
                /* Bottom line on page will become top line
                 * after one page forward. Thus -1: */
                page_height = terminal_height - 1;
                please_display_more_prompt &= ~1;

                if (input == 'q')
                    goto end;
            }

            /*
             * There are two input streams to worry about here:
             *
             * c    : the character we are reading from the file being "mored"
             * input: a character received from the keyboard
             *
             * If we hit a newline in the _file_ stream, we want to test and
             * see if any characters have been hit in the _input_ stream. This
             * allows the user to quit while in the middle of a file.
             */
            if (c == '\n') {
                /* increment by just one line if we are at
                 * the end of this line */
                if (input == '\n')
                    please_display_more_prompt |= 1;
                /* Adjust the terminal height for any overlap, so that
                 * no lines get lost off the top. */
                if (len >= terminal_width) {
                    int quot, rem;
                    quot = len / terminal_width;
                    rem  = len - (quot * terminal_width);
                    page_height -= (quot - 1);
                    if (rem)
                        page_height--;
                }
                if (++lines >= page_height) {
                    please_display_more_prompt |= 1;
                }
                len = 0;
            }
            /*
             * If we just read a newline from the file being 'mored' and any
             * key other than a return is hit, scroll by one page
             */
            putc(c, stdout);
            /* My small mind cannot fathom tabs, backspaces,
             * and UTF-8 */
            len++;
        }
        fclose(file);
        fflush(stdout);
    } while (*argv && *++argv);
end:
    setTermSettings(cin_fileno, &initial_settings);
    return 0;
}
Exemple #13
0
int telnet_main(int argc UNUSED_PARAM, char **argv)
{
	char *host;
	int port;
	int len;
	struct pollfd ufds[2];

	INIT_G();

#if ENABLE_FEATURE_AUTOWIDTH
	get_terminal_width_height(0, &G.win_width, &G.win_height);
#endif

#if ENABLE_FEATURE_TELNET_TTYPE
	G.ttype = getenv("TERM");
#endif

	if (tcgetattr(0, &G.termios_def) >= 0) {
		G.do_termios = 1;
		G.termios_raw = G.termios_def;
		cfmakeraw(&G.termios_raw);
	}

#if ENABLE_FEATURE_TELNET_AUTOLOGIN
	if (1 & getopt32(argv, "al:", &G.autologin))
		G.autologin = getenv("USER");
	argv += optind;
#else
	argv++;
#endif
	if (!*argv)
		bb_show_usage();
	host = *argv++;
	port = bb_lookup_port(*argv ? *argv++ : "telnet", "tcp", 23);
	if (*argv) /* extra params?? */
		bb_show_usage();

	xmove_fd(create_and_connect_stream_or_die(host, port), netfd);

	setsockopt_keepalive(netfd);

	signal(SIGINT, record_signo);

	ufds[0].fd = STDIN_FILENO;
	ufds[0].events = POLLIN;
	ufds[1].fd = netfd;
	ufds[1].events = POLLIN;

	while (1) {
		if (poll(ufds, 2, -1) < 0) {
			/* error, ignore and/or log something, bay go to loop */
			if (bb_got_signal)
				con_escape();
			else
				sleep(1);
			continue;
		}

// FIXME: reads can block. Need full bidirectional buffering.

		if (ufds[0].revents) {
			len = safe_read(STDIN_FILENO, G.buf, DATABUFSIZE);
			if (len <= 0)
				doexit(EXIT_SUCCESS);
			TRACE(0, ("Read con: %d\n", len));
			handle_net_output(len);
		}

		if (ufds[1].revents) {
			len = safe_read(netfd, G.buf, DATABUFSIZE);
			if (len <= 0) {
				full_write1_str("Connection closed by foreign host\r\n");
				doexit(EXIT_FAILURE);
			}
			TRACE(0, ("Read netfd (%d): %d\n", netfd, len));
			handle_net_input(len);
		}
	} /* while (1) */
}
Exemple #14
0
static unsigned int get_tty2_width(void)
{
	unsigned width;
	get_terminal_width_height(2, &width, NULL);
	return width;
}
Exemple #15
0
extern int ls_main(int argc, char **argv)
{
	struct dnode **dnd;
	struct dnode **dnf;
	struct dnode **dnp;
	struct dnode *dn;
	struct dnode *cur;
	long opt;
	int nfiles = 0;
	int dnfiles;
	int dndirs;
	int oi;
	int ac;
	int i;
	char **av;
#ifdef CONFIG_FEATURE_AUTOWIDTH
	char *tabstops_str = NULL;
	char *terminal_width_str = NULL;
#endif

#ifdef CONFIG_SELINUX
	is_flask_enabled_flag = is_flask_enabled();
#endif

	all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO
#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
		| TIME_MOD
#endif
#ifdef CONFIG_FEATURE_LS_SORTFILES
		| SORT_NAME | SORT_ORDER_FORWARD
#endif
		;

#ifdef CONFIG_FEATURE_AUTOWIDTH
	/* Obtain the terminal width.  */
	get_terminal_width_height(0, &terminal_width, NULL);
	/* Go one less... */
	terminal_width--;
#endif

#ifdef CONFIG_FEATURE_LS_COLOR
	if (isatty(fileno(stdout)))
		show_color = 1;
#endif

	/* process options */
#ifdef CONFIG_FEATURE_AUTOWIDTH
	opt = bb_getopt_ulflags(argc, argv, ls_options, &tabstops_str, &terminal_width_str);
	if (tabstops_str) {
		tabstops = atoi(tabstops_str);
	}
	if (terminal_width_str) {
		terminal_width = atoi(terminal_width_str);
	}
#else
	opt = bb_getopt_ulflags(argc, argv, ls_options);
#endif
	/* 16 = maximum options minus tabsize and screewn width */
	for (i = 0; i < 16; i++) {
		if (opt & (1 << i)) {
			unsigned int flags = opt_flags[i];
			if (flags & LIST_MASK_TRIGGER) {
				all_fmt &= ~LIST_MASK;
			}
			if (flags & STYLE_MASK_TRIGGER) {
				all_fmt &= ~STYLE_MASK;
			}
#ifdef CONFIG_FEATURE_LS_SORTFILES
			if (flags & SORT_MASK_TRIGGER) {
				all_fmt &= ~SORT_MASK;
			}
#endif
			if (flags & DISP_MASK_TRIGGER) {
				all_fmt &= ~DISP_MASK;
			}
#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
			if (flags & TIME_MASK_TRIGGER) {
				all_fmt &= ~TIME_MASK;
			}
#endif
			if (flags & LIST_CONTEXT) {
				all_fmt |= STYLE_SINGLE;
			}
#ifdef CONFIG_FEATURE_HUMAN_READABLE
			if (opt == 'l') {
				all_fmt &= ~LS_DISP_HR;
			}
#endif
			all_fmt |= flags;
		}
	}

	/* sort out which command line options take precedence */
#ifdef CONFIG_FEATURE_LS_RECURSIVE
	if (all_fmt & DISP_NOLIST)
		all_fmt &= ~DISP_RECURSIVE;	/* no recurse if listing only dir */
#endif
#if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES)
	if (all_fmt & TIME_CHANGE)
		all_fmt = (all_fmt & ~SORT_MASK) | SORT_CTIME;
	if (all_fmt & TIME_ACCESS)
		all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
#endif
	if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */
		all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC);
#ifdef CONFIG_FEATURE_LS_USERNAME
	if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
		all_fmt &= ~LIST_ID_NAME;	/* don't list names if numeric uid */
#endif
			
	/* choose a display format */
	if ((all_fmt & STYLE_MASK) == STYLE_AUTO)
#if STYLE_AUTO != 0
		all_fmt = (all_fmt & ~STYLE_MASK)
				| (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
#else
		all_fmt |= (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
#endif

	/*
	 * when there are no cmd line args we have to supply a default "." arg.
	 * we will create a second argv array, "av" that will hold either
	 * our created "." arg, or the real cmd line args.  The av array
	 * just holds the pointers- we don't move the date the pointers
	 * point to.
	 */
	ac = argc - optind;	/* how many cmd line args are left */
	if (ac < 1) {
		av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *)));
		av[0] = bb_xstrdup(".");
		ac = 1;
	} else {
		av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *)));
		for (oi = 0; oi < ac; oi++) {
			av[oi] = argv[optind++];	/* copy pointer to real cmd line arg */
		}
	}

	/* now, everything is in the av array */
	if (ac > 1)
		all_fmt |= DISP_DIRNAME;	/* 2 or more items? label directories */

	/* stuff the command line file names into an dnode array */
	dn = NULL;
	for (oi = 0; oi < ac; oi++) {
		char *fullname = bb_xstrdup(av[oi]);

		cur = my_stat(fullname, fullname);
		if (!cur)
			continue;
		cur->next = dn;
		dn = cur;
		nfiles++;
	}

	/* now that we know how many files there are
	   ** allocate memory for an array to hold dnode pointers
	 */
	dnp = dnalloc(nfiles);
	for (i = 0, cur = dn; i < nfiles; i++) {
		dnp[i] = cur;	/* save pointer to node in array */
		cur = cur->next;
	}


	if (all_fmt & DISP_NOLIST) {
#ifdef CONFIG_FEATURE_LS_SORTFILES
		shellsort(dnp, nfiles);
#endif
		if (nfiles > 0)
			showfiles(dnp, nfiles);
	} else {
		dnd = splitdnarray(dnp, nfiles, SPLIT_DIR);
		dnf = splitdnarray(dnp, nfiles, SPLIT_FILE);
		dndirs = countdirs(dnp, nfiles);
		dnfiles = nfiles - dndirs;
		if (dnfiles > 0) {
#ifdef CONFIG_FEATURE_LS_SORTFILES
			shellsort(dnf, dnfiles);
#endif
			showfiles(dnf, dnfiles);
		}
		if (dndirs > 0) {
#ifdef CONFIG_FEATURE_LS_SORTFILES
			shellsort(dnd, dndirs);
#endif
			showdirs(dnd, dndirs);
		}
	}
	return (status);
}
Exemple #16
0
int less_main(int argc, char **argv)
{
	int keypress;

	INIT_G();

	/* TODO: -x: do not interpret backspace, -xx: tab also */
	/* -xxx: newline also */
	/* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
	getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S"));
	argc -= optind;
	argv += optind;
	num_files = argc;
	files = argv;

	/* Another popular pager, most, detects when stdout
	 * is not a tty and turns into cat. This makes sense. */
	if (!isatty(STDOUT_FILENO))
		return bb_cat(argv);

	if (!num_files) {
		if (isatty(STDIN_FILENO)) {
			/* Just "less"? No args and no redirection? */
			bb_error_msg("missing filename");
			bb_show_usage();
		}
	} else {
		filename = xstrdup(files[0]);
	}

	if (option_mask32 & FLAG_TILDE)
		empty_line_marker = "";

	kbd_fd = open(CURRENT_TTY, O_RDONLY);
	if (kbd_fd < 0)
		return bb_cat(argv);
	ndelay_on(kbd_fd);

	tcgetattr(kbd_fd, &term_orig);
	term_less = term_orig;
	term_less.c_lflag &= ~(ICANON | ECHO);
	term_less.c_iflag &= ~(IXON | ICRNL);
	/*term_less.c_oflag &= ~ONLCR;*/
	term_less.c_cc[VMIN] = 1;
	term_less.c_cc[VTIME] = 0;

	get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
	/* 20: two tabstops + 4 */
	if (width < 20 || max_displayed_line < 3)
		return bb_cat(argv);
	max_displayed_line -= 2;

	/* We want to restore term_orig on exit */
	bb_signals(BB_FATAL_SIGS, sig_catcher);
#if ENABLE_FEATURE_LESS_WINCH
	signal(SIGWINCH, sigwinch_handler);
#endif

	buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
	reinitialize();
	while (1) {
#if ENABLE_FEATURE_LESS_WINCH
		while (WINCH_COUNTER) {
 again:
			winch_counter--;
			get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
			/* 20: two tabstops + 4 */
			if (width < 20)
				width = 20;
			if (max_displayed_line < 3)
				max_displayed_line = 3;
			max_displayed_line -= 2;
			free(buffer);
			buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
			/* Avoid re-wrap and/or redraw if we already know
			 * we need to do it again. These ops are expensive */
			if (WINCH_COUNTER)
				goto again;
			re_wrap();
			if (WINCH_COUNTER)
				goto again;
			buffer_fill_and_print();
			/* This took some time. Loop back and check,
			 * were there another SIGWINCH? */
		}
#endif
		keypress = less_getch(-1); /* -1: do not position cursor */
		keypress_process(keypress);
	}
}
Exemple #17
0
int busybox_main(int argc, char **argv)
{
	/*
	 * This style of argument parsing doesn't scale well
	 * in the event that busybox starts wanting more --options.
	 * If someone has a cleaner approach, by all means implement it.
	 */
	if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) {
		int use_symbolic_links = 0;
		int rc = 0;
		char *busybox;

		/* to use symlinks, or not to use symlinks... */
		if (argc > 2) {
			if ((strcmp(argv[2], "-s") == 0)) {
				use_symbolic_links = 1;
			}
		}

		/* link */
		busybox = xreadlink("/proc/self/exe");
		if (busybox) {
			install_links(busybox, use_symbolic_links);
			free(busybox);
		} else {
			rc = 1;
		}
		return rc;
	}

	/* Deal with --help.  (Also print help when called with no arguments) */

	if (argc==1 || !strcmp(argv[1],"--help") ) {
		if (argc>2) {
			run_applet_by_name(bb_applet_name=argv[2], 2, argv);
		} else {
			const struct BB_applet *a;
			int col, output_width;

			if (ENABLE_FEATURE_AUTOWIDTH) {
				/* Obtain the terminal width.  */
				get_terminal_width_height(0, &output_width, NULL);
				/* leading tab and room to wrap */
				output_width -= 20;
			} else output_width = 60;

			printf("%s\n\n"
			       "Usage: busybox [function] [arguments]...\n"
			       "   or: [function] [arguments]...\n\n"
			       "\tBusyBox is a multi-call binary that combines many common Unix\n"
			       "\tutilities into a single executable.  Most people will create a\n"
			       "\tlink to busybox for each function they wish to use and BusyBox\n"
			       "\twill act like whatever it was invoked as!\n"
			       "\nCurrently defined functions:\n", bb_msg_full_version);

			col=0;
			for(a = applets; a->name;) {
				col += printf("%s%s", (col ? ", " : "\t"), (a++)->name);
				if (col > output_width && a->name) {
					printf(",\n");
					col = 0;
				}
			}
			printf("\n\n");
			exit(0);
		}
	} else run_applet_by_name(bb_applet_name=argv[1], argc-1, argv+1);

	bb_error_msg_and_die("applet not found");
}