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_TIMESTAMP_COMMA_GT, time_string,
sizeof(time_string)) != 0)
#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);
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);
- printf(USAGE_HELP_OPTIONS(22));
+ fprintf(out, USAGE_HELP_OPTIONS(22));
- printf(USAGE_MAN_TAIL("utmpdump(1)"));
+ fprintf(out, USAGE_MAN_TAIL("utmpdump(1)"));
exit(EXIT_SUCCESS);
}
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");