Esempio n. 1
0
File: gmcpubar.c Progetto: vmj/gmbar
static error_t
handle_option(int key, char* arg, struct argp_state *state)
{
        error_t err = 0;
        arguments* config = (arguments*) state->input;

        switch (key)
        {
        case ARGP_KEY_INIT:
                state->child_inputs[0] = config;
                break;

        case OPTION_KERN_COLOR:
                err = parse_option_arg_string(arg, &config->common_config.bar->sections[0]->color);
                break;
        case OPTION_USER_COLOR:
                err = parse_option_arg_string(arg, &config->common_config.bar->sections[1]->color);
                break;
        case OPTION_NICE_COLOR:
                err = parse_option_arg_string(arg, &config->common_config.bar->sections[2]->color);
                break;
        case OPTION_IDLE_COLOR:
                err = parse_option_arg_string(arg, &config->common_config.bar->sections[3]->color);
                break;
        case OPTION_CPU_INDEX:
                config->cpu_index = parse_unsigned_int(arg, NULL);
                break;

        default:
                err = ARGP_ERR_UNKNOWN;
                break;
        }

        return err;
}
Esempio n. 2
0
File: gmcpubar.c Progetto: vmj/gmbar
/**
 * Parse CPU field from stat.
 *
 * @param   stat      Contents of the /proc/stat file
 * @param   size      Size of the content
 * @param   field     Name of the field to parse, e.g. "cpu" or "cpu1", zero terminated
 * @param   kern      On return, contains the parsed value or zero.
 * @param   user      On return, contains the parsed value or zero.
 * @param   nice      On return, contains the parsed value or zero.
 * @param   idle      On return, contains the parsed value or zero.
 * @return  Zero on success, -1 if the field is not found.  Note that any
 * parse errors are not detected.
 */
static int
parse_stat(const char* stat,
           const unsigned int size,
           const char* field,
           unsigned int *kern,
           unsigned int *user,
           unsigned int *nice,
           unsigned int *idle)
{
        const char* p = stat;
        unsigned int len = size;

        /* Initialize to zeros */
        *kern = *user = *nice = *idle = 0;

        /* Find the field */
        do
        {
                p = memstr(p, field, len);
                if (!p)
                {
                        log_error("Field not found: %d", -1);
                        return -1;
                }
        } while (p != stat && p[-1] != '\n' && p++ && (len = size - (p - stat)));

        /* Skip the label */
        p += strlen(field);

        *user = parse_unsigned_int(p, &p);
        *nice = parse_unsigned_int(p, &p);
        *kern = parse_unsigned_int(p, &p);
        *idle = parse_unsigned_int(p, NULL);

        return 0;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
	int out_fd = -1, use_splice = 1, truncate = O_TRUNC, verboseness = 0;
	char *buf = NULL, *dev_path = DEV_PATH, *out_path = NULL;
	int restart_requested, dev_fd, pipe_in, pipe_out, pipe_fd[2];
	ssize_t n, m;
	unsigned int snaplen = 0, buflen = 8192;
	ssize_t (*read_dev)(void);
	ssize_t (*write_out)(void);
	
	struct argp_option options[] = {
		{"append", 'a', 0, 0, "append new records instead of overwriting"},
		{"device", 'd', "DEVICE", 0, "read events from DEVICE (default: " DEV_PATH ")"},
		{"buflen", 'l', "BYTES", 0, "set buffer length; implies -n (default: 8192)"},
		{"no-splice", 'n', 0, 0, "use read()/write() instead of splice"},
		{"quiet", 'q', 0, 0, "decrease verboseness of debug output"},
		{"snaplen", 's', "BYTES", 0, "set maximum packet capture size to BYTES bytes"},
		{"verbose", 'v', 0, 0, "increase verboseness of debug output"},
		{0},
	};

	error_t parse_opt(int key, char *arg, struct argp_state *state)
	{
		switch (key) {
		case 'a':
			truncate = 0;
			break;
		case 'd':
			dev_path = arg;
			break;
		case 'l':
			if (parse_unsigned_int(&buflen, arg))
				argp_error(state, "invalid buflen: %s\n", arg);
			use_splice = 0;
			break;
		case 'n':
			use_splice = 0;
			break;
		case 'q':
			verboseness--;
			break;
		case 's':
			if (parse_unsigned_int(&snaplen, arg))
				argp_error(state, "invalid snaplen: %s\n", arg);
			break;
		case 'v':
			verboseness++;
			break;
		case ARGP_KEY_ARG:
			if (!state->arg_num)
				out_path = arg;
			else
				return ARGP_ERR_UNKNOWN;
			break;
		default:
			return ARGP_ERR_UNKNOWN;
		}
		return 0;
	}

	struct argp argp = {options, parse_opt, "[OUTPUT_FILE]",
			"Read Hone events and write to a file or standard output.",
			NULL, NULL, NULL};

	if (argp_parse(&argp, argc, argv, 0, NULL, NULL))
		err(EX_OSERR, "argp_parse() failed");

	if (verboseness > 0)
		verbose1 = log_stderr;
	if (verboseness > 1)
		verbose2 = log_stderr;
	if (verboseness > 2)
		verbose3 = log_stderr;

	verbose2("Options:\n");
	verbose2("   buffer size: ");
	if (use_splice)
		verbose2("unused\n");
	else
		verbose2("%u\n", buflen);
	verbose2("   input device: %s\n", dev_path);
	verbose2("   output file: %s\n", out_path ?: "<standard output>");
	verbose2("   snaplen: %u\n", snaplen);
	verbose2("   use splice: %s\n", use_splice ? "yes" : "no");
	verbose2("   verbosity level: %d\n", verboseness);

	if (verboseness > 3)
		err(EX_USAGE, "verboseness limit exceeded");

	signal(SIGHUP, sighandler);
	signal(SIGINT, sighandler);
	signal(SIGTERM, sighandler);

	ssize_t splice_read(void)
	{
		return splice(dev_fd, NULL, pipe_in, NULL, 65536, 0);
	}

	ssize_t splice_write(void)
	{
		return splice(pipe_out, NULL, out_fd, NULL, n, 0);
	}

	ssize_t conventional_read(void)
	{
		return read(dev_fd, buf, buflen);
	}

	ssize_t conventional_write(void)
	{
		return write(out_fd, buf, n);
	}

	if (use_splice) {
		if (pipe(pipe_fd))
			err(EX_OSERR, "pipe() failed");
		pipe_out = pipe_fd[0];
		pipe_in = pipe_fd[1];
		read_dev = splice_read;
		write_out = splice_write;
	} else {
		if (!(buf = (typeof(buf)) malloc(buflen)))
			err(EX_OSERR, "malloc() failed");
		read_dev = conventional_read;
		write_out = conventional_write;
	}

	if ((dev_fd = open(dev_path, O_RDONLY, 0)) == -1)
		err(EX_NOINPUT, "open() failed on %s", dev_path);
	if (snaplen && ioctl(dev_fd, HEIO_SET_SNAPLEN, snaplen) == -1)
		err(EX_IOERR, "set snaplen ioctl() failed");

	void close_out(void)
	{
		if (close(out_fd))
			err(EX_OSERR, "close() failed on %s", out_path);
		out_fd = -1;
	}

restart:
	restart = 0;
	restart_requested = 0;

	if (out_fd != -1)
		close_out();
	if (!out_path || !strcmp(out_path, "-")) {
		if ((out_fd = dup(STDOUT_FILENO)) == -1)
			err(EX_CANTCREAT, "dup() failed on stdout");
	} else {
		if ((out_fd = open(out_path,
					O_WRONLY | O_CREAT | O_LARGEFILE | truncate, 00664)) == -1)
			err(EX_CANTCREAT, "open() failed on %s", out_path);
		if (!truncate && lseek(out_fd, 0, SEEK_END) == (off_t) -1)
			err(EX_OSERR, "error seeking to end of output file");
	}

	if (use_splice) {
		int is_fifo = 0;
		struct stat st;

		if (fstat(out_fd, &st))
			warn("fstat() failed");
		else
			is_fifo = S_ISFIFO(st.st_mode);
		pipe_in = is_fifo ? out_fd : pipe_fd[1];

		verbose2("output file is%s a FIFO\n", is_fifo ? "" : " not");
	}

	for (;;) {
		if ((restart || done) && !restart_requested) {
			if (ioctl(dev_fd, HEIO_RESTART) == -1)
				err(EX_OSERR, "reset ioctl() failed");
			verbose1("Requesting device restart.\n");
			restart_requested = 1;
		}

		if ((n = read_dev()) == -1) {
			if (errno != EINTR && errno != EAGAIN)
				err(EX_OSERR, "reading from device failed");
			continue;
		}

		if (!n) {
			verbose1("Device restarted.\n");
			if (done || ioctl(dev_fd, HEIO_GET_AT_HEAD) <= 0)
				break;
			verbose1("Reopening output file.\n");
			goto restart;
		}

		verbose3("Read %ld bytes\n", n);
		if (out_fd == pipe_in)  /* spliced directly to FIFO */
			continue;

		while (n > 0) {
			if ((m = write_out()) == -1) {
				if (errno != EINTR && errno != EAGAIN)
					err(EX_OSERR, "writing to output failed");
				continue;
			}
			verbose3("Wrote %ld bytes\n", m);
			n -= m;
		}
	}

	close_out();
	close(dev_fd);
	close(pipe_fd[0]);
	close(pipe_fd[1]);
	free(buf);

	exit(EX_OK);
}