|
1 This patch was submitted upstream by Jens Elkner, who reported it on #pkg5; |
|
2 it was accepted after the 5.3.1 release. |
|
3 |
|
4 --- zsh-5.0.7/Src/watch.c.orig Thu Jul 31 20:41:49 2014 |
|
5 +++ zsh-5.0.7/Src/watch.c Wed Jan 11 16:37:49 2017 |
|
6 @@ -87,6 +87,9 @@ |
|
7 |
|
8 #if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMPX) && defined(REAL_UTMPX_FILE) |
|
9 # define WATCH_STRUCT_UTMP struct utmpx |
|
10 +# define setutent setutxent |
|
11 +# define getutent getutxent |
|
12 +# define endutent endutxent |
|
13 /* |
|
14 * In utmpx, the ut_name field is replaced by ut_user. |
|
15 * Howver, on some systems ut_name may already be defined this |
|
16 @@ -141,9 +144,9 @@ |
|
17 # define WATCH_WTMP_FILE "/dev/null" |
|
18 # endif |
|
19 |
|
20 -static int wtabsz; |
|
21 -static WATCH_STRUCT_UTMP *wtab; |
|
22 -static time_t lastutmpcheck; |
|
23 +static int wtabsz = 0; |
|
24 +static WATCH_STRUCT_UTMP *wtab = NULL; |
|
25 +static time_t lastutmpcheck = 0; |
|
26 |
|
27 /* get the time of login/logout for WATCH */ |
|
28 |
|
29 @@ -449,34 +452,44 @@ |
|
30 /* initialize the user List */ |
|
31 |
|
32 /**/ |
|
33 -static void |
|
34 -readwtab(void) |
|
35 +static int |
|
36 +readwtab(WATCH_STRUCT_UTMP **head, int initial_sz) |
|
37 { |
|
38 - WATCH_STRUCT_UTMP *uptr; |
|
39 - int wtabmax = 32; |
|
40 - FILE *in; |
|
41 + WATCH_STRUCT_UTMP *uptr, *tmp; |
|
42 + int wtabmax = initial_sz < 2 ? 32 : initial_sz; |
|
43 + int sz = 0; |
|
44 |
|
45 - wtabsz = 0; |
|
46 - if (!(in = fopen(WATCH_UTMP_FILE, "r"))) |
|
47 - return; |
|
48 - uptr = wtab = (WATCH_STRUCT_UTMP *)zalloc(wtabmax * sizeof(WATCH_STRUCT_UTMP)); |
|
49 - while (fread(uptr, sizeof(WATCH_STRUCT_UTMP), 1, in)) |
|
50 + |
|
51 + uptr = *head = (WATCH_STRUCT_UTMP *)zalloc(wtabmax * sizeof(WATCH_STRUCT_UTMP)); |
|
52 + setutent(); |
|
53 + while ((tmp = getutent()) != NULL) |
|
54 # ifdef USER_PROCESS |
|
55 - if (uptr->ut_type == USER_PROCESS) |
|
56 + if (tmp->ut_type == USER_PROCESS) |
|
57 # else /* !USER_PROCESS */ |
|
58 - if (uptr->ut_name[0]) |
|
59 + if (tmp->ut_name[0]) |
|
60 # endif /* !USER_PROCESS */ |
|
61 { |
|
62 + memcpy(uptr, tmp, sizeof (WATCH_STRUCT_UTMP)); |
|
63 uptr++; |
|
64 - if (++wtabsz == wtabmax) |
|
65 - uptr = (wtab = (WATCH_STRUCT_UTMP *)realloc((void *) wtab, (wtabmax *= 2) * |
|
66 - sizeof(WATCH_STRUCT_UTMP))) + wtabsz; |
|
67 + if (++sz == wtabmax) { |
|
68 + uptr = (WATCH_STRUCT_UTMP *) |
|
69 + realloc(*head, (wtabmax *= 2) * sizeof(WATCH_STRUCT_UTMP)); |
|
70 + if (uptr == NULL) { |
|
71 + /* memory pressure - so stop consuming and use, what we have |
|
72 + * Other option is to exit() here, as zmalloc does on error */ |
|
73 + sz--; |
|
74 + break; |
|
75 + } |
|
76 + *head = uptr; |
|
77 + uptr += sz; |
|
78 + } |
|
79 } |
|
80 - fclose(in); |
|
81 + endutent(); |
|
82 |
|
83 - if (wtabsz) |
|
84 - qsort((void *) wtab, wtabsz, sizeof(WATCH_STRUCT_UTMP), |
|
85 + if (sz) |
|
86 + qsort((void *) *head, sz, sizeof(WATCH_STRUCT_UTMP), |
|
87 (int (*) _((const void *, const void *)))ucmp); |
|
88 + return sz; |
|
89 } |
|
90 |
|
91 /* Check for login/logout events; executed before * |
|
92 @@ -486,55 +499,28 @@ |
|
93 void |
|
94 dowatch(void) |
|
95 { |
|
96 - FILE *in; |
|
97 WATCH_STRUCT_UTMP *utab, *uptr, *wptr; |
|
98 struct stat st; |
|
99 char **s; |
|
100 char *fmt; |
|
101 - int utabsz = 0, utabmax = wtabsz + 4; |
|
102 - int uct, wct; |
|
103 + int utabsz, uct, wct; |
|
104 |
|
105 s = watch; |
|
106 |
|
107 holdintr(); |
|
108 - if (!wtab) { |
|
109 - readwtab(); |
|
110 - noholdintr(); |
|
111 - return; |
|
112 - } |
|
113 + if (!wtab) |
|
114 + wtabsz = readwtab(&wtab, 32); |
|
115 if ((stat(WATCH_UTMP_FILE, &st) == -1) || (st.st_mtime <= lastutmpcheck)) { |
|
116 noholdintr(); |
|
117 return; |
|
118 } |
|
119 lastutmpcheck = st.st_mtime; |
|
120 - uptr = utab = (WATCH_STRUCT_UTMP *) zalloc(utabmax * sizeof(WATCH_STRUCT_UTMP)); |
|
121 - |
|
122 - if (!(in = fopen(WATCH_UTMP_FILE, "r"))) { |
|
123 - free(utab); |
|
124 - noholdintr(); |
|
125 - return; |
|
126 - } |
|
127 - while (fread(uptr, sizeof *uptr, 1, in)) |
|
128 -# ifdef USER_PROCESS |
|
129 - if (uptr->ut_type == USER_PROCESS) |
|
130 -# else /* !USER_PROCESS */ |
|
131 - if (uptr->ut_name[0]) |
|
132 -# endif /* !USER_PROCESS */ |
|
133 - { |
|
134 - uptr++; |
|
135 - if (++utabsz == utabmax) |
|
136 - uptr = (utab = (WATCH_STRUCT_UTMP *)realloc((void *) utab, (utabmax *= 2) * |
|
137 - sizeof(WATCH_STRUCT_UTMP))) + utabsz; |
|
138 - } |
|
139 - fclose(in); |
|
140 + utabsz = readwtab(&utab, wtabsz + 4); |
|
141 noholdintr(); |
|
142 if (errflag) { |
|
143 free(utab); |
|
144 return; |
|
145 } |
|
146 - if (utabsz) |
|
147 - qsort((void *) utab, utabsz, sizeof(WATCH_STRUCT_UTMP), |
|
148 - (int (*) _((const void *, const void *)))ucmp); |
|
149 |
|
150 wct = wtabsz; |
|
151 uct = utabsz; |