Esempio n. 1
0
int losetup_main(int argc, char **argv)
{
	unsigned opt;
	char *opt_o;
	unsigned long long offset = 0;

	opt = getopt32(argc, argv, "do:", &opt_o);
	argc -= optind;
	argv += optind;

	if (opt == 0x3) // -d + -o (illegal)
		bb_show_usage();

	if (opt == 0x1) { // -d
		/* detach takes exactly one argument */
		if (argc != 1)
			bb_show_usage();
		if (!del_loop(argv[0]))
			return EXIT_SUCCESS;
		bb_perror_nomsg_and_die();
	}

	if (opt == 0x2) // -o
		offset = xatoull(opt_o);

	/* -o or no option */

	if (argc == 2) {
		if (set_loop(&argv[0], argv[1], offset) < 0)
			bb_perror_nomsg_and_die();
	} else if (argc == 1) {
		char *s = query_loop(argv[0]);
		if (!s)
			bb_perror_nomsg_and_die();
		printf("%s: %s\n", argv[0], s);
		if (ENABLE_FEATURE_CLEAN_UP)
			free(s);
	} else {
		char dev[sizeof(LOOP_NAME"0")] = LOOP_NAME"0";
		char c;
		for (c = '0'; c <= '9'; ++c) {
			char *s;
			dev[sizeof(LOOP_NAME"0")-2] = c;
			s = query_loop(dev);
			if (s) {
				printf("%s: %s\n", dev, s);
				if (ENABLE_FEATURE_CLEAN_UP)
					free(s);
			}
		}
	}
	return EXIT_SUCCESS;
}
Esempio n. 2
0
static void tail_xprint_header(const char *fmt, const char *filename)
{
	/* If we get an output error, there is really no sense in continuing. */
	if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
		bb_perror_nomsg_and_die();
	}
}
Esempio n. 3
0
/* len should probably be size_t */
static void tail_xbb_full_write(const char *buf, size_t len)
{
	/* If we get a write error, there is really no sense in continuing. */
	if (bb_full_write(STDOUT_FILENO, buf, len) < 0) {
		bb_perror_nomsg_and_die();
	}
}
Esempio n. 4
0
int mktemp_main(int argc UNUSED_PARAM, char **argv)
{
	const char *path;
	char *chp;
	unsigned opts;
	enum {
		OPT_d = 1 << 0,
		OPT_q = 1 << 1,
		OPT_t = 1 << 2,
		OPT_p = 1 << 3,
		OPT_u = 1 << 4,
	};

	path = getenv("TMPDIR");
	if (!path || path[0] == '\0')
		path = "/tmp";

	opt_complementary = "?1"; /* 1 argument max */
	opts = getopt32(argv, "dqtp:u", &path);

	chp = argv[optind];
	if (!chp) {
		/* GNU coreutils 8.4:
		 * bare "mktemp" -> "mktemp -t tmp.XXXXXX"
		 */
		chp = xstrdup("tmp.XXXXXX");
		opts |= OPT_t;
	}
#if 0
	/* Don't allow directory separator in template */
	if ((opts & OPT_t) && bb_basename(chp) != chp) {
		errno = EINVAL;
		goto error;
	}
#endif
	if (opts & (OPT_t|OPT_p))
		chp = concat_path_file(path, chp);

	if (opts & OPT_u) {
		chp = mktemp(chp);
		if (chp[0] == '\0')
			goto error;
	} else if (opts & OPT_d) {
		if (mkdtemp(chp) == NULL)
			goto error;
	} else {
		if (mkstemp(chp) < 0)
			goto error;
	}
	puts(chp);
	return EXIT_SUCCESS;
 error:
	if (opts & OPT_q)
		return EXIT_FAILURE;
	/* don't use chp as it gets mangled in case of error */
	bb_perror_nomsg_and_die();
}
Esempio n. 5
0
int usleep_main(int argc UNUSED_PARAM, char **argv)
{
	if (!argv[1]) {
		bb_show_usage();
	}

	if (usleep(xatou(argv[1]))) {
		bb_perror_nomsg_and_die();
	}

	return EXIT_SUCCESS;
}
Esempio n. 6
0
/* if fn is NULL then input is stdin and output is stdout */
static void convert(char *fn, int conv_type)
{
	FILE *in, *out;
	int ch;
	char *temp_fn = temp_fn; /* for compiler */
	char *resolved_fn = resolved_fn;

	in = stdin;
	out = stdout;
	if (fn != NULL) {
		struct stat st;
		int fd;

		resolved_fn = xmalloc_follow_symlinks(fn);
		if (resolved_fn == NULL)
			bb_simple_perror_msg_and_die(fn);
		in = xfopen_for_read(resolved_fn);
		xfstat(fileno(in), &st, resolved_fn);

		temp_fn = xasprintf("%sXXXXXX", resolved_fn);
		fd = xmkstemp(temp_fn);
		if (fchmod(fd, st.st_mode) == -1)
			bb_simple_perror_msg_and_die(temp_fn);
		fchown(fd, st.st_uid, st.st_gid);

		out = xfdopen_for_write(fd);
	}

	while ((ch = fgetc(in)) != EOF) {
		if (ch == '\r')
			continue;
		if (ch == '\n')
			if (conv_type == CT_UNIX2DOS)
				fputc('\r', out);
		fputc(ch, out);
	}

	if (fn != NULL) {
		if (fclose(in) < 0 || fclose(out) < 0) {
			unlink(temp_fn);
			bb_perror_nomsg_and_die();
		}
		xrename(temp_fn, resolved_fn);
		free(temp_fn);
		free(resolved_fn);
	}
}
Esempio n. 7
0
int yes_main(int argc UNUSED_PARAM, char **argv)
{
	char **pp;

	argv[0] = (char*)"y";
	if (argv[1])
		++argv;

	do {
		pp = argv;
		while (1) {
			fputs(*pp, stdout);
			if (!*++pp)
				break;
			putchar(' ');
		}
	} while (putchar('\n') != EOF);

	bb_perror_nomsg_and_die();
}
extern int fdflush_main(int argc, char **argv)
{
	int fd, result;

	if (argc <= 1)
		bb_show_usage();

	fd = bb_xopen(argv[1], 0);

	result = ioctl(fd, FDFLUSH, 0);
#ifdef CONFIG_FEATURE_CLEAN_UP
	close(fd);
#endif
	if (result) {
		bb_perror_nomsg_and_die();
	}

	/* Don't bother closing.  Exit does
	 * that, so we can save a few bytes */
	return EXIT_SUCCESS;
}
Esempio n. 9
0
int yes_main(int argc, char **argv)
{
	char **first_arg;

	argv[0] = (char*)"y";
	if (argc != 1) {
		++argv;
	}

	first_arg = argv;
	do {
		while (1) {
			fputs(*argv, stdout);
			if (!*++argv)
				break;
			putchar(' ');
		}
		argv = first_arg;
	} while (putchar('\n') != EOF);

	bb_perror_nomsg_and_die();
}
Esempio n. 10
0
int yes_main(int argc, char **argv)
{
	static const char fmt_str[] = " %s";
	const char *fmt;
	char **first_arg;

	*argv = "y";
	if (argc != 1) {
		++argv;
	}

	first_arg = argv;
	do {
		fmt = fmt_str + 1;
		do {
			printf(fmt, *argv);
			fmt = fmt_str;
		} while (*++argv);
		argv = first_arg;
	} while (putchar('\n') != EOF);

	bb_perror_nomsg_and_die();
}
Esempio n. 11
0
int flock_main(int argc UNUSED_PARAM, char **argv)
{
	int mode, opt, fd;
	enum {
		OPT_s = (1 << 0),
		OPT_x = (1 << 1),
		OPT_n = (1 << 2),
		OPT_u = (1 << 3),
		OPT_c = (1 << 4),
	};

#if ENABLE_LONG_OPTS
	static const char getopt_longopts[] ALIGN1 =
		"shared\0"      No_argument       "s"
		"exclusive\0"   No_argument       "x"
		"unlock\0"      No_argument       "u"
		"nonblock\0"    No_argument       "n"
		;
	applet_long_options = getopt_longopts;
#endif
	opt_complementary = "-1";

	opt = getopt32(argv, "+sxnu");
	argv += optind;

	if (argv[1]) {
		fd = open(argv[0], O_RDONLY|O_NOCTTY|O_CREAT, 0666);
		if (fd < 0 && errno == EISDIR)
			fd = open(argv[0], O_RDONLY|O_NOCTTY);
		if (fd < 0)
			bb_perror_msg_and_die("can't open '%s'", argv[0]);
		//TODO? close_on_exec_on(fd);
	} else {
		fd = xatoi_positive(argv[0]);
	}
	argv++;

	/* If it is "flock FILE -c PROG", then -c isn't caught by getopt32:
	 * we use "+" in order to support "flock -opt FILE PROG -with-opts",
	 * we need to remove -c by hand.
	 */
	if (argv[0]
	 && argv[0][0] == '-'
	 && (  (argv[0][1] == 'c' && !argv[0][2])
	    || (ENABLE_LONG_OPTS && strcmp(argv[0] + 1, "-command") == 0)
	    )
	) {
		argv++;
		if (argv[1])
			bb_error_msg_and_die("-c takes only one argument");
		opt |= OPT_c;
	}

	if (OPT_s == LOCK_SH && OPT_x == LOCK_EX && OPT_n == LOCK_NB && OPT_u == LOCK_UN) {
		/* With suitably matched constants, mode setting is much simpler */
		mode = opt & (LOCK_SH + LOCK_EX + LOCK_NB + LOCK_UN);
		if (!(mode & ~LOCK_NB))
			mode |= LOCK_EX;
	} else {
		if (opt & OPT_u)
			mode = LOCK_UN;
		else if (opt & OPT_s)
			mode = LOCK_SH;
		else
			mode = LOCK_EX;
		if (opt & OPT_n)
			mode |= LOCK_NB;
	}

	if (flock(fd, mode) != 0) {
		if (errno == EWOULDBLOCK)
			return EXIT_FAILURE;
		bb_perror_nomsg_and_die();
	}

	if (argv[0]) {
		int rc;
		if (opt & OPT_c) {
			/* -c 'PROG ARGS' means "run sh -c 'PROG ARGS'" */
			argv -= 2;
			argv[0] = (char*)get_shell_name();
			argv[1] = (char*)"-c";
			/* argv[2] = "PROG ARGS"; */
			/* argv[3] = NULL; */
		}
		rc = spawn_and_wait(argv);
		if (rc < 0)
			bb_simple_perror_msg(argv[0]);
		return rc;
	}

	return EXIT_SUCCESS;
}
Esempio n. 12
0
static void tail_xprint_header(const char *fmt, const char *filename)
{
	if (fdprintf(STDOUT_FILENO, fmt, filename) < 0)
		bb_perror_nomsg_and_die();
}
Esempio n. 13
0
/* if fn is NULL then input is stdin and output is stdout */
static int convert(char *fn, int ConvType)
{
	int c, fd;
	FILE *in, *out;

	if (fn != NULL) {
		in = bb_xfopen(fn, "rw");
		/*
		The file is then created with mode read/write and
		permissions 0666 for glibc 2.0.6 and earlier or
		0600  for glibc  2.0.7 and  later. 
		*/
		snprintf(tempFn, sizeof(tempFn), "%sXXXXXX", fn);
		/*
		sizeof tempFn is 4096, so it should be big enough to hold the full
		path. however if the output is truncated the subsequent call to
		mkstemp would fail.
		*/
		if ((fd = mkstemp(&tempFn[0])) == -1 || chmod(tempFn, 0600) == -1) {
			bb_perror_nomsg_and_die();
		}
		out = fdopen(fd, "w+");
		if (!out) {
			close(fd);
			remove(tempFn);
		}
	} else {
		in = stdin;
		out = stdout;
	}

	while ((c = fgetc(in)) != EOF) {
		if (c == '\r')
			continue;
		if (c == '\n') {
			if (ConvType == CT_UNIX2DOS)
				fputc('\r', out);
			fputc('\n', out);
			continue;
		}
		fputc(c, out);
	}

	if (fn != NULL) {
		if (fclose(in) < 0 || fclose(out) < 0) {
			bb_perror_nomsg();
			remove(tempFn);
			return -2;
	    }
	
		/* Assume they are both on the same filesystem (which
		* should be true since we put them into the same directory
		* so we _should_ be ok, but you never know... */
		if (rename(tempFn, fn) < 0) {
			bb_perror_msg("cannot rename '%s' as '%s'", tempFn, fn);
			return -1;
	    }
	}

	return 0;
}
Esempio n. 14
0
int adduser_main(int argc UNUSED_PARAM, char **argv)
{
	struct passwd pw;
	const char *usegroup = NULL;
	FILE *file;

#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
	applet_long_options = adduser_longopts;
#endif

	/* got root? */
	if (geteuid()) {
		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
	}

	pw.pw_gecos = (char *)"Linux User,,,";
	pw.pw_shell = (char *)DEFAULT_SHELL;
	pw.pw_dir = NULL;

	/* exactly one non-option arg */
	opt_complementary = "=1";
	getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
	argv += optind;

	/* fill in the passwd struct */
	pw.pw_name = argv[0];
	die_if_bad_username(pw.pw_name);
	if (!pw.pw_dir) {
		/* create string for $HOME if not specified already */
		pw.pw_dir = xasprintf("/home/%s", argv[0]);
	}
	pw.pw_passwd = (char *)"x";
	pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */

	/* make sure everything is kosher and setup uid && maybe gid */
	passwd_study(&pw);

	/* add to passwd */
	file = xfopen(bb_path_passwd_file, "a");
	//fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
	if (putpwent(&pw, file) != 0) {
		bb_perror_nomsg_and_die();
	}
	/* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
	 * We will exec passwd, files must be flushed & closed before that! */
	fclose(file);

#if ENABLE_FEATURE_SHADOWPASSWDS
	/* add to shadow if necessary */
	file = fopen_or_warn(bb_path_shadow_file, "a");
	if (file) {
		//fseek(file, 0, SEEK_END);
		fprintf(file, "%s:!:%u:0:99999:7:::\n",
				pw.pw_name,             /* username */
				(unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
				/*0,*/                  /* sp->sp_min */
				/*99999,*/              /* sp->sp_max */
				/*7*/                   /* sp->sp_warn */
		);
		fclose(file);
	}
#endif

	/* add to group */
	/* addgroup should be responsible for dealing w/ gshadow */
	/* if using a pre-existing group, don't create one */
	if (!usegroup)
		addgroup_wrapper(&pw);

	/* Clear the umask for this process so it doesn't
	 * screw up the permissions on the mkdir and chown. */
	umask(0);
	if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
		/* Set the owner and group so it is owned by the new user,
		   then fix up the permissions to 2755. Can't do it before
		   since chown will clear the setgid bit */
		if (mkdir(pw.pw_dir, 0755)
		 || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid)
		 || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */
		) {
			bb_simple_perror_msg(pw.pw_dir);
		}
	}

	if (!(option_mask32 & OPT_DONT_SET_PASS)) {
		/* interactively set passwd */
		passwd_wrapper(pw.pw_name);
	}

	return 0;
}
Esempio n. 15
0
int pscan_main(int argc UNUSED_PARAM, char **argv)
{
	const char *opt_max_port = "1024";      /* -P: default max port */
	const char *opt_min_port = "1";         /* -p: default min port */
	const char *opt_timeout = "5000";       /* -t: default timeout in msec */
	/* We estimate rtt and wait rtt*4 before concluding that port is
	 * totally blocked. min rtt of 5 ms may be too low if you are
	 * scanning an Internet host behind saturated/traffic shaped link.
	 * Rule of thumb: with min_rtt of N msec, scanning 1000 ports
	 * will take N seconds at absolute minimum */
	const char *opt_min_rtt = "5";          /* -T: default min rtt in msec */
	const char *result_str;
	len_and_sockaddr *lsap;
	int s;
	unsigned opt;
	unsigned port, max_port, nports;
	unsigned closed_ports = 0;
	unsigned open_ports = 0;
	/* all in usec */
	unsigned timeout;
	unsigned min_rtt;
	unsigned rtt_4;
	unsigned start, diff;

	opt_complementary = "=1"; /* exactly one non-option */
	opt = getopt32(argv, "cbp:P:t:T:", &opt_min_port, &opt_max_port, &opt_timeout, &opt_min_rtt);
	argv += optind;
	max_port = xatou_range(opt_max_port, 1, 65535);
	port = xatou_range(opt_min_port, 1, max_port);
	nports = max_port - port + 1;
	min_rtt = xatou_range(opt_min_rtt, 1, INT_MAX/1000 / 4) * 1000;
	timeout = xatou_range(opt_timeout, 1, INT_MAX/1000 / 4) * 1000;
	/* Initial rtt is BIG: */
	rtt_4 = timeout;

	DMSG("min_rtt %u timeout %u", min_rtt, timeout);

	lsap = xhost2sockaddr(*argv, port);
	printf("Scanning %s ports %u to %u\n Port\tProto\tState\tService\n",
			*argv, port, max_port);

	for (; port <= max_port; port++) {
		DMSG("rtt %u", rtt_4);

		/* The SOCK_STREAM socket type is implemented on the TCP/IP protocol. */
		set_nport(&lsap->u.sa, htons(port));
		s = xsocket(lsap->u.sa.sa_family, SOCK_STREAM, 0);
		/* We need unblocking socket so we don't need to wait for ETIMEOUT. */
		/* Nonblocking connect typically "fails" with errno == EINPROGRESS */
		ndelay_on(s);

		DMSG("connect to port %u", port);
		result_str = NULL;
		start = MONOTONIC_US();
		if (connect(s, &lsap->u.sa, lsap->len) == 0) {
			/* Unlikely, for me even localhost fails :) */
			DMSG("connect succeeded");
			goto open;
		}
		/* Check for untypical errors... */
		if (errno != EAGAIN && errno != EINPROGRESS
		 && errno != ECONNREFUSED
		) {
			bb_perror_nomsg_and_die();
		}

		diff = 0;
		while (1) {
			if (errno == ECONNREFUSED) {
				if (opt & 1) /* -c: show closed too */
					result_str = "closed";
				closed_ports++;
				break;
			}
			DERR("port %u errno %d @%u", port, errno, diff);

			if (diff > rtt_4) {
				if (opt & 2) /* -b: show blocked too */
					result_str = "blocked";
				break;
			}
			/* Can sleep (much) longer than specified delay.
			 * We check rtt BEFORE we usleep, otherwise
			 * on localhost we'll have no writes done (!)
			 * before we exceed (rather small) rtt */
			usleep(rtt_4/8);
 open:
			diff = MONOTONIC_US() - start;
			DMSG("write to port %u @%u", port, diff - start);
			if (write(s, " ", 1) >= 0) { /* We were able to write to the socket */
				open_ports++;
				result_str = "open";
				break;
			}
		}
		DMSG("out of loop @%u", diff);
		if (result_str)
			printf("%5u" "\t" "tcp" "\t" "%s" "\t" "%s" "\n",
					port, result_str, port_name(port));

		/* Estimate new rtt - we don't want to wait entire timeout
		 * for each port. *4 allows for rise in net delay.
		 * We increase rtt quickly (rtt_4*4), decrease slowly
		 * (diff is at least rtt_4/8, *4 == rtt_4/2)
		 * because we don't want to accidentally miss ports. */
		rtt_4 = diff * 4;
		if (rtt_4 < min_rtt)
			rtt_4 = min_rtt;
		if (rtt_4 > timeout)
			rtt_4 = timeout;
		/* Clean up */
		close(s);
	}
	if (ENABLE_FEATURE_CLEAN_UP) free(lsap);

	printf("%u closed, %u open, %u timed out (or blocked) ports\n",
					closed_ports,
					open_ports,
					nports - (closed_ports + open_ports));
	return EXIT_SUCCESS;
}
Esempio n. 16
0
int halt_main(int argc UNUSED_PARAM, char **argv)
{
	static const int magic[] = {
		RB_HALT_SYSTEM,
		RB_POWER_OFF,
		RB_AUTOBOOT
	};
	static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };

	int delay = 0;
	int which, flags, rc;

	/* Figure out which applet we're running */
	for (which = 0; "hpr"[which] != applet_name[0]; which++)
		continue;

	/* Parse and handle arguments */
	opt_complementary = "d+"; /* -d N */
	/* We support -w even if !ENABLE_FEATURE_WTMP,
	 * in order to not break scripts.
	 * -i (shut down network interfaces) is ignored.
	 */
	flags = getopt32(argv, "d:nfwi", &delay);

	sleep(delay);

	write_wtmp();

	if (flags & 8) /* -w */
		return EXIT_SUCCESS;

	if (!(flags & 2)) /* no -n */
		sync();

	/* Perform action. */
	rc = 1;
	if (!(flags & 4)) { /* no -f */
//TODO: I tend to think that signalling linuxrc is wrong
// pity original author didn't comment on it...
		if (ENABLE_FEATURE_INITRD) {
			/* talk to linuxrc */
			/* bbox init/linuxrc assumed */
			pid_t *pidlist = find_pid_by_name("linuxrc");
			if (pidlist[0] > 0)
				rc = kill(pidlist[0], signals[which]);
			if (ENABLE_FEATURE_CLEAN_UP)
				free(pidlist);
		}
		if (rc) {
			/* talk to init */
			if (!ENABLE_FEATURE_CALL_TELINIT) {
				/* bbox init assumed */
				rc = kill(1, signals[which]);
			} else {
				/* SysV style init assumed */
				/* runlevels:
				 * 0 == shutdown
				 * 6 == reboot */
				rc = execlp(CONFIG_TELINIT_PATH,
						CONFIG_TELINIT_PATH,
						which == 2 ? "6" : "0",
						(char *)NULL
				);
			}
		}
	} else {
		rc = reboot(magic[which]);
	}

	if (rc)
		bb_perror_nomsg_and_die();
	return rc;
}
Esempio n. 17
0
int adjtimex_main(int argc UNUSED_PARAM, char **argv)
{
    enum {
        OPT_quiet = 0x1
    };
    unsigned opt;
    char *opt_o, *opt_f, *opt_p, *opt_t;
    struct timex txc;
    int i, ret;
    const char *descript;

    opt_complementary = "=0"; /* no valid non-option parameters */
    opt = getopt32(argv, "qo:f:p:t:",
                   &opt_o, &opt_f, &opt_p, &opt_t);
    txc.modes = 0;
    //if (opt & 0x1) // -q
    if (opt & 0x2) { // -o
        txc.offset = xatol(opt_o);
        txc.modes |= ADJ_OFFSET_SINGLESHOT;
    }
    if (opt & 0x4) { // -f
        txc.freq = xatol(opt_f);
        txc.modes |= ADJ_FREQUENCY;
    }
    if (opt & 0x8) { // -p
        txc.constant = xatol(opt_p);
        txc.modes |= ADJ_TIMECONST;
    }
    if (opt & 0x10) { // -t
        txc.tick = xatol(opt_t);
        txc.modes |= ADJ_TICK;
    }

    ret = adjtimex(&txc);

    if (ret < 0) {
        bb_perror_nomsg_and_die();
    }

    if (!(opt & OPT_quiet)) {
        int sep;
        const char *name;

        printf(
            "    mode:         %d\n"
            "-o  offset:       %ld\n"
            "-f  frequency:    %ld\n"
            "    maxerror:     %ld\n"
            "    esterror:     %ld\n"
            "    status:       %d (",
            txc.modes, txc.offset, txc.freq, txc.maxerror,
            txc.esterror, txc.status);

        /* representative output of next code fragment:
           "PLL | PPSTIME" */
        name = statlist_name;
        sep = 0;
        for (i = 0; statlist_bit[i]; i++) {
            if (txc.status & statlist_bit[i]) {
                if (sep)
                    fputs(" | ", stdout);
                fputs(name, stdout);
                sep = 1;
            }
            name += strlen(name) + 1;
        }

        descript = "error";
        if (ret <= 5)
            descript = nth_string(ret_code_descript, ret);
        printf(")\n"
               "-p  timeconstant: %ld\n"
               "    precision:    %ld\n"
               "    tolerance:    %ld\n"
               "-t  tick:         %ld\n"
               "    time.tv_sec:  %ld\n"
               "    time.tv_usec: %ld\n"
               "    return value: %d (%s)\n",
               txc.constant,
               txc.precision, txc.tolerance, txc.tick,
               (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript);
    }

    return 0;
}
Esempio n. 18
0
int adjtimex_main(int argc UNUSED_PARAM, char **argv)
{
	enum {
		OPT_quiet = 0x1
	};
	unsigned opt;
	char *opt_o, *opt_f, *opt_p, *opt_t;
	struct timex txc;
	int ret;
	const char *descript;

	memset(&txc, 0, sizeof(txc));

	opt = getopt32(argv, "^" "qo:f:p:t:"
			"\0" "=0"/*no valid non-option args*/,
			&opt_o, &opt_f, &opt_p, &opt_t
	);
	//if (opt & 0x1) // -q
	if (opt & 0x2) { // -o
		txc.offset = xatol(opt_o);
		txc.modes |= ADJ_OFFSET_SINGLESHOT;
	}
	if (opt & 0x4) { // -f
		txc.freq = xatol(opt_f);
		txc.modes |= ADJ_FREQUENCY;
	}
	if (opt & 0x8) { // -p
		txc.constant = xatol(opt_p);
		txc.modes |= ADJ_TIMECONST;
	}
	if (opt & 0x10) { // -t
		txc.tick = xatol(opt_t);
		txc.modes |= ADJ_TICK;
	}

	/* It's NOFORK applet because the code is very simple:
	 * just some printf. No opens, no allocs.
	 * If you need to make it more complex, feel free to downgrade to NOEXEC
	 */

	ret = adjtimex(&txc);
	if (ret < 0)
		bb_perror_nomsg_and_die();

	if (!(opt & OPT_quiet)) {
		const char *sep;
		const char *name;
		int i;

		printf(
			"    mode:         %d\n"
			"-o  offset:       %ld us\n"
			"-f  freq.adjust:  %ld (65536 = 1ppm)\n"
			"    maxerror:     %ld\n"
			"    esterror:     %ld\n"
			"    status:       %d (",
			txc.modes, txc.offset, txc.freq, txc.maxerror,
			txc.esterror, txc.status
		);

		/* representative output of next code fragment:
		 * "PLL | PPSTIME"
		 */
		name = statlist_name;
		sep = "";
		for (i = 0; statlist_bit[i]; i++) {
			if (txc.status & statlist_bit[i]) {
				printf("%s%s", sep, name);
				sep = " | ";
			}
			name += strlen(name) + 1;
		}

		descript = "error";
		if (ret <= 5)
			descript = nth_string(ret_code_descript, ret);
		printf(")\n"
			"-p  timeconstant: %ld\n"
			"    precision:    %ld us\n"
			"    tolerance:    %ld\n"
			"-t  tick:         %ld us\n"
			"    time.tv_sec:  %ld\n"
			"    time.tv_usec: %ld\n"
			"    return value: %d (%s)\n",
			txc.constant,
			txc.precision, txc.tolerance, txc.tick,
			(long)txc.time.tv_sec, (long)txc.time.tv_usec,
			ret, descript
		);
	}

	return 0;
}