/src/samba/source3/smbd/utmp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | utmp routines |
4 | | Copyright (C) T.D.Lee@durham.ac.uk 1999 |
5 | | Heavily modified by Andrew Bartlett and Tridge, April 2001 |
6 | | |
7 | | This program is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | This program is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | GNU General Public License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "includes.h" |
22 | | #include "system/filesys.h" |
23 | | #include "smbd/smbd.h" |
24 | | |
25 | | /**************************************************************************** |
26 | | Reflect connection status in utmp/wtmp files. |
27 | | T.D.Lee@durham.ac.uk September 1999 |
28 | | |
29 | | With grateful thanks since then to many who have helped port it to |
30 | | different operating systems. The variety of OS quirks thereby |
31 | | uncovered is amazing... |
32 | | |
33 | | Hints for porting: |
34 | | o Always attempt to use programmatic interface (pututline() etc.) |
35 | | Indeed, at present only programmatic use is supported. |
36 | | o The only currently supported programmatic interface to "wtmp{,x}" |
37 | | is through "updwtmp*()" routines. |
38 | | o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable. |
39 | | o The HAVE_* items should identify supported features. |
40 | | o If at all possible, avoid "if defined(MY-OS)" constructions. |
41 | | |
42 | | OS observations and status: |
43 | | Almost every OS seems to have its own quirks. |
44 | | |
45 | | Solaris 2.x: |
46 | | Tested on 2.6 and 2.7; should be OK on other flavours. |
47 | | AIX: |
48 | | Apparently has utmpx.h but doesn't implement. |
49 | | OSF: |
50 | | Has utmpx.h, but (e.g.) no "getutmpx()". (Is this like AIX ?) |
51 | | Redhat 6: |
52 | | utmpx.h seems not to set default filenames. non-x better. |
53 | | IRIX 6.5: |
54 | | Not tested. Appears to have "x". |
55 | | HP-UX 9.x: |
56 | | Not tested. Appears to lack "x". |
57 | | HP-UX 10.x: |
58 | | Not tested. |
59 | | "updwtmp*()" routines seem absent, so no current wtmp* support. |
60 | | Has "ut_addr": probably trivial to implement (although remember |
61 | | that IPv6 is coming...). |
62 | | |
63 | | FreeBSD: |
64 | | No "putut*()" type of interface. |
65 | | No "ut_type" and associated defines. |
66 | | Write files directly. Alternatively use its login(3)/logout(3). |
67 | | SunOS 4: |
68 | | Not tested. Resembles FreeBSD, but no login()/logout(). |
69 | | |
70 | | lastlog: |
71 | | Should "lastlog" files, if any, be updated? |
72 | | BSD systems (SunOS 4, FreeBSD): |
73 | | o Prominent mention on man pages. |
74 | | System-V (e.g. Solaris 2): |
75 | | o No mention on man pages, even under "man -k". |
76 | | o Has a "/var/adm/lastlog" file, but pututxline() etc. seem |
77 | | not to touch it. |
78 | | o Despite downplaying (above), nevertheless has <lastlog.h>. |
79 | | So perhaps UN*X "lastlog" facility is intended for tty/terminal only? |
80 | | |
81 | | Notes: |
82 | | Each connection requires a small number (starting at 0, working up) |
83 | | to represent the line. This must be unique within and across all |
84 | | smbd processes. It is the 'id_num' from Samba's session.c code. |
85 | | |
86 | | The 4 byte 'ut_id' component is vital to distinguish connections, |
87 | | of which there could be several hundred or even thousand. |
88 | | Entries seem to be printable characters, with optional NULL pads. |
89 | | |
90 | | We need to be distinct from other entries in utmp/wtmp. |
91 | | |
92 | | Observed things: therefore avoid them. Add to this list please. |
93 | | From Solaris 2.x (because that's what I have): |
94 | | 'sN' : run-levels; N: [0-9] |
95 | | 'co' : console |
96 | | 'CC' : arbitrary things; C: [a-z] |
97 | | 'rXNN' : rlogin; N: [0-9]; X: [0-9a-z] |
98 | | 'tXNN' : rlogin; N: [0-9]; X: [0-9a-z] |
99 | | '/NNN' : Solaris CDE |
100 | | 'ftpZ' : ftp (Z is the number 255, aka 0377, aka 0xff) |
101 | | Mostly a record uses the same 'ut_id' in both "utmp" and "wtmp", |
102 | | but differences have been seen. |
103 | | |
104 | | Arbitrarily I have chosen to use a distinctive 'SM' for the |
105 | | first two bytes. |
106 | | |
107 | | The remaining two bytes encode the session 'id_num' (see above). |
108 | | Our caller (session.c) should note our 16-bit limitation. |
109 | | |
110 | | ****************************************************************************/ |
111 | | |
112 | | #ifndef WITH_UTMP |
113 | | /* |
114 | | * Not WITH_UTMP? Simply supply dummy routines. |
115 | | */ |
116 | | |
117 | | void sys_utmp_claim(const char *username, const char *hostname, |
118 | | const char *id_str, int id_num) |
119 | | {} |
120 | | |
121 | | void sys_utmp_yield(const char *username, const char *hostname, |
122 | | const char *id_str, int id_num) |
123 | | {} |
124 | | |
125 | | #else /* WITH_UTMP */ |
126 | | |
127 | | #ifdef HAVE_UTMP_H |
128 | | #include <utmp.h> |
129 | | #endif |
130 | | |
131 | | #ifdef HAVE_UTMPX_H |
132 | | #include <utmpx.h> |
133 | | #endif |
134 | | |
135 | | /* BSD systems: some may need lastlog.h (SunOS 4), some may not (FreeBSD) */ |
136 | | /* Some System-V systems (e.g. Solaris 2) declare this too. */ |
137 | | #ifdef HAVE_LASTLOG_H |
138 | | #include <lastlog.h> |
139 | | #endif |
140 | | |
141 | | /**************************************************************************** |
142 | | Default paths to various {u,w}tmp{,x} files. |
143 | | ****************************************************************************/ |
144 | | |
145 | | #ifdef HAVE_UTMPX_H |
146 | | |
147 | | static const char * const ux_pathname = |
148 | | # if defined (UTMPX_FILE) |
149 | | UTMPX_FILE ; |
150 | | # elif defined (_UTMPX_FILE) |
151 | | _UTMPX_FILE ; |
152 | | # elif defined (_PATH_UTMPX) |
153 | | _PATH_UTMPX ; |
154 | | # else |
155 | | "" ; |
156 | | # endif |
157 | | |
158 | | static const char * const wx_pathname = |
159 | | # if defined (WTMPX_FILE) |
160 | | WTMPX_FILE ; |
161 | | # elif defined (_WTMPX_FILE) |
162 | | _WTMPX_FILE ; |
163 | | # elif defined (_PATH_WTMPX) |
164 | | _PATH_WTMPX ; |
165 | | # else |
166 | | "" ; |
167 | | # endif |
168 | | |
169 | | #endif /* HAVE_UTMPX_H */ |
170 | | |
171 | | static const char * const ut_pathname = |
172 | | # if defined (UTMP_FILE) |
173 | | UTMP_FILE ; |
174 | | # elif defined (_UTMP_FILE) |
175 | | _UTMP_FILE ; |
176 | | # elif defined (_PATH_UTMP) |
177 | | _PATH_UTMP ; |
178 | | # else |
179 | | "" ; |
180 | | # endif |
181 | | |
182 | | static const char * const wt_pathname = |
183 | | # if defined (WTMP_FILE) |
184 | | WTMP_FILE ; |
185 | | # elif defined (_WTMP_FILE) |
186 | | _WTMP_FILE ; |
187 | | # elif defined (_PATH_WTMP) |
188 | | _PATH_WTMP ; |
189 | | # else |
190 | | "" ; |
191 | | # endif |
192 | | |
193 | | /* BSD-like systems might want "lastlog" support. */ |
194 | | #if 0 /* *** Not yet implemented */ |
195 | | #ifndef HAVE_PUTUTLINE /* see "pututline_my()" */ |
196 | | static const char *ll_pathname = |
197 | | # if defined (_PATH_LASTLOG) /* what other names (if any?) */ |
198 | | _PATH_LASTLOG ; |
199 | | # else |
200 | | "" ; |
201 | | # endif /* _PATH_LASTLOG */ |
202 | | #endif /* HAVE_PUTUTLINE */ |
203 | | #endif |
204 | | |
205 | | /* |
206 | | * Get name of {u,w}tmp{,x} file. |
207 | | * return: fname contains filename |
208 | | * Possibly empty if this code not yet ported to this system. |
209 | | * |
210 | | * utmp{,x}: try "utmp dir", then default (a define) |
211 | | * wtmp{,x}: try "wtmp dir", then "utmp dir", then default (a define) |
212 | | */ |
213 | | static char *uw_pathname(TALLOC_CTX *ctx, |
214 | | const char *uw_name, |
215 | | const char *uw_default) |
216 | 0 | { |
217 | 0 | char *dirname = NULL; |
218 | | |
219 | | /* For w-files, first look for explicit "wtmp dir" */ |
220 | 0 | if (uw_name[0] == 'w') { |
221 | 0 | dirname = talloc_strdup(ctx, lp_wtmp_directory()); |
222 | 0 | if (!dirname) { |
223 | 0 | return NULL; |
224 | 0 | } |
225 | 0 | trim_char(dirname,'\0','/'); |
226 | 0 | } |
227 | | |
228 | | /* For u-files and non-explicit w-dir, look for "utmp dir" */ |
229 | 0 | if ((dirname == NULL) || (strlen(dirname) == 0)) { |
230 | 0 | dirname = talloc_strdup(ctx, lp_utmp_directory()); |
231 | 0 | if (!dirname) { |
232 | 0 | return NULL; |
233 | 0 | } |
234 | 0 | trim_char(dirname,'\0','/'); |
235 | 0 | } |
236 | | |
237 | | /* If explicit directory above, use it */ |
238 | 0 | if (dirname && strlen(dirname) != 0) { |
239 | 0 | return talloc_asprintf(ctx, |
240 | 0 | "%s/%s", |
241 | 0 | dirname, |
242 | 0 | uw_name); |
243 | 0 | } |
244 | | |
245 | | /* No explicit directory: attempt to use default paths */ |
246 | 0 | if (strlen(uw_default) == 0) { |
247 | | /* No explicit setting, no known default. |
248 | | * Has it yet been ported to this OS? |
249 | | */ |
250 | 0 | DEBUG(2,("uw_pathname: unable to determine pathname\n")); |
251 | 0 | } |
252 | 0 | return talloc_strdup(ctx, uw_default); |
253 | 0 | } |
254 | | |
255 | | #ifndef HAVE_PUTUTLINE |
256 | | /**************************************************************************** |
257 | | Update utmp file directly. No subroutine interface: probably a BSD system. |
258 | | ****************************************************************************/ |
259 | | |
260 | | static void pututline_my(const char *uname, struct utmp *u, bool claim) |
261 | | { |
262 | | DEBUG(1,("pututline_my: not yet implemented\n")); |
263 | | /* BSD implementor: may want to consider (or not) adjusting "lastlog" */ |
264 | | } |
265 | | #endif /* HAVE_PUTUTLINE */ |
266 | | |
267 | | #ifndef HAVE_UPDWTMP |
268 | | |
269 | | /**************************************************************************** |
270 | | Update wtmp file directly. No subroutine interface: probably a BSD system. |
271 | | Credit: Michail Vidiassov <master@iaas.msu.ru> |
272 | | ****************************************************************************/ |
273 | | |
274 | | static void updwtmp_my(const char *wname, struct utmp *u, bool claim) |
275 | | { |
276 | | int fd; |
277 | | struct stat buf; |
278 | | |
279 | | if (! claim) { |
280 | | /* |
281 | | * BSD-like systems: |
282 | | * may use empty ut_name to distinguish a logout record. |
283 | | * |
284 | | * May need "if defined(SUNOS4)" etc. around some of these, |
285 | | * but try to avoid if possible. |
286 | | * |
287 | | * SunOS 4: |
288 | | * man page indicates ut_name and ut_host both NULL |
289 | | * FreeBSD 4.0: |
290 | | * man page appears not to specify (hints non-NULL) |
291 | | * A correspondent suggest at least ut_name should be NULL |
292 | | */ |
293 | | #if defined(HAVE_UT_UT_NAME) |
294 | | memset((char *)&u->ut_name, '\0', sizeof(u->ut_name)); |
295 | | #endif |
296 | | #if defined(HAVE_UT_UT_HOST) |
297 | | memset((char *)&u->ut_host, '\0', sizeof(u->ut_host)); |
298 | | #endif |
299 | | } |
300 | | /* Stolen from logwtmp function in libutil. |
301 | | * May be more locking/blocking is needed? |
302 | | */ |
303 | | if ((fd = open(wname, O_WRONLY|O_APPEND, 0)) < 0) |
304 | | return; |
305 | | if (fstat(fd, &buf) == 0) { |
306 | | if (write(fd, (char *)u, sizeof(struct utmp)) != sizeof(struct utmp)) |
307 | | (void) ftruncate(fd, buf.st_size); |
308 | | } |
309 | | (void) close(fd); |
310 | | } |
311 | | #endif /* HAVE_UPDWTMP */ |
312 | | |
313 | | /**************************************************************************** |
314 | | Update via utmp/wtmp (not utmpx/wtmpx). |
315 | | ****************************************************************************/ |
316 | | |
317 | | static void utmp_nox_update(struct utmp *u, bool claim) |
318 | 0 | { |
319 | 0 | char *uname = NULL; |
320 | 0 | char *wname = NULL; |
321 | 0 | #if defined(PUTUTLINE_RETURNS_UTMP) |
322 | 0 | struct utmp *urc; |
323 | 0 | #endif /* PUTUTLINE_RETURNS_UTMP */ |
324 | |
|
325 | 0 | uname = uw_pathname(talloc_tos(), "utmp", ut_pathname); |
326 | 0 | if (!uname) { |
327 | 0 | return; |
328 | 0 | } |
329 | 0 | DEBUG(2,("utmp_nox_update: uname:%s\n", uname)); |
330 | |
|
331 | 0 | #ifdef HAVE_PUTUTLINE |
332 | 0 | if (strlen(uname) != 0) { |
333 | 0 | utmpname(uname); |
334 | 0 | } |
335 | |
|
336 | 0 | # if defined(PUTUTLINE_RETURNS_UTMP) |
337 | 0 | setutent(); |
338 | 0 | urc = pututline(u); |
339 | 0 | endutent(); |
340 | 0 | if (urc == NULL) { |
341 | 0 | DEBUG(2,("utmp_nox_update: pututline() failed\n")); |
342 | 0 | return; |
343 | 0 | } |
344 | | # else /* PUTUTLINE_RETURNS_UTMP */ |
345 | | setutent(); |
346 | | pututline(u); |
347 | | endutent(); |
348 | | # endif /* PUTUTLINE_RETURNS_UTMP */ |
349 | | |
350 | | #else /* HAVE_PUTUTLINE */ |
351 | | if (strlen(uname) != 0) { |
352 | | pututline_my(uname, u, claim); |
353 | | } |
354 | | #endif /* HAVE_PUTUTLINE */ |
355 | | |
356 | 0 | wname = uw_pathname(talloc_tos(), "wtmp", wt_pathname); |
357 | 0 | if (!wname) { |
358 | 0 | return; |
359 | 0 | } |
360 | 0 | DEBUG(2,("utmp_nox_update: wname:%s\n", wname)); |
361 | 0 | if (strlen(wname) != 0) { |
362 | 0 | #ifdef HAVE_UPDWTMP |
363 | 0 | updwtmp(wname, u); |
364 | | /* |
365 | | * updwtmp() and the newer updwtmpx() may be unsymmetrical. |
366 | | * At least one OS, Solaris 2.x declares the former in the |
367 | | * "utmpx" (latter) file and context. |
368 | | * In the Solaris case this is irrelevant: it has both and |
369 | | * we always prefer the "x" case, so doesn't come here. |
370 | | * But are there other systems, with no "x", which lack |
371 | | * updwtmp() perhaps? |
372 | | */ |
373 | | #else |
374 | | updwtmp_my(wname, u, claim); |
375 | | #endif /* HAVE_UPDWTMP */ |
376 | 0 | } |
377 | 0 | } |
378 | | |
379 | | /**************************************************************************** |
380 | | Copy a string in the utmp structure. |
381 | | ****************************************************************************/ |
382 | | |
383 | | static void utmp_strcpy(char *dest, const char *src, size_t n) |
384 | 0 | { |
385 | 0 | size_t len = 0; |
386 | |
|
387 | 0 | memset(dest, '\0', n); |
388 | 0 | if (src) |
389 | 0 | len = strlen(src); |
390 | 0 | if (len >= n) { |
391 | 0 | memcpy(dest, src, n); |
392 | 0 | } else { |
393 | 0 | if (len) |
394 | 0 | memcpy(dest, src, len); |
395 | 0 | } |
396 | 0 | } |
397 | | |
398 | | /**************************************************************************** |
399 | | Update via utmpx/wtmpx (preferred) or via utmp/wtmp. |
400 | | ****************************************************************************/ |
401 | | |
402 | | static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim) |
403 | 0 | { |
404 | | #if !defined(HAVE_UTMPX_H) |
405 | | /* No utmpx stuff. Drop to non-x stuff */ |
406 | | utmp_nox_update(u, claim); |
407 | | #elif !defined(HAVE_PUTUTXLINE) |
408 | | /* Odd. Have utmpx.h but no "pututxline()". Drop to non-x stuff */ |
409 | | DEBUG(1,("utmp_update: have utmpx.h but no pututxline() function\n")); |
410 | | utmp_nox_update(u, claim); |
411 | | #elif !defined(HAVE_GETUTMPX) |
412 | | /* Odd. Have utmpx.h but no "getutmpx()". Drop to non-x stuff */ |
413 | | DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); |
414 | | utmp_nox_update(u, claim); |
415 | | #elif !defined(HAVE_UPDWTMPX) |
416 | | /* Have utmpx.h but no "updwtmpx()". Drop to non-x stuff */ |
417 | | DEBUG(1,("utmp_update: have utmpx.h but no updwtmpx() function\n")); |
418 | | utmp_nox_update(u, claim); |
419 | | #else |
420 | 0 | char *uname = NULL; |
421 | 0 | char *wname = NULL; |
422 | 0 | struct utmpx ux, *uxrc; |
423 | |
|
424 | 0 | getutmpx(u, &ux); |
425 | |
|
426 | | #if defined(HAVE_UX_UT_SYSLEN) |
427 | | if (hostname) |
428 | | ux.ut_syslen = strlen(hostname) + 1; /* include end NULL */ |
429 | | else |
430 | | ux.ut_syslen = 0; |
431 | | #endif |
432 | 0 | #if defined(HAVE_UX_UT_HOST) |
433 | 0 | utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)); |
434 | 0 | #endif |
435 | |
|
436 | 0 | uname = uw_pathname(talloc_tos(), "utmpx", ux_pathname); |
437 | 0 | wname = uw_pathname(talloc_tos(), "wtmpx", wx_pathname); |
438 | 0 | if (uname && wname) { |
439 | 0 | DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname)); |
440 | 0 | } |
441 | | |
442 | | /* |
443 | | * Check for either uname or wname being empty. |
444 | | * Some systems, such as Redhat 6, have a "utmpx.h" which doesn't |
445 | | * define default filenames. |
446 | | * Also, our local installation has not provided an override. |
447 | | * Drop to non-x method. (E.g. RH6 has good defaults in "utmp.h".) |
448 | | */ |
449 | 0 | if (!uname || !wname || (strlen(uname) == 0) || (strlen(wname) == 0)) { |
450 | 0 | utmp_nox_update(u, claim); |
451 | 0 | } else { |
452 | 0 | utmpxname(uname); |
453 | 0 | setutxent(); |
454 | 0 | uxrc = pututxline(&ux); |
455 | 0 | endutxent(); |
456 | 0 | if (uxrc == NULL) { |
457 | 0 | DEBUG(2,("utmp_update: pututxline() failed\n")); |
458 | 0 | return; |
459 | 0 | } |
460 | 0 | updwtmpx(wname, &ux); |
461 | 0 | } |
462 | 0 | #endif /* HAVE_UTMPX_H */ |
463 | 0 | } |
464 | | |
465 | | #if defined(HAVE_UT_UT_ID) |
466 | | /**************************************************************************** |
467 | | Encode the unique connection number into "ut_id". |
468 | | ****************************************************************************/ |
469 | | |
470 | | static int ut_id_encode(int i, char *fourbyte) |
471 | 0 | { |
472 | 0 | int nbase; |
473 | 0 | const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
474 | | |
475 | | /* |
476 | | * 'ut_id_encstr' is the character set on which modulo arithmetic is done. |
477 | | * Example: digits would produce the base-10 numbers from '001'. |
478 | | */ |
479 | 0 | nbase = strlen(ut_id_encstr); |
480 | |
|
481 | 0 | fourbyte[0] = ut_id_encstr[i % nbase]; |
482 | 0 | i /= nbase; |
483 | 0 | fourbyte[1] = ut_id_encstr[i % nbase]; |
484 | 0 | i /= nbase; |
485 | 0 | fourbyte[3] = ut_id_encstr[i % nbase]; |
486 | 0 | i /= nbase; |
487 | 0 | fourbyte[2] = ut_id_encstr[i % nbase]; |
488 | 0 | i /= nbase; |
489 | | |
490 | | /* we do not care about overflows as i is a random number */ |
491 | 0 | return 0; |
492 | 0 | } |
493 | | #endif /* defined(HAVE_UT_UT_ID) */ |
494 | | |
495 | | |
496 | | /* |
497 | | fill a system utmp structure given all the info we can gather |
498 | | */ |
499 | | static bool sys_utmp_fill(struct utmp *u, |
500 | | const char *username, const char *hostname, |
501 | | const char *id_str, int id_num) |
502 | 0 | { |
503 | 0 | struct timeval timeval; |
504 | | |
505 | | /* |
506 | | * ut_name, ut_user: |
507 | | * Several (all?) systems seems to define one as the other. |
508 | | * It is easier and clearer simply to let the following take its course, |
509 | | * rather than to try to detect and optimise. |
510 | | */ |
511 | 0 | #if defined(HAVE_UT_UT_USER) |
512 | 0 | utmp_strcpy(u->ut_user, username, sizeof(u->ut_user)); |
513 | | #elif defined(HAVE_UT_UT_NAME) |
514 | | utmp_strcpy(u->ut_name, username, sizeof(u->ut_name)); |
515 | | #endif |
516 | | |
517 | | /* |
518 | | * ut_line: |
519 | | * If size limit proves troublesome, then perhaps use "ut_id_encode()". |
520 | | */ |
521 | 0 | utmp_strcpy(u->ut_line, id_str, sizeof(u->ut_line)); |
522 | |
|
523 | 0 | #if defined(HAVE_UT_UT_PID) |
524 | 0 | u->ut_pid = getpid(); |
525 | 0 | #endif |
526 | | |
527 | | /* |
528 | | * ut_time, ut_tv: |
529 | | * Some have one, some the other. Many have both, but defined (aliased). |
530 | | * It is easier and clearer simply to let the following take its course. |
531 | | * But note that we do the more precise ut_tv as the final assignment. |
532 | | */ |
533 | 0 | #if defined(HAVE_UT_UT_TIME) |
534 | 0 | GetTimeOfDay(&timeval); |
535 | 0 | u->ut_time = timeval.tv_sec; |
536 | | #elif defined(HAVE_UT_UT_TV) |
537 | | GetTimeOfDay(&timeval); |
538 | | u->ut_tv = timeval; |
539 | | #else |
540 | | #error "with-utmp must have UT_TIME or UT_TV" |
541 | | #endif |
542 | |
|
543 | 0 | #if defined(HAVE_UT_UT_HOST) |
544 | 0 | utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host)); |
545 | 0 | #endif |
546 | |
|
547 | 0 | #if defined(HAVE_UT_UT_ID) |
548 | 0 | if (ut_id_encode(id_num, u->ut_id) != 0) { |
549 | 0 | DEBUG(1,("utmp_fill: cannot encode id %d\n", id_num)); |
550 | 0 | return False; |
551 | 0 | } |
552 | 0 | #endif |
553 | | |
554 | 0 | return True; |
555 | 0 | } |
556 | | |
557 | | /**************************************************************************** |
558 | | Close a connection. |
559 | | ****************************************************************************/ |
560 | | |
561 | | void sys_utmp_yield(const char *username, const char *hostname, |
562 | | const char *id_str, int id_num) |
563 | 0 | { |
564 | 0 | struct utmp u; |
565 | |
|
566 | 0 | ZERO_STRUCT(u); |
567 | |
|
568 | 0 | #if defined(HAVE_UT_UT_EXIT) |
569 | 0 | u.ut_exit.e_termination = 0; |
570 | 0 | u.ut_exit.e_exit = 0; |
571 | 0 | #endif |
572 | |
|
573 | 0 | #if defined(HAVE_UT_UT_TYPE) |
574 | 0 | u.ut_type = DEAD_PROCESS; |
575 | 0 | #endif |
576 | |
|
577 | 0 | if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) |
578 | 0 | return; |
579 | | |
580 | 0 | sys_utmp_update(&u, NULL, False); |
581 | 0 | } |
582 | | |
583 | | /**************************************************************************** |
584 | | Claim a entry in whatever utmp system the OS uses. |
585 | | ****************************************************************************/ |
586 | | |
587 | | void sys_utmp_claim(const char *username, const char *hostname, |
588 | | const char *id_str, int id_num) |
589 | 0 | { |
590 | 0 | struct utmp u; |
591 | |
|
592 | 0 | ZERO_STRUCT(u); |
593 | |
|
594 | 0 | #if defined(HAVE_UT_UT_TYPE) |
595 | 0 | u.ut_type = USER_PROCESS; |
596 | 0 | #endif |
597 | |
|
598 | 0 | if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) |
599 | 0 | return; |
600 | | |
601 | 0 | sys_utmp_update(&u, hostname, True); |
602 | 0 | } |
603 | | |
604 | | #endif /* WITH_UTMP */ |