static suseconds_t strtousec(const char *s_time)
{
const char *s = strchr(s_time, ',');
- if (s)
- return (suseconds_t) atoi(s + 1);
+
+ if (s && *++s) {
+ suseconds_t us;
+ char *end = NULL;
+
+ errno = 0;
+ us = strtol(s, &end, 10);
+ if (errno == 0 && end && end > s)
+ return us;
+ }
return 0;
}
addr_string = inet_ntop(AF_INET, &(ut->ut_addr_v6), buffer, sizeof(buffer));
tv.tv_sec = ut->ut_tv.tv_sec;
- tv.tv_usec = ut->ut_tv.tv_usec;
+ tv.tv_usec = ut->ut_tv.tv_usec < (int32_t) USEC_PER_SEC ? ut->ut_tv.tv_usec : 0;
- if (strtimeval_iso(&tv,
- ISO_8601_DATE | ISO_8601_TIME | ISO_8601_COMMAUSEC |
- ISO_8601_TIMEZONE | ISO_8601_GMTIME, time_string,
+ if (strtimeval_iso(&tv, ISO_TIMESTAMP_COMMA_GT, time_string,
sizeof(time_string)) != 0)
return;
cleanse(ut->ut_id);
size = ftello(in);
fclose(in);
+ if (size < 0)
+ err(EXIT_FAILURE, _("%s: cannot get file position"), filename);
+
wd = inotify_add_watch(fd, filename, EVENTS);
if (wd == -1)
err(EXIT_FAILURE, _("%s: cannot add inotify watch."), filename);
#ifdef HAVE_INOTIFY_INIT
if (follow_by_inotify(in, filename, out) == 0)
return NULL; /* file already closed */
- else
#endif
- /* fallback for systems without inotify or with non-free
- * inotify instances */
- for (;;) {
- while (fread(&ut, sizeof(ut), 1, in) == 1)
- print_utline(&ut, out);
- sleep(1);
- }
+ /* fallback for systems without inotify or with non-free
+ * inotify instances */
+ for (;;) {
+ while (fread(&ut, sizeof(ut), 1, in) == 1)
+ print_utline(&ut, out);
+ sleep(1);
+ }
return in;
}
static void undump(FILE *in, FILE *out)
{
struct utmpx ut;
- char s_addr[INET6_ADDRSTRLEN + 1], s_time[29], *linestart, *line;
+ char s_addr[INET6_ADDRSTRLEN + 1], s_time[29] = {}, *linestart, *line;
linestart = xmalloc(1024 * sizeof(*linestart));
s_time[28] = 0;
while (fgets(linestart, 1023, in)) {
line = linestart;
memset(&ut, '\0', sizeof(ut));
- sscanf(line, "[%hd] [%d] [%4c] ", &ut.ut_type, &ut.ut_pid, ut.ut_id);
+
+ if (sscanf(line, "[%hd] [%d] [%4c] ",
+ &ut.ut_type, &ut.ut_pid, ut.ut_id) != 3) {
+ warnx(_("parse error: %s"), line);
+ continue;
+ }
line += 19;
line += gettok(line, ut.ut_user, sizeof(ut.ut_user), 1);
free(linestart);
}
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static void __attribute__((__noreturn__)) usage(void)
{
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out,
fputs(_(" -f, --follow output appended data as the file grows\n"), out);
fputs(_(" -r, --reverse write back dumped data into utmp file\n"), out);
fputs(_(" -o, --output <file> write to file instead of standard output\n"), out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_HELP_OPTIONS(22));
fprintf(out, USAGE_MAN_TAIL("utmpdump(1)"));
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
int main(int argc, char **argv)
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
while ((c = getopt_long(argc, argv, "fro:hV", longopts, NULL)) != -1) {
switch (c) {
break;
case 'h':
- usage(stdout);
- break;
+ usage();
case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
+ print_version(EXIT_SUCCESS);
default:
errtryhelp(EXIT_FAILURE);
}
if (!out)
out = stdout;
+ if (follow && (out != stdout || !isatty(STDOUT_FILENO))) {
+ setvbuf(out, NULL, _IOLBF, 0);
+ }
+
if (optind < argc) {
filename = argv[optind];
in = fopen(filename, "r");