예제 #1
0
std::string Process::readline() {
    std::string result;

    while (!readbufferedline(result))
    {
        ssize_t size = readchunk();

        if (size == 0)
        {
            break;
        }
    }

    return result;
}
예제 #2
0
int
main(int argc, char *argv[]) {
	char *buf;
	struct disk *disks, *dp;
	int ch, ok;
	long long minwait, nextwait;
	struct sigaction sa;
	long long counter;
	int initial_debug;
	const char *conf_file, *save_file;

	conf_file = _PATH_CONF;
	save_file = _PATH_SAVE;
	debug = 0;

	while ((ch = getopt(argc, argv, "df:o:")) != -1)
		switch (ch) {
		case 'd':
			if (debug)
				debug *= 2;
			else
				debug = 1;
			break;
		case 'f':
			conf_file = optarg;
			break;
		case 'o':
			save_file = optarg;
			break;
		default:
			usage();
			/* NOTREACHED */
		}

	argv += optind;
	argc -= optind;

	if (argc != 0)
		usage();

	initial_debug = debug;

	openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0),
		LOG_DAEMON);

	if (!debug && daemon(0, 0) < 0) {
		syslog(LOG_NOTICE, "daemon() failure: %m");
		exit(EXIT_FAILURE);
	}

	sa.sa_handler = sigterm;
	sa.sa_flags = SA_RESTART;
	sigemptyset(&sa.sa_mask);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT, &sa, NULL);

	sa.sa_handler = sighup;
	sigaction(SIGHUP, &sa, NULL);

	/* Read the configuration file and the saved offsets */
	disks = readconf(conf_file);
	readoffsets(disks, save_file);

	if ((buf = malloc(READ_SIZE)) == NULL) {
		syslog(LOG_NOTICE, "malloc failure: %m");
		exit(EXIT_FAILURE);
	}

	/* The main disk checking loop.
	 *
	 * We wait the shortest amount of time we need to before
	 * another disk is due for a read -- this time is updated
	 * in the 'nextwait' variable, which is then copied to
	 * 'minwait'.  After a sleep, 'minwait' is subtracted from
	 * each disk's 'next' field, and when that reaches zero,
	 * that disk is read again.
	 */
	counter = 0LL;
	minwait = 0LL;
	while (!got_sigterm) {
		ok = 0;
		nextwait = LLONG_MAX;
		for (dp = disks; dp->device != NULL; dp++)
			if (dp->fd != -1) {
				if (debug > 1)
					fprintf(stderr,
						"%s:  next(%qd) -= %qd\n",
						dp->device, dp->next, minwait);
				if ((dp->next -= minwait) == 0) {
					ok = 1;
					readchunk(dp, buf);
				}

				/* XXX debugging */
				if (dp->next < 0LL) {
					syslog(LOG_NOTICE,
					  "dp->next < 0 for %s", dp->device);
					abort();
				}

				if (dp->next < nextwait)
					nextwait = dp->next;
			}

		if (!ok) {
			syslog(LOG_EMERG, "all disks had read errors");
			exit(EXIT_FAILURE);
		}

		/* 300 seconds => 5 minutes */
		if (counter >= 300000000LL) {
			if (debug)
				fprintf(stderr, "counter rollover %qd => 0\n",
					counter);
			updateproctitle(disks);
			writeoffsets(disks, save_file);
			counter = 0LL;
		}

		minwait = nextwait;
		if (debug > 1) {
			--debug;
			fprintf(stderr, "sleep %qd, counter %qd\n",
				minwait, counter);
		}

		/*
		 * Handle whole seconds and usec separately to avoid overflow
		 * when calling usleep -- useconds_t is only 32 bits on at
		 * least some architectures, and minwait (being long long)
		 * may exceed INT_MAX.
		 */
		if (minwait > 1000000LL)
			sleep((unsigned int)(minwait / 1000000));
		if ((minwait % 1000000) > 0)
			usleep((useconds_t)(minwait % 1000000));
		counter += minwait;

		if (got_sighup) {
			/*
			 * Got a SIGHUP, so save the offsets, free the
			 * memory used for the disk structures, and then
			 * re-read the config file and the disk offsets.
			 */
			if (debug) {
				fprintf(stderr, "got SIGHUP, counter == %qd\n",
					counter);
				debug = initial_debug;
			}
			writeoffsets(disks, save_file);
			for (dp = disks; dp->device != NULL; dp++) {
				free(dp->device);
				close(dp->fd);
			}
			free(disks);
			disks = readconf(conf_file);
			readoffsets(disks, save_file);
			minwait = 0LL;
			got_sighup = 0;
		}
	}

	if (debug)
		fprintf(stderr, "got %s, counter == %qd\n",
			got_sigterm==SIGTERM?"SIGTERM":"SIGINT", counter);
	writeoffsets(disks, save_file);
	return (EXIT_SUCCESS);
}