Exemplo n.º 1
0
static void my_fgets80(char *buf80)
{
	fflush_all();
	if (!fgets(buf80, 80, stdin)) {
		bb_perror_msg_and_die("can't read standard input");
	}
}
Exemplo n.º 2
0
static void die_if_nologin(void)
{
    FILE *fp;
    int c;
    int empty = 1;

    fp = fopen_for_read("/etc/nologin");
    if (!fp) /* assuming it does not exist */
        return;

    while ((c = getc(fp)) != EOF) {
        if (c == '\n')
            bb_putchar('\r');
        bb_putchar(c);
        empty = 0;
    }
    if (empty)
        puts("\r\nSystem closed for routine maintenance\r");

    fclose(fp);
    fflush_all();
    /* Users say that they do need this prior to exit: */
    tcdrain(STDOUT_FILENO);
    exit(EXIT_FAILURE);
}
Exemplo n.º 3
0
static void confirm_or_abort(void)
{
	fprintf(stderr, "Continue? [y/N] ");
	fflush_all();
	if (!bb_ask_confirmation())
		bb_error_msg_and_die("aborting");
}
Exemplo n.º 4
0
static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
{
	printf("\rErasing %u Kibyte @ %x - %2u%% complete.",
		(unsigned)meminfo->erasesize / 1024,
		erase->start,
		(unsigned) ((unsigned long long) erase->start * 100 / meminfo->size)
	);
	fflush_all();
}
Exemplo n.º 5
0
/* Die with an error message if we can't copy an entire FILE* to stdout,
 * then close that file. */
void FAST_FUNC xprint_and_close_file(FILE *file)
{
	fflush_all();
	// copyfd outputs error messages for us.
	if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1)
		xfunc_die();

	fclose(file);
}
Exemplo n.º 6
0
void FAST_FUNC print_login_prompt(void)
{
	char *hostname = safe_gethostname();

	fputs(hostname, stdout);
	fputs(LOGIN, stdout);
	fflush_all();
	free(hostname);
}
/* Code size is approximately the same, but currently it's the only user
 * of writev in entire bbox. __libc_writev in uclibc is ~50 bytes. */
void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
{
	int strerr_len, msgeol_len;
	struct iovec iov[3];

#define used   (iov[2].iov_len)
#define msgv   (iov[2].iov_base)
#define msgc   ((char*)(iov[2].iov_base))
#define msgptr (&(iov[2].iov_base))

	if (!logmode)
		return;

	if (!s) /* nomsg[_and_die] uses NULL fmt */
		s = ""; /* some libc don't like printf(NULL) */

	/* Prevent "derefing type-punned ptr will break aliasing rules" */
	used = vasprintf((char**)(void*)msgptr, s, p);
	if (used < 0)
		return;

	/* This is ugly and costs +60 bytes compared to multiple
	 * fprintf's, but is guaranteed to do a single write.
	 * This is needed for e.g. httpd logging, when multiple
	 * children can produce log messages simultaneously. */

	strerr_len = strerr ? strlen(strerr) : 0;
	msgeol_len = strlen(msg_eol);
	/* +3 is for ": " before strerr and for terminating NUL */
	msgv = xrealloc(msgv, used + strerr_len + msgeol_len + 3);
	if (strerr) {
		msgc[used++] = ':';
		msgc[used++] = ' ';
		strcpy(msgc + used, strerr);
		used += strerr_len;
	}
	strcpy(msgc + used, msg_eol);
	used += msgeol_len;

	if (logmode & LOGMODE_STDIO) {
		iov[0].iov_base = (char*)applet_name;
		iov[0].iov_len = strlen(applet_name);
		iov[1].iov_base = (char*)": ";
		iov[1].iov_len = 2;
		/*iov[2].iov_base = msgc;*/
		/*iov[2].iov_len = used;*/
		fflush_all();
		writev(STDERR_FILENO, iov, 3);
	}
# if ENABLE_FEATURE_SYSLOG
	if (logmode & LOGMODE_SYSLOG) {
		syslog(LOG_ERR, "%s", msgc);
	}
# endif
	free(msgc);
}
Exemplo n.º 8
0
int length_main(int argc, char **argv)
{
	if ((argc != 2) || (**(++argv) == '-')) {
		bb_show_usage();
	}

	printf("%u\n", (unsigned)strlen(*argv));

	return fflush_all();
}
// file coreutils/dirname.c line 29
signed int __main(signed int argc, char **argv)
{
  char *return_value_single_argv$1;
  return_value_single_argv$1=single_argv(argv);
  char *return_value_dirname$2;
  return_value_dirname$2=dirname(return_value_single_argv$1);
  puts(return_value_dirname$2);
  signed int return_value_fflush_all$3;
  return_value_fflush_all$3=fflush_all();
  return return_value_fflush_all$3;
}
Exemplo n.º 10
0
static void motd(void)
{
    int fd;

    fd = open(bb_path_motd_file, O_RDONLY);
    if (fd >= 0) {
        fflush_all();
        bb_copyfd_eof(fd, STDOUT_FILENO);
        close(fd);
    }
}
Exemplo n.º 11
0
static void alarm_handler(int sig UNUSED_PARAM)
{
    /* This is the escape hatch!  Poor serial line users and the like
     * arrive here when their connection is broken.
     * We don't want to block here */
    ndelay_on(1);
    printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT);
    fflush_all();
    /* unix API is brain damaged regarding O_NONBLOCK,
     * we should undo it, or else we can affect other processes */
    ndelay_off(1);
    _exit(EXIT_SUCCESS);
}
Exemplo n.º 12
0
/* Read a line from fp.  If the first non-whitespace char is 'y' or 'Y',
 * return 1.  Otherwise return 0.
 */
int FAST_FUNC bb_ask_y_confirmation_FILE(FILE *fp)
{
	char first = 0;
	int c;

	fflush_all();
	while (((c = fgetc(fp)) != EOF) && (c != '\n')) {
		if (first == 0 && !isblank(c)) {
			first = c|0x20;
		}
	}

	return first == 'y';
}
Exemplo n.º 13
0
static void progress(int mode, uoff_t count, uoff_t total)
{
	uoff_t percent;

	if (!option_mask32) //if (!(option_mask32 & OPT_v))
		return;
	percent = count * 100;
	if (total)
		percent = (unsigned) (percent / total);
	printf("\r%s: %"OFF_FMT"u/%"OFF_FMT"u (%u%%) ",
		(mode < 0) ? "Erasing block" : ((mode == 0) ? "Writing kb" : "Verifying kb"),
		count, total, (unsigned)percent);
	fflush_all();
}
Exemplo n.º 14
0
char* FAST_FUNC send_mail_command(const char *fmt, const char *param)
{
	char *msg;
	if (timeout)
		alarm(timeout);
	msg = (char*)fmt;
	if (fmt) {
		msg = xasprintf(fmt, param);
		if (verbose)
			bb_error_msg("send:'%s'", msg);
		printf("%s\r\n", msg);
	}
	fflush_all();
	return msg;
}
Exemplo n.º 15
0
/* Prompt the user for a response, and
 * if user responds affirmatively, return true;
 * otherwise, return false. Uses "/dev/tty", not stdin.
 */
static int xargs_ask_confirmation(void)
{
	FILE *tty_stream;
	int c, savec;

#if !ENABLE_PLATFORM_MINGW32
	tty_stream = xfopen_for_read(CURRENT_TTY);
#endif
	fputs(" ?...", stderr);
	fflush_all();
#if !ENABLE_PLATFORM_MINGW32
	c = savec = getc(tty_stream);
	while (c != EOF && c != '\n')
		c = getc(tty_stream);
	fclose(tty_stream);
#else
	c = savec = getche();
	while (c != EOF && c != '\r')
		c = getche();
	fputs("\n", stderr);
	fflush_all();
#endif
	return (savec == 'y' || savec == 'Y');
}
Exemplo n.º 16
0
void FAST_FUNC bb_info_msg(const char *s, ...)
{
#ifdef THIS_ONE_DOESNT_DO_SINGLE_WRITE
	va_list p;
	/* va_copy is used because it is not portable
	 * to use va_list p twice */
	va_list p2;

	va_start(p, s);
	va_copy(p2, p);
	if (logmode & LOGMODE_STDIO) {
		vprintf(s, p);
		fputs(msg_eol, stdout);
	}
# if ENABLE_FEATURE_SYSLOG
	if (logmode & LOGMODE_SYSLOG)
		vsyslog(LOG_INFO, s, p2);
# endif
	va_end(p2);
	va_end(p);
#else
	int used;
	char *msg;
	va_list p;

	if (logmode == 0)
		return;

	va_start(p, s);
	used = vasprintf(&msg, s, p);
	va_end(p);
	if (used < 0)
		return;

# if ENABLE_FEATURE_SYSLOG
	if (logmode & LOGMODE_SYSLOG)
		syslog(LOG_INFO, "%s", msg);
# endif
	if (logmode & LOGMODE_STDIO) {
		fflush_all();
		/* used = strlen(msg); - must be true already */
		msg[used++] = '\n';
		full_write(STDOUT_FILENO, msg, used);
	}

	free(msg);
#endif
}
Exemplo n.º 17
0
/*
 * Write the specified lines out to the specified file.
 * Returns TRUE if successful, or FALSE on an error with a message output.
 */
static int writeLines(const char *file, int num1, int num2)
{
	LINE *lp;
	int fd, lineCount, charCount;

	if (bad_nums(num1, num2, "write"))
		return FALSE;

	lineCount = 0;
	charCount = 0;

	fd = creat(file, 0666);
	if (fd < 0) {
		bb_simple_perror_msg(file);
		return FALSE;
	}

	printf("\"%s\", ", file);
	fflush_all();

	lp = findLine(num1);
	if (lp == NULL) {
		close(fd);
		return FALSE;
	}

	while (num1++ <= num2) {
		if (full_write(fd, lp->data, lp->len) != lp->len) {
			bb_simple_perror_msg(file);
			close(fd);
			return FALSE;
		}
		charCount += lp->len;
		lineCount++;
		lp = lp->next;
	}

	if (close(fd) < 0) {
		bb_simple_perror_msg(file);
		return FALSE;
	}

	printf("%d lines, %d chars\n", lineCount, charCount);
	return TRUE;
}
// file coreutils/hostid.c line 33
signed int __main(signed int argc, char **argv)
{
  if(!(argv == ((char **)NULL)))
    (void)0;

  else
    /* assertion !(argv == ((char **)((void*)0))) */
    __VERIFIER_error();
  if(!(*(1l + argv) == ((char *)NULL)))
    bb_show_usage();

  signed long int return_value_gethostid$1;
  return_value_gethostid$1=gethostid();
  printf("%08x\n", (unsigned int)return_value_gethostid$1);
  signed int return_value_fflush_all$2;
  return_value_fflush_all$2=fflush_all();
  return return_value_fflush_all$2;
}
Exemplo n.º 19
0
void FAST_FUNC print_login_prompt(void)
{
	char buf[MAXHOSTNAMELEN+1];
/* Login Prompt by BrainSlayer */
  FILE *fp = fopen ("/tmp/loginprompt", "rb");
  if (fp)
    {    
      int d;
      while ((d=getc(fp))!=EOF)
	{
	  putc (d, stdout);
	}
      fclose (fp);
    }
	fprintf(stdout,"\n");
 	char *hostname = safe_gethostname(); 	
	fputs(hostname, stdout);
	fputs(LOGIN, stdout);
	fflush_all();
	free(hostname);
}
Exemplo n.º 20
0
/* This does a fork/exec in one call, using vfork().  Returns PID of new child,
 * -1 for failure.  Runs argv[0], searching path if that has no / in it. */
pid_t FAST_FUNC spawn(char **argv)
{
	/* Compiler should not optimize stores here */
	volatile int failed;
	pid_t pid;

	fflush_all();

	/* Be nice to nommu machines. */
	failed = 0;
	pid = vfork();
	if (pid < 0) /* error */
		return pid;
	if (!pid) { /* child */
		/* This macro is ok - it doesn't do NOEXEC/NOFORK tricks */
		BB_EXECVP(argv[0], argv);

		/* We are (maybe) sharing a stack with blocked parent,
		 * let parent know we failed and then exit to unblock parent
		 * (but don't run atexit() stuff, which would screw up parent.)
		 */
		failed = errno;
		/* mount, for example, does not want the message */
		/*bb_perror_msg("can't execute '%s'", argv[0]);*/
		_exit(111);
	}
	/* parent */
	/* Unfortunately, this is not reliable: according to standards
	 * vfork() can be equivalent to fork() and we won't see value
	 * of 'failed'.
	 * Interested party can wait on pid and learn exit code.
	 * If 111 - then it (most probably) failed to exec */
	if (failed) {
		safe_waitpid(pid, NULL, 0); /* prevent zombie */
		errno = failed;
		return -1;
	}
	return pid;
}
Exemplo n.º 21
0
/* Reset terminal input to normal */
static void set_tty_cooked(void)
{
	fflush_all();
	tcsetattr(kbd_fd, TCSANOW, &term_orig);
}
void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
{
	char *msg, *msg1;
	int applet_len, strerr_len, msgeol_len, used;

	if (!logmode)
		return;

	if (!s) /* nomsg[_and_die] uses NULL fmt */
		s = ""; /* some libc don't like printf(NULL) */

	used = vasprintf(&msg, s, p);
	if (used < 0)
		return;

	/* This is ugly and costs +60 bytes compared to multiple
	 * fprintf's, but is guaranteed to do a single write.
	 * This is needed for e.g. httpd logging, when multiple
	 * children can produce log messages simultaneously. */

	applet_len = strlen(applet_name) + 2; /* "applet: " */
	strerr_len = strerr ? strlen(strerr) : 0;
	msgeol_len = strlen(msg_eol);
	/* can't use xrealloc: it calls error_msg on failure,
	 * that may result in a recursion */
	/* +3 is for ": " before strerr and for terminating NUL */
	msg1 = realloc(msg, applet_len + used + strerr_len + msgeol_len + 3);
	if (!msg1) {
		msg[used++] = '\n'; /* overwrites NUL */
		applet_len = 0;
	} else {
		msg = msg1;
		/* TODO: maybe use writev instead of memmoving? Need full_writev? */
		memmove(msg + applet_len, msg, used);
		used += applet_len;
		strcpy(msg, applet_name);
		msg[applet_len - 2] = ':';
		msg[applet_len - 1] = ' ';
		if (strerr) {
			if (s[0]) { /* not perror_nomsg? */
				msg[used++] = ':';
				msg[used++] = ' ';
			}
			strcpy(&msg[used], strerr);
			used += strerr_len;
		}
		strcpy(&msg[used], msg_eol);
		used += msgeol_len;
	}

	if (logmode & LOGMODE_STDIO) {
		fflush_all();
		full_write(STDERR_FILENO, msg, used);
	}
#if ENABLE_FEATURE_SYSLOG
	if (logmode & LOGMODE_SYSLOG) {
		syslog(LOG_ERR, "%s", msg + applet_len);
	}
#endif
	free(msg);
}
Exemplo n.º 23
0
void FAST_FUNC print_login_issue(const char *issue_file, const char *tty)
{
	FILE *fp;
	int c;
	char buf[256+1];
	const char *outbuf;
	time_t t;
	struct utsname uts;

	time(&t);
	uname(&uts);

	puts("\r");  /* start a new line */

	fp = fopen_for_read(issue_file);
	if (!fp)
		return;
	while ((c = fgetc(fp)) != EOF) {
		outbuf = buf;
		buf[0] = c;
		buf[1] = '\0';
		if (c == '\n') {
			buf[1] = '\r';
			buf[2] = '\0';
		}
		if (c == '\\' || c == '%') {
			c = fgetc(fp);
			switch (c) {
//From getty manpage (* - supported by us)
//========================================
//4 or 4{interface}
//  Insert the IPv4 address of the network interface (example: \4{eth0}).
//  If the interface argument is not specified, then select the first
//  fully configured (UP, non-LOOPBACK, RUNNING) interface.
//6 or 6{interface} -- The same as \4 but for IPv6.
//b -- Insert the baudrate of the current line.
//*d -- Insert the current date.
//*t -- Insert the current time.
//e or e{name}
//  Translate the human-readable name to an escape sequence and insert it
//  (for example: \e{red}Alert text.\e{reset}).  If the name argument
//  is not specified, then insert \033. The currently supported names are:
//  black, blink, blue, bold, brown, cyan, darkgray, gray, green, halfbright,
//  lightblue, lightcyan, lightgray, lightgreen, lightmagenta, lightred,
//  magenta, red, reset, reverse, and yellow. Unknown names are ignored.
//*s
//  Insert the system name (the name of the operating system - `uname -s`)
//*S or S{VARIABLE}
//  Insert the VARIABLE data from /etc/os-release.
//  If the VARIABLE argument is not specified, use PRETTY_NAME.
//  If PRETTY_NAME is not in /etc/os-release, \S is the same as \s.
//*l -- Insert the name of the current tty line.
//*m -- Insert the architecture identifier of the machine: `uname -m`.
//*n -- Insert the nodename of the machine: `uname -n`.
//*o -- Insert the NIS domainname of the machine.  Same as `hostname -d'.
//*O -- Insert the DNS domainname of the machine.
//*r -- Insert the release number of the OS: `uname -r`.
//u -- Insert the number of current users logged in.
//U -- Insert the string "1 user" or "N users" (current users logged in).
//*v -- Insert the version of the OS, e.g. the build-date etc: `uname -v`.
//We also implement:
//*D -- same as \O "DNS domainname"
//*h -- same as \n "nodename"

			case 'S':
				/* minimal implementation, not reading /etc/os-release */
				/*FALLTHROUGH*/
			case 's':
				outbuf = uts.sysname;
				break;
			case 'n':
			case 'h':
				outbuf = uts.nodename;
				break;
			case 'r':
				outbuf = uts.release;
				break;
			case 'v':
				outbuf = uts.version;
				break;
			case 'm':
				outbuf = uts.machine;
				break;
/* The field domainname of struct utsname is Linux specific. */
#if defined(__linux__)
			case 'D':
			case 'o':
			case 'O':
				outbuf = uts.domainname;
				break;
#endif
			case 'd':
				strftime(buf, sizeof(buf), fmtstr_d, localtime(&t));
				break;
			case 't':
				strftime_HHMMSS(buf, sizeof(buf), &t);
				break;
			case 'l':
				outbuf = tty;
				break;
			default:
				buf[0] = c;
			}
		}
		fputs(outbuf, stdout);
	}
	fclose(fp);
	fflush_all();
}
Exemplo n.º 24
0
/* Dump all but word data. */
static void dump_data(int bus_fd, int mode, unsigned first,
		      unsigned last, int *block, int blen)
{
	int i, j, res;

	puts("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f"
	     "    0123456789abcdef");

	for (i = 0; i < I2CDUMP_NUM_REGS; i += 0x10) {
		if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
			break;
		if (i/16 < first/16)
			continue;
		if (i/16 > last/16)
			break;

		printf("%02x: ", i);
		for (j = 0; j < 16; j++) {
			fflush_all();
			/* Skip unwanted registers */
			if (i+j < first || i+j > last) {
				printf("   ");
				if (mode == I2C_SMBUS_WORD_DATA) {
					printf("   ");
					j++;
				}
				continue;
			}

			switch (mode) {
			case I2C_SMBUS_BYTE_DATA:
				res = i2c_smbus_read_byte_data(bus_fd, i+j);
				block[i+j] = res;
				break;
			case I2C_SMBUS_WORD_DATA:
				res = i2c_smbus_read_word_data(bus_fd, i+j);
				if (res < 0) {
					block[i+j] = res;
					block[i+j+1] = res;
				} else {
					block[i+j] = res & 0xff;
					block[i+j+1] = res >> 8;
				}
				break;
			case I2C_SMBUS_BYTE:
				res = i2c_smbus_read_byte(bus_fd);
				block[i+j] = res;
				break;
			default:
				res = block[i+j];
			}

			if (mode == I2C_SMBUS_BLOCK_DATA &&
			    i+j >= blen) {
				printf("   ");
			} else if (res < 0) {
				printf("XX ");
				if (mode == I2C_SMBUS_WORD_DATA)
					printf("XX ");
			} else {
				printf("%02x ", block[i+j]);
				if (mode == I2C_SMBUS_WORD_DATA)
					printf("%02x ", block[i+j+1]);
			}

			if (mode == I2C_SMBUS_WORD_DATA)
				j++;
		}
		printf("   ");

		for (j = 0; j < 16; j++) {
			if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
				break;
			/* Skip unwanted registers */
			if (i+j < first || i+j > last) {
				bb_putchar(' ');
				continue;
			}

			res = block[i+j];
			if (res < 0) {
				bb_putchar('X');
			} else if (res == 0x00 || res == 0xff) {
				bb_putchar('.');
			} else if (res < 32 || res >= 127) {
				bb_putchar('?');
			} else {
				bb_putchar(res);
			}
		}
		bb_putchar('\n');
	}
}
Exemplo n.º 25
0
/*
 * Read lines from a file at the specified line number.
 * Returns TRUE if the file was successfully read.
 */
static int readLines(const char *file, int num)
{
	int fd, cc;
	int len, lineCount, charCount;
	char *cp;

	if ((num < 1) || (num > lastNum + 1)) {
		bb_error_msg("bad line for read");
		return FALSE;
	}

	fd = open(file, 0);
	if (fd < 0) {
		bb_simple_perror_msg(file);
		return FALSE;
	}

	bufPtr = bufBase;
	bufUsed = 0;
	lineCount = 0;
	charCount = 0;
	cc = 0;

	printf("\"%s\", ", file);
	fflush_all();

	do {
		cp = memchr(bufPtr, '\n', bufUsed);

		if (cp) {
			len = (cp - bufPtr) + 1;
			if (!insertLine(num, bufPtr, len)) {
				close(fd);
				return FALSE;
			}
			bufPtr += len;
			bufUsed -= len;
			charCount += len;
			lineCount++;
			num++;
			continue;
		}

		if (bufPtr != bufBase) {
			memcpy(bufBase, bufPtr, bufUsed);
			bufPtr = bufBase + bufUsed;
		}

		if (bufUsed >= bufSize) {
			len = (bufSize * 3) / 2;
			cp = xrealloc(bufBase, len);
			bufBase = cp;
			bufPtr = bufBase + bufUsed;
			bufSize = len;
		}

		cc = safe_read(fd, bufPtr, bufSize - bufUsed);
		bufUsed += cc;
		bufPtr = bufBase;
	} while (cc > 0);

	if (cc < 0) {
		bb_simple_perror_msg(file);
		close(fd);
		return FALSE;
	}

	if (bufUsed) {
		if (!insertLine(num, bufPtr, bufUsed)) {
			close(fd);
			return -1;
		}
		lineCount++;
		charCount += bufUsed;
	}

	close(fd);

	printf("%d lines%s, %d chars\n", lineCount,
		(bufUsed ? " (incomplete)" : ""), charCount);

	return TRUE;
}
char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
{
	/* Was static char[BIGNUM] */
	enum { sizeof_passwd = 128 };
	static char *passwd;

	char *ret;
	int i;
	struct sigaction sa, oldsa;
	struct termios tio, oldtio;

	tcgetattr(fd, &oldtio);
	tcflush(fd, TCIFLUSH);
	tio = oldtio;
#ifndef IUCLC
# define IUCLC 0
#endif
	tio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
	tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP);
	tcsetattr(fd, TCSANOW, &tio);

	memset(&sa, 0, sizeof(sa));
	/* sa.sa_flags = 0; - no SA_RESTART! */
	/* SIGINT and SIGALRM will interrupt reads below */
	sa.sa_handler = askpass_timeout;
	sigaction(SIGINT, &sa, &oldsa);
	if (timeout) {
		sigaction_set(SIGALRM, &sa);
		alarm(timeout);
	}

	fputs(prompt, stdout);
	fflush_all();

	if (!passwd)
		passwd = xmalloc(sizeof_passwd);
	ret = passwd;
	i = 0;
	while (1) {
		int r = read(fd, &ret[i], 1);
		if (r < 0) {
			/* read is interrupted by timeout or ^C */
			ret = NULL;
			break;
		}
		if (r == 0 /* EOF */
		 || ret[i] == '\r' || ret[i] == '\n' /* EOL */
		 || ++i == sizeof_passwd-1 /* line limit */
		) {
			ret[i] = '\0';
			break;
		}
	}

	if (timeout) {
		alarm(0);
	}
	sigaction_set(SIGINT, &oldsa);
	tcsetattr(fd, TCSANOW, &oldtio);
	bb_putchar('\n');
	fflush_all();
	return ret;
}
Exemplo n.º 27
0
static int getch_nowait(void)
{
	int rd;
	struct pollfd pfd[2];

	pfd[0].fd = STDIN_FILENO;
	pfd[0].events = POLLIN;
	pfd[1].fd = kbd_fd;
	pfd[1].events = POLLIN;
 again:
	tcsetattr(kbd_fd, TCSANOW, &term_less);
	/* NB: select/poll returns whenever read will not block. Therefore:
	 * if eof is reached, select/poll will return immediately
	 * because read will immediately return 0 bytes.
	 * Even if select/poll says that input is available, read CAN block
	 * (switch fd into O_NONBLOCK'ed mode to avoid it)
	 */
	rd = 1;
	/* Are we interested in stdin? */
//TODO: reuse code for determining this
	if (!(option_mask32 & FLAG_S)
	   ? !(max_fline > cur_fline + max_displayed_line)
	   : !(max_fline >= cur_fline
	       && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
	) {
		if (eof_error > 0) /* did NOT reach eof yet */
			rd = 0; /* yes, we are interested in stdin */
	}
	/* Position cursor if line input is done */
	if (less_gets_pos >= 0)
		move_cursor(max_displayed_line + 2, less_gets_pos + 1);
	fflush_all();

	if (kbd_input[0] == 0) { /* if nothing is buffered */
#if ENABLE_FEATURE_LESS_WINCH
		while (1) {
			int r;
			/* NB: SIGWINCH interrupts poll() */
			r = poll(pfd + rd, 2 - rd, -1);
			if (/*r < 0 && errno == EINTR &&*/ winch_counter)
				return '\\'; /* anything which has no defined function */
			if (r) break;
		}
#else
		safe_poll(pfd + rd, 2 - rd, -1);
#endif
	}

	/* We have kbd_fd in O_NONBLOCK mode, read inside read_key()
	 * would not block even if there is no input available */
	rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2);
	if (rd == -1) {
		if (errno == EAGAIN) {
			/* No keyboard input available. Since poll() did return,
			 * we should have input on stdin */
			read_lines();
			buffer_fill_and_print();
			goto again;
		}
		/* EOF/error (ssh session got killed etc) */
		less_exit(0);
	}
	set_tty_cooked();
	return rd;
}
Exemplo n.º 28
0
int seq_main(int argc, char **argv)
{
	enum {
		OPT_w = (1 << 0),
		OPT_s = (1 << 1),
	};
	double first, last, increment, v;
	unsigned n;
	unsigned width;
	unsigned frac_part;
	const char *sep, *opt_s = "\n";
	unsigned opt;

#if ENABLE_LOCALE_SUPPORT
	/* Undo busybox.c: on input, we want to use dot
	 * as fractional separator, regardless of current locale */
	setlocale(LC_NUMERIC, "C");
#endif

	opt = getopt32(argv, "+ws:", &opt_s);
	argc -= optind;
	argv += optind;
	first = increment = 1;
	errno = 0;
	switch (argc) {
			char *pp;
		case 3:
			increment = strtod(argv[1], &pp);
			errno |= *pp;
		case 2:
			first = strtod(argv[0], &pp);
			errno |= *pp;
		case 1:
			last = strtod(argv[argc-1], &pp);
			if (!errno && *pp == '\0')
				break;
		default:
			bb_show_usage();
	}

#if ENABLE_LOCALE_SUPPORT
	setlocale(LC_NUMERIC, "");
#endif

	/* Last checked to be compatible with: coreutils-6.10 */
	width = 0;
	frac_part = 0;
	while (1) {
		char *dot = strchrnul(*argv, '.');
		int w = (dot - *argv);
		int f = strlen(dot);
		if (width < w)
			width = w;
		argv++;
		if (!*argv)
			break;
		/* Why do the above _before_ frac check below?
		 * Try "seq 1 2.0" and "seq 1.0 2.0":
		 * coreutils never pay attention to the number
		 * of fractional digits in last arg. */
		if (frac_part < f)
			frac_part = f;
	}
	if (frac_part) {
		frac_part--;
		if (frac_part)
			width += frac_part + 1;
	}
	if (!(opt & OPT_w))
		width = 0;

	sep = "";
	v = first;
	n = 0;
	while (increment >= 0 ? v <= last : v >= last) {
		if (printf("%s%0*.*f", sep, width, frac_part, v) < 0)
			break; /* I/O error, bail out (yes, this really happens) */
		sep = opt_s;
		/* v += increment; - would accumulate floating point errors */
		n++;
		v = first + n * increment;
	}
	if (n) /* if while loop executed at least once */
		bb_putchar('\n');

	return fflush_all();
}
Exemplo n.º 29
0
//TODO: use more efficient setvar() which takes a pointer to malloced "VAR=VAL"
//string. hush naturally has it, and ash has setvareq().
//Here we can simply store "VAR=" at buffer start and store read data directly
//after "=", then pass buffer to setvar() to consume.
const char* FAST_FUNC
shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
	char       **argv,
	const char *ifs,
	int        read_flags,
	const char *opt_n,
	const char *opt_p,
	const char *opt_t,
	const char *opt_u
)
{
	unsigned end_ms; /* -t TIMEOUT */
	int fd; /* -u FD */
	int nchars; /* -n NUM */
	char **pp;
	char *buffer;
	struct termios tty, old_tty;
	const char *retval;
	int bufpos; /* need to be able to hold -1 */
	int startword;
	smallint backslash;

	pp = argv;
	while (*pp) {
		if (!is_well_formed_var_name(*pp, '\0')) {
			/* Mimic bash message */
			bb_error_msg("read: '%s': not a valid identifier", *pp);
			return (const char *)(uintptr_t)1;
		}
		pp++;
	}

	nchars = 0; /* if != 0, -n is in effect */
	if (opt_n) {
		nchars = bb_strtou(opt_n, NULL, 10);
		if (nchars < 0 || errno)
			return "invalid count";
		/* note: "-n 0": off (bash 3.2 does this too) */
	}
	end_ms = 0;
	if (opt_t) {
		end_ms = bb_strtou(opt_t, NULL, 10);
		if (errno || end_ms > UINT_MAX / 2048)
			return "invalid timeout";
		end_ms *= 1000;
#if 0 /* even bash has no -t N.NNN support */
		ts.tv_sec = bb_strtou(opt_t, &p, 10);
		ts.tv_usec = 0;
		/* EINVAL means number is ok, but not terminated by NUL */
		if (*p == '.' && errno == EINVAL) {
			char *p2;
			if (*++p) {
				int scale;
				ts.tv_usec = bb_strtou(p, &p2, 10);
				if (errno)
					return "invalid timeout";
				scale = p2 - p;
				/* normalize to usec */
				if (scale > 6)
					return "invalid timeout";
				while (scale++ < 6)
					ts.tv_usec *= 10;
			}
		} else if (ts.tv_sec < 0 || errno) {
			return "invalid timeout";
		}
		if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
			return "invalid timeout";
		}
#endif /* if 0 */
	}
	fd = STDIN_FILENO;
	if (opt_u) {
		fd = bb_strtou(opt_u, NULL, 10);
		if (fd < 0 || errno)
			return "invalid file descriptor";
	}

	if (opt_p && isatty(fd)) {
		fputs(opt_p, stderr);
		fflush_all();
	}

	if (ifs == NULL)
		ifs = defifs;

	if (nchars || (read_flags & BUILTIN_READ_SILENT)) {
		tcgetattr(fd, &tty);
		old_tty = tty;
		if (nchars) {
			tty.c_lflag &= ~ICANON;
			tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
		}
		if (read_flags & BUILTIN_READ_SILENT) {
			tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
		}
		/* This forces execution of "restoring" tcgetattr later */
		read_flags |= BUILTIN_READ_SILENT;
		/* if tcgetattr failed, tcsetattr will fail too.
		 * Ignoring, it's harmless. */
		tcsetattr(fd, TCSANOW, &tty);
	}

	retval = (const char *)(uintptr_t)0;
	startword = 1;
	backslash = 0;
	if (end_ms) /* NB: end_ms stays nonzero: */
		end_ms = ((unsigned)monotonic_ms() + end_ms) | 1;
	buffer = NULL;
	bufpos = 0;
	do {
		char c;

		if (end_ms) {
			int timeout;
			struct pollfd pfd[1];

			pfd[0].fd = fd;
			pfd[0].events = POLLIN;
			timeout = end_ms - (unsigned)monotonic_ms();
			if (timeout <= 0 /* already late? */
			 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
			) { /* timed out! */
				retval = (const char *)(uintptr_t)1;
				goto ret;
			}
		}

		if ((bufpos & 0xff) == 0)
			buffer = xrealloc(buffer, bufpos + 0x100);
		if (nonblock_safe_read(fd, &buffer[bufpos], 1) != 1) {
			retval = (const char *)(uintptr_t)1;
			break;
		}
		c = buffer[bufpos];
		if (c == '\0')
			continue;
		if (backslash) {
			backslash = 0;
			if (c != '\n')
				goto put;
			continue;
		}
		if (!(read_flags & BUILTIN_READ_RAW) && c == '\\') {
			backslash = 1;
			continue;
		}
		if (c == '\n')
			break;

		/* $IFS splitting. NOT done if we run "read"
		 * without variable names (bash compat).
		 * Thus, "read" and "read REPLY" are not the same.
		 */
		if (argv[0]) {
/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */
			const char *is_ifs = strchr(ifs, c);
			if (startword && is_ifs) {
				if (isspace(c))
					continue;
				/* it is a non-space ifs char */
				startword--;
				if (startword == 1) /* first one? */
					continue; /* yes, it is not next word yet */
			}
			startword = 0;
			if (argv[1] != NULL && is_ifs) {
				buffer[bufpos] = '\0';
				bufpos = 0;
				setvar(*argv, buffer);
				argv++;
				/* can we skip one non-space ifs char? (2: yes) */
				startword = isspace(c) ? 2 : 1;
				continue;
			}
		}
 put:
		bufpos++;
	} while (--nchars);

	if (argv[0]) {
		/* Remove trailing space $IFS chars */
		while (--bufpos >= 0 && isspace(buffer[bufpos]) && strchr(ifs, buffer[bufpos]) != NULL)
			continue;
		buffer[bufpos + 1] = '\0';
		/* Use the remainder as a value for the next variable */
		setvar(*argv, buffer);
		/* Set the rest to "" */
		while (*++argv)
			setvar(*argv, "");
	} else {
		/* Note: no $IFS removal */
		buffer[bufpos] = '\0';
		setvar("REPLY", buffer);
	}

 ret:
	free(buffer);
	if (read_flags & BUILTIN_READ_SILENT)
		tcsetattr(fd, TCSANOW, &old_tty);
	return retval;
}
Exemplo n.º 30
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;
}