std::string Process::readline() { std::string result; while (!readbufferedline(result)) { ssize_t size = readchunk(); if (size == 0) { break; } } return result; }
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); }