summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2015-03-13 11:13:26 +0100
committerKarel Zak <kzak@redhat.com>2015-03-13 11:24:13 +0100
commitc016a9239503e6278d8e2d276ac5ffa36f57bd3a (patch)
tree044eb606e877d5c1b7dadf75657bfe34925585f2
parentbefb2f7914a48deec108f1a046ff0fd0a065bef6 (diff)
downloadutil-linux-c016a9239503e6278d8e2d276ac5ffa36f57bd3a.tar.gz
last: fix utmplist usage
last(1) uses a global list of entries, this is unnecessary and it's also mistake because the pointer to the list is not set to NULL when last(1) opens another utmp file. For example: last -f /var/log/wtmp -f /var/log/wtmp-20150220 ends with unexpected free() call or sometimes with never ending loop. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1201033 Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--login-utils/last.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/login-utils/last.c b/login-utils/last.c
index d6d8d9624..3d9a62bee 100644
--- a/login-utils/last.c
+++ b/login-utils/last.c
@@ -107,7 +107,6 @@ struct utmplist {
struct utmplist *next;
struct utmplist *prev;
};
-struct utmplist *utmplist = NULL;
/* Types of listing */
enum {
@@ -622,8 +621,10 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut)
static void process_wtmp_file(const struct last_control *ctl)
{
FILE *fp; /* Filepointer of wtmp file */
+ char *filename;
struct utmp ut; /* Current utmp entry */
+ struct utmplist *ulist = NULL; /* All entries */
struct utmplist *p; /* Pointer into utmplist */
struct utmplist *next; /* Pointer into utmplist */
@@ -640,6 +641,7 @@ static void process_wtmp_file(const struct last_control *ctl)
time(&lastdown);
lastrch = lastdown;
+ filename = ctl->altv[ctl->alti];
/*
* Fill in 'lastdate'
@@ -655,8 +657,8 @@ static void process_wtmp_file(const struct last_control *ctl)
/*
* Open the utmp file
*/
- if ((fp = fopen(ctl->altv[ctl->alti], "r")) == NULL)
- err(EXIT_FAILURE, _("cannot open %s"), ctl->altv[ctl->alti]);
+ if ((fp = fopen(filename, "r")) == NULL)
+ err(EXIT_FAILURE, _("cannot open %s"), filename);
/*
* Optimize the buffer size.
@@ -670,7 +672,7 @@ static void process_wtmp_file(const struct last_control *ctl)
begintime = ut.UL_UT_TIME;
else {
if (fstat(fileno(fp), &st) != 0)
- err(EXIT_FAILURE, _("stat of %s failed"), ctl->altv[ctl->alti]);
+ err(EXIT_FAILURE, _("stat of %s failed"), filename);
begintime = st.st_ctime;
quit = 1;
}
@@ -787,7 +789,7 @@ static void process_wtmp_file(const struct last_control *ctl)
* the same ut_line.
*/
c = 0;
- for (p = utmplist; p; p = next) {
+ for (p = ulist; p; p = next) {
next = p->next;
if (strncmp(p->ut.ut_line, ut.ut_line,
UT_LINESIZE) == 0) {
@@ -796,11 +798,12 @@ static void process_wtmp_file(const struct last_control *ctl)
quit = list(ctl, &ut, p->ut.UL_UT_TIME, R_NORMAL);
c = 1;
}
- if (p->next) p->next->prev = p->prev;
+ if (p->next)
+ p->next->prev = p->prev;
if (p->prev)
p->prev->next = p->next;
else
- utmplist = p->next;
+ ulist = p->next;
free(p);
}
}
@@ -829,10 +832,11 @@ static void process_wtmp_file(const struct last_control *ctl)
break;
p = xmalloc(sizeof(struct utmplist));
memcpy(&p->ut, &ut, sizeof(struct utmp));
- p->next = utmplist;
+ p->next = ulist;
p->prev = NULL;
- if (utmplist) utmplist->prev = p;
- utmplist = p;
+ if (ulist)
+ ulist->prev = p;
+ ulist = p;
break;
case EMPTY:
@@ -848,23 +852,24 @@ static void process_wtmp_file(const struct last_control *ctl)
/*
* If we saw a shutdown/reboot record we can remove
- * the entire current utmplist.
+ * the entire current ulist.
*/
if (down) {
lastboot = ut.UL_UT_TIME;
whydown = (ut.ut_type == SHUTDOWN_TIME) ? R_DOWN : R_CRASH;
- for (p = utmplist; p; p = next) {
+ for (p = ulist; p; p = next) {
next = p->next;
free(p);
}
- utmplist = NULL;
+ ulist = NULL;
down = 0;
}
}
- printf(_("\n%s begins %s"), basename(ctl->altv[ctl->alti]), ctime(&begintime));
+ printf(_("\n%s begins %s"), basename(filename), ctime(&begintime));
fclose(fp);
- for (p = utmplist; p; p = next) {
+
+ for (p = ulist; p; p = next) {
next = p->next;
free(p);
}
@@ -1001,7 +1006,7 @@ int main(int argc, char **argv)
ctl.altc++;
}
- for (; ctl.alti < ctl.altc; ctl.alti++) {
+ for (ctl.alti = 0; ctl.alti < ctl.altc; ctl.alti++) {
get_boot_time(&ctl.boot_time);
process_wtmp_file(&ctl);
free(ctl.altv[ctl.alti]);