sessreg.c revision 1e5fa1c5
1a6d9b409Smrg/* 2a6d9b409Smrg * Copyright 1990, 1998 The Open Group 3a6d9b409Smrg * 4a6d9b409Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5a6d9b409Smrg * documentation for any purpose is hereby granted without fee, provided that 6a6d9b409Smrg * the above copyright notice appear in all copies and that both that 7a6d9b409Smrg * copyright notice and this permission notice appear in supporting 8a6d9b409Smrg * documentation. 9a6d9b409Smrg * 10a6d9b409Smrg * The above copyright notice and this permission notice shall be included 11a6d9b409Smrg * in all copies or substantial portions of the Software. 12a6d9b409Smrg * 13a6d9b409Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14a6d9b409Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15a6d9b409Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16a6d9b409Smrg * IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 17a6d9b409Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18a6d9b409Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19a6d9b409Smrg * OTHER DEALINGS IN THE SOFTWARE. 20a6d9b409Smrg * 21a6d9b409Smrg * Except as contained in this notice, the name of The Open Group shall 22a6d9b409Smrg * not be used in advertising or otherwise to promote the sale, use or 23a6d9b409Smrg * other dealings in this Software without prior written authorization 24a6d9b409Smrg * from The Open Group. 25a6d9b409Smrg * 26a6d9b409Smrg */ 27a6d9b409Smrg 28a6d9b409Smrg/* Copyright 2005 Sun Microsystems, Inc. All rights reserved. 29a6d9b409Smrg * 30a6d9b409Smrg * Permission is hereby granted, free of charge, to any person obtaining a 311e5fa1c5Smrg * copy of this software and associated documentation files (the "Software"), 321e5fa1c5Smrg * to deal in the Software without restriction, including without limitation 331e5fa1c5Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 341e5fa1c5Smrg * and/or sell copies of the Software, and to permit persons to whom the 351e5fa1c5Smrg * Software is furnished to do so, subject to the following conditions: 361e5fa1c5Smrg * 371e5fa1c5Smrg * The above copyright notice and this permission notice (including the next 381e5fa1c5Smrg * paragraph) shall be included in all copies or substantial portions of the 391e5fa1c5Smrg * Software. 401e5fa1c5Smrg * 411e5fa1c5Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 421e5fa1c5Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 431e5fa1c5Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 441e5fa1c5Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 451e5fa1c5Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 461e5fa1c5Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 471e5fa1c5Smrg * DEALINGS IN THE SOFTWARE. 48a6d9b409Smrg */ 49a6d9b409Smrg 50a6d9b409Smrg/* 51a6d9b409Smrg * Author: Keith Packard, MIT X Consortium 52a6d9b409Smrg * Lastlog support and dynamic utmp entry allocation 53a6d9b409Smrg * by Andreas Stolcke <stolcke@icsi.berkeley.edu> 54a6d9b409Smrg */ 55a6d9b409Smrg 56a6d9b409Smrg/* 57a6d9b409Smrg * sessreg 58a6d9b409Smrg * 59a6d9b409Smrg * simple wtmp/utmp frobber 60a6d9b409Smrg * 61a6d9b409Smrg * usage: sessreg [ -w <wtmp-file> ] [ -u <utmp-file> ] 62a6d9b409Smrg * [ -l <line> ] 63efda2da8Smrg * [ -L <lastlog-file> ] / #ifndef NO_LASTLOG 64a6d9b409Smrg * [ -h <host-name> ] / BSD only 65a6d9b409Smrg * [ -s <slot-number> ] [ -x Xservers-file ] / BSD only 66a6d9b409Smrg * [ -t <ttys-file> ] / BSD only 67a6d9b409Smrg * [ -a ] [ -d ] user-name 68a6d9b409Smrg * 69a6d9b409Smrg * one of -a or -d must be specified 70a6d9b409Smrg */ 71a6d9b409Smrg 72a6d9b409Smrg#include "sessreg.h" 73a6d9b409Smrg 74a6d9b409Smrg# include <X11/Xos.h> 75a6d9b409Smrg# include <X11/Xfuncs.h> 76a6d9b409Smrg# include <stdio.h> 77a6d9b409Smrg# include <stdlib.h> 78a6d9b409Smrg 79a6d9b409Smrg#if defined(__SVR4) || defined(SVR4) || defined(linux) || defined(__GLIBC__) 80a6d9b409Smrg# define SYSV 81a6d9b409Smrg#endif 82a6d9b409Smrg 83a6d9b409Smrg#include <time.h> 84a6d9b409Smrg#define Time_t time_t 85a6d9b409Smrg 861e5fa1c5Smrg#ifdef USE_UTMP 871e5fa1c5Smrgstatic void set_utmp (struct utmp *u, char *line, char *user, char *host, 881e5fa1c5Smrg Time_t date, int addp); 891e5fa1c5Smrg#endif 90a6d9b409Smrg 91a6d9b409Smrg#ifdef USE_UTMPX 92a6d9b409Smrgstatic void set_utmpx (struct utmpx *u, const char *line, const char *user, 93a6d9b409Smrg const char *host, Time_t date, int addp); 94a6d9b409Smrg#endif 95a6d9b409Smrg 96efda2da8Smrgstatic int wflag, uflag, lflag; 97efda2da8Smrgstatic char *wtmp_file, *utmp_file, *line; 98a6d9b409Smrg#ifdef USE_UTMPX 991e5fa1c5Smrg#ifdef HAVE_UPDWTMPX 1001e5fa1c5Smrgstatic char *wtmpx_file = NULL; 1011e5fa1c5Smrg#endif 1021e5fa1c5Smrg#ifdef HAVE_UTMPXNAME 1031e5fa1c5Smrgstatic char *utmpx_file = NULL; 1041e5fa1c5Smrg#endif 105a6d9b409Smrg#endif 106efda2da8Smrgstatic int utmp_none, wtmp_none; 107a6d9b409Smrg/* 108a6d9b409Smrg * BSD specific variables. To make life much easier for Xstartup/Xreset 109a6d9b409Smrg * maintainers, these arguments are accepted but ignored for sysV 110a6d9b409Smrg */ 111efda2da8Smrgstatic int hflag, sflag, xflag, tflag; 112efda2da8Smrgstatic char *host_name = NULL; 1131e5fa1c5Smrg#ifdef USE_UTMP 114efda2da8Smrgstatic int slot_number; 1151e5fa1c5Smrg#endif 116efda2da8Smrgstatic char *xservers_file, *ttys_file; 117efda2da8Smrgstatic char *user_name; 118efda2da8Smrgstatic int aflag, dflag; 119a6d9b409Smrg#ifndef NO_LASTLOG 120efda2da8Smrgstatic char *llog_file; 121efda2da8Smrgstatic int llog_none, Lflag; 122a6d9b409Smrg#endif 123a6d9b409Smrg 124efda2da8Smrgstatic char *program_name; 125a6d9b409Smrg 126a6d9b409Smrg#ifndef SYSV 127a6d9b409Smrgstatic int findslot (char *line_name, char *host_name, int addp, int slot); 128a6d9b409Smrgstatic int Xslot (char *ttys_file, char *servers_file, char *tty_line, 129a6d9b409Smrg char *host_name, int addp); 130a6d9b409Smrg#endif 131a6d9b409Smrg 132a6d9b409Smrgstatic int 133a6d9b409Smrgusage (int x) 134a6d9b409Smrg{ 135a6d9b409Smrg if (x) { 136a6d9b409Smrg fprintf (stderr, "%s: usage %s {-a -d} [-w wtmp-file] [-u utmp-file]", program_name, program_name); 137a6d9b409Smrg#ifndef NO_LASTLOG 138a6d9b409Smrg fprintf (stderr, " [-L lastlog-file]"); 139a6d9b409Smrg#endif 140a6d9b409Smrg fprintf (stderr, "\n"); 141a6d9b409Smrg fprintf (stderr, " [-t ttys-file] [-l line-name] [-h host-name]\n"); 142a6d9b409Smrg fprintf (stderr, " [-s slot-number] [-x servers-file] user-name\n"); 143a6d9b409Smrg exit (1); 144a6d9b409Smrg } 145a6d9b409Smrg return x; 146a6d9b409Smrg} 147a6d9b409Smrg 148a6d9b409Smrgstatic char * 149a6d9b409Smrggetstring (char ***avp, int *flagp) 150a6d9b409Smrg{ 151a6d9b409Smrg char **a = *avp; 152a6d9b409Smrg 153a6d9b409Smrg usage ((*flagp)++); 154a6d9b409Smrg if (*++*a) 155a6d9b409Smrg return *a; 156a6d9b409Smrg ++a; 157a6d9b409Smrg usage (!*a); 158a6d9b409Smrg *avp = a; 159a6d9b409Smrg return *a; 160a6d9b409Smrg} 161a6d9b409Smrg 162a6d9b409Smrg#ifndef SYSV 163a6d9b409Smrgstatic int 164a6d9b409Smrgsyserr (int x, const char *s) 165a6d9b409Smrg{ 166a6d9b409Smrg if (x == -1) { 167a6d9b409Smrg perror (s); 168a6d9b409Smrg exit (1); 169a6d9b409Smrg } 170a6d9b409Smrg return x; 171a6d9b409Smrg} 172a6d9b409Smrg#endif 173a6d9b409Smrg 174a6d9b409Smrgstatic int 175a6d9b409Smrgsysnerr (int x, const char *s) 176a6d9b409Smrg{ 177a6d9b409Smrg if (x == 0) { 178a6d9b409Smrg perror (s); 179a6d9b409Smrg exit (1); 180a6d9b409Smrg } 181a6d9b409Smrg return x; 182a6d9b409Smrg} 183a6d9b409Smrg 184a6d9b409Smrgint 185a6d9b409Smrgmain (int argc, char **argv) 186a6d9b409Smrg{ 1871e5fa1c5Smrg#if defined(USE_UTMP) && !defined(SYSV) 188a6d9b409Smrg int utmp; 189a6d9b409Smrg#endif 190a6d9b409Smrg char *line_tmp; 191a6d9b409Smrg#ifndef USE_UTMPX 192a6d9b409Smrg int wtmp; 193a6d9b409Smrg#endif 194a6d9b409Smrg Time_t current_time; 1951e5fa1c5Smrg#ifdef USE_UTMP 196a6d9b409Smrg struct utmp utmp_entry; 1971e5fa1c5Smrg#endif 198a6d9b409Smrg#ifdef USE_UTMPX 199a6d9b409Smrg struct utmpx utmpx_entry; 200a6d9b409Smrg#endif 201a6d9b409Smrg 202a6d9b409Smrg program_name = argv[0]; 203a6d9b409Smrg while (*++argv && **argv == '-') { 204a6d9b409Smrg switch (*++*argv) { 205a6d9b409Smrg case 'w': 206a6d9b409Smrg wtmp_file = getstring (&argv, &wflag); 207a6d9b409Smrg if (!strcmp (wtmp_file, "none")) 208a6d9b409Smrg wtmp_none = 1; 209a6d9b409Smrg break; 210a6d9b409Smrg case 'u': 211a6d9b409Smrg utmp_file = getstring (&argv, &uflag); 212a6d9b409Smrg if (!strcmp (utmp_file, "none")) 213a6d9b409Smrg utmp_none = 1; 214a6d9b409Smrg break; 215a6d9b409Smrg#ifndef NO_LASTLOG 216a6d9b409Smrg case 'L': 217a6d9b409Smrg llog_file = getstring (&argv, &Lflag); 218a6d9b409Smrg if (!strcmp (llog_file, "none")) 219a6d9b409Smrg llog_none = 1; 220a6d9b409Smrg break; 221a6d9b409Smrg#endif 222a6d9b409Smrg case 't': 223a6d9b409Smrg ttys_file = getstring (&argv, &tflag); 224a6d9b409Smrg break; 225a6d9b409Smrg case 'l': 226a6d9b409Smrg line = getstring (&argv, &lflag); 227a6d9b409Smrg break; 228a6d9b409Smrg case 'h': 229a6d9b409Smrg host_name = getstring (&argv, &hflag); 230a6d9b409Smrg break; 231a6d9b409Smrg case 's': 2321e5fa1c5Smrg#ifdef USE_UTMP 233a6d9b409Smrg slot_number = atoi (getstring (&argv, &sflag)); 2341e5fa1c5Smrg#endif 235a6d9b409Smrg break; 236a6d9b409Smrg case 'x': 237a6d9b409Smrg xservers_file = getstring (&argv, &xflag); 238a6d9b409Smrg break; 239a6d9b409Smrg case 'a': 240a6d9b409Smrg aflag++; 241a6d9b409Smrg break; 242a6d9b409Smrg case 'd': 243a6d9b409Smrg dflag++; 244a6d9b409Smrg break; 245a6d9b409Smrg default: 246a6d9b409Smrg usage (1); 247a6d9b409Smrg } 248a6d9b409Smrg } 249a6d9b409Smrg usage (!(user_name = *argv++)); 250efda2da8Smrg usage (*argv != NULL); 251a6d9b409Smrg /* 252a6d9b409Smrg * complain if neither aflag nor dflag are set, 253a6d9b409Smrg * or if both are set. 254a6d9b409Smrg */ 255a6d9b409Smrg usage (!(aflag ^ dflag)); 256a6d9b409Smrg usage (xflag && !lflag); 257a6d9b409Smrg /* set up default file names */ 258a6d9b409Smrg if (!wflag) { 259a6d9b409Smrg wtmp_file = WTMP_FILE; 2601e5fa1c5Smrg#if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX) 261a6d9b409Smrg wtmpx_file = WTMPX_FILE; 262a6d9b409Smrg#endif 263a6d9b409Smrg } 264a6d9b409Smrg#ifndef NO_UTMP 265a6d9b409Smrg if (!uflag) { 266a6d9b409Smrg utmp_file = UTMP_FILE; 2671e5fa1c5Smrg#if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME) 268a6d9b409Smrg utmpx_file = UTMPX_FILE; 269a6d9b409Smrg#endif 270a6d9b409Smrg } 271a6d9b409Smrg#else 272a6d9b409Smrg utmp_none = 1; 273a6d9b409Smrg#endif 274a6d9b409Smrg#ifndef NO_LASTLOG 275a6d9b409Smrg if (!Lflag) 276a6d9b409Smrg llog_file = LLOG_FILE; 277a6d9b409Smrg#endif 2781e5fa1c5Smrg#if defined(USE_UTMP) && !defined(SYSV) && !defined(linux) && !defined(__QNX__) 279a6d9b409Smrg if (!tflag) 280a6d9b409Smrg ttys_file = TTYS_FILE; 281a6d9b409Smrg if (!sflag && !utmp_none) { 282a6d9b409Smrg if (xflag) 283a6d9b409Smrg sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot"); 284a6d9b409Smrg else 285a6d9b409Smrg sysnerr (slot_number = ttyslot (), "ttyslot"); 286a6d9b409Smrg } 287a6d9b409Smrg#endif 288a6d9b409Smrg if (!lflag) { 289a6d9b409Smrg sysnerr ((line_tmp = ttyname (0)) != NULL, "ttyname"); 290a6d9b409Smrg line = strrchr(line_tmp, '/'); 291a6d9b409Smrg if (line) 292a6d9b409Smrg line = line + 1; 293a6d9b409Smrg else 294a6d9b409Smrg line = line_tmp; 295a6d9b409Smrg } 296a6d9b409Smrg time (¤t_time); 2971e5fa1c5Smrg#ifdef USE_UTMP 298a6d9b409Smrg set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag); 2991e5fa1c5Smrg#endif 300a6d9b409Smrg 301a6d9b409Smrg#ifdef USE_UTMPX 302a6d9b409Smrg /* need to set utmpxname() before calling set_utmpx() for 303a6d9b409Smrg UtmpxIdOpen to work */ 3041e5fa1c5Smrg# ifdef HAVE_UTMPXNAME 305a6d9b409Smrg if (utmpx_file != NULL) { 306a6d9b409Smrg utmpxname (utmpx_file); 307a6d9b409Smrg } 3081e5fa1c5Smrg# endif 309a6d9b409Smrg set_utmpx (&utmpx_entry, line, user_name, 310a6d9b409Smrg host_name, current_time, aflag); 311a6d9b409Smrg#endif 312a6d9b409Smrg 313a6d9b409Smrg if (!utmp_none) { 314a6d9b409Smrg#ifdef USE_UTMPX 3151e5fa1c5Smrg# ifdef HAVE_UTMPX_NAME 3161e5fa1c5Smrg if (utmpx_file != NULL) 3171e5fa1c5Smrg# endif 3181e5fa1c5Smrg { 319a6d9b409Smrg setutxent (); 320a6d9b409Smrg (void) getutxid (&utmpx_entry); 321a6d9b409Smrg pututxline (&utmpx_entry); 322a6d9b409Smrg endutxent (); 323a6d9b409Smrg } 324a6d9b409Smrg#endif 3251e5fa1c5Smrg#ifdef USE_UTMP 3261e5fa1c5Smrg# ifdef SYSV 327a6d9b409Smrg utmpname (utmp_file); 328a6d9b409Smrg setutent (); 329a6d9b409Smrg (void) getutid (&utmp_entry); 330a6d9b409Smrg pututline (&utmp_entry); 331a6d9b409Smrg endutent (); 3321e5fa1c5Smrg# else 333a6d9b409Smrg utmp = open (utmp_file, O_RDWR); 334a6d9b409Smrg if (utmp != -1) { 335a6d9b409Smrg syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek"); 336a6d9b409Smrg sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry)) 337a6d9b409Smrg == sizeof (utmp_entry), "write utmp entry"); 338a6d9b409Smrg close (utmp); 339a6d9b409Smrg } 3401e5fa1c5Smrg# endif 3411e5fa1c5Smrg#endif /* USE_UTMP */ 342a6d9b409Smrg } 343a6d9b409Smrg if (!wtmp_none) { 344a6d9b409Smrg#ifdef USE_UTMPX 3451e5fa1c5Smrg# ifdef HAVE_UPDWTMPX 346a6d9b409Smrg if (wtmpx_file != NULL) { 347a6d9b409Smrg updwtmpx(wtmpx_file, &utmpx_entry); 348a6d9b409Smrg } 3491e5fa1c5Smrg# endif 350a6d9b409Smrg#else 351a6d9b409Smrg wtmp = open (wtmp_file, O_WRONLY|O_APPEND); 352a6d9b409Smrg if (wtmp != -1) { 353a6d9b409Smrg sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry)) 354a6d9b409Smrg == sizeof (utmp_entry), "write wtmp entry"); 355a6d9b409Smrg close (wtmp); 356a6d9b409Smrg } 357a6d9b409Smrg#endif 358a6d9b409Smrg } 359a6d9b409Smrg#ifndef NO_LASTLOG 360a6d9b409Smrg if (aflag && !llog_none) { 361a6d9b409Smrg int llog; 362a6d9b409Smrg struct passwd *pwd = getpwnam(user_name); 363a6d9b409Smrg 364a6d9b409Smrg sysnerr( pwd != NULL, "get user id"); 365a6d9b409Smrg llog = open (llog_file, O_RDWR); 366a6d9b409Smrg 367a6d9b409Smrg if (llog != -1) { 368a6d9b409Smrg struct lastlog ll; 369a6d9b409Smrg 370a6d9b409Smrg sysnerr (lseek(llog, (long) pwd->pw_uid*sizeof(ll), 0) 371a6d9b409Smrg != -1, "seeking lastlog entry"); 372a6d9b409Smrg bzero((char *)&ll, sizeof(ll)); 373a6d9b409Smrg ll.ll_time = current_time; 374a6d9b409Smrg if (line) 375a6d9b409Smrg (void) strncpy (ll.ll_line, line, sizeof (ll.ll_line)); 376a6d9b409Smrg if (host_name) 377a6d9b409Smrg (void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host)); 378a6d9b409Smrg 379a6d9b409Smrg sysnerr (write (llog, (char *) &ll, sizeof (ll)) 380a6d9b409Smrg == sizeof (ll), "write lastlog entry"); 381a6d9b409Smrg close (llog); 382a6d9b409Smrg } 383a6d9b409Smrg } 384a6d9b409Smrg#endif 385a6d9b409Smrg return 0; 386a6d9b409Smrg} 387a6d9b409Smrg 388a6d9b409Smrg/* 389a6d9b409Smrg * fill in the appropriate records of the utmp entry 390a6d9b409Smrg */ 391a6d9b409Smrg 3921e5fa1c5Smrg#ifdef USE_UTMP 393a6d9b409Smrgstatic void 394a6d9b409Smrgset_utmp (struct utmp *u, char *line, char *user, char *host, Time_t date, int addp) 395a6d9b409Smrg{ 396a6d9b409Smrg bzero (u, sizeof (*u)); 397a6d9b409Smrg if (line) 398a6d9b409Smrg (void) strncpy (u->ut_line, line, sizeof (u->ut_line)); 399a6d9b409Smrg else 400a6d9b409Smrg bzero (u->ut_line, sizeof (u->ut_line)); 401a6d9b409Smrg if (addp && user) 402a6d9b409Smrg (void) strncpy (u->ut_name, user, sizeof (u->ut_name)); 403a6d9b409Smrg else 404a6d9b409Smrg bzero (u->ut_name, sizeof (u->ut_name)); 405a6d9b409Smrg#ifdef SYSV 406a6d9b409Smrg if (line) { 407a6d9b409Smrg int i; 408a6d9b409Smrg /* 409a6d9b409Smrg * this is a bit crufty, but 410a6d9b409Smrg * follows the apparent conventions in 411a6d9b409Smrg * the ttys file. ut_id is only 4 bytes 412a6d9b409Smrg * long, and the last 4 bytes of the line 413a6d9b409Smrg * name are written into it, left justified. 414a6d9b409Smrg */ 415a6d9b409Smrg i = strlen (line); 416a6d9b409Smrg if (i >= sizeof (u->ut_id)) 417a6d9b409Smrg i -= sizeof (u->ut_id); 418a6d9b409Smrg else 419a6d9b409Smrg i = 0; 420a6d9b409Smrg (void) strncpy (u->ut_id, line + i, sizeof (u->ut_id)); 421a6d9b409Smrg } else 422a6d9b409Smrg bzero (u->ut_id, sizeof (u->ut_id)); 423a6d9b409Smrg if (addp) { 424a6d9b409Smrg u->ut_pid = getppid (); 425a6d9b409Smrg u->ut_type = USER_PROCESS; 426a6d9b409Smrg } else { 427a6d9b409Smrg u->ut_pid = 0; 428a6d9b409Smrg u->ut_type = DEAD_PROCESS; 429a6d9b409Smrg } 430a6d9b409Smrg#endif 431a6d9b409Smrg#if (!defined(SYSV) && !defined(__QNX__)) || defined(linux) 432a6d9b409Smrg if (addp && host) 433a6d9b409Smrg (void) strncpy (u->ut_host, host, sizeof (u->ut_host)); 434a6d9b409Smrg else 435a6d9b409Smrg bzero (u->ut_host, sizeof (u->ut_host)); 436a6d9b409Smrg#endif 437a6d9b409Smrg u->ut_time = date; 438a6d9b409Smrg} 4391e5fa1c5Smrg#endif /* USE_UTMP */ 440a6d9b409Smrg 441a6d9b409Smrg#ifdef USE_UTMPX 442a6d9b409Smrgstatic int 443a6d9b409SmrgUtmpxIdOpen( char *utmpId ) 444a6d9b409Smrg{ 445a6d9b409Smrg struct utmpx *u; /* pointer to entry in utmp file */ 446a6d9b409Smrg int status = 1; /* return code */ 4471e5fa1c5Smrg 4481e5fa1c5Smrg setutxent(); 449a6d9b409Smrg 450a6d9b409Smrg while ( (u = getutxent()) != NULL ) { 451a6d9b409Smrg 452a6d9b409Smrg if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) && 453a6d9b409Smrg u->ut_type != DEAD_PROCESS ) { 454a6d9b409Smrg 455a6d9b409Smrg status = 0; 456a6d9b409Smrg break; 457a6d9b409Smrg } 458a6d9b409Smrg } 459a6d9b409Smrg 4601e5fa1c5Smrg endutxent(); 461a6d9b409Smrg return (status); 462a6d9b409Smrg} 463a6d9b409Smrg 464a6d9b409Smrgstatic void 465a6d9b409Smrgset_utmpx (struct utmpx *u, const char *line, const char *user, 466a6d9b409Smrg const char *host, Time_t date, int addp) 467a6d9b409Smrg{ 468a6d9b409Smrg static const char letters[] = 469a6d9b409Smrg "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 470a6d9b409Smrg 471a6d9b409Smrg if (line) 472a6d9b409Smrg { 473a6d9b409Smrg if(strcmp(line, ":0") == 0) 474a6d9b409Smrg (void) strcpy(u->ut_line, "console"); 475a6d9b409Smrg else 476a6d9b409Smrg (void) strncpy (u->ut_line, line, sizeof (u->ut_line)); 477a6d9b409Smrg 478a6d9b409Smrg strncpy(u->ut_host, line, sizeof(u->ut_host)); 4791e5fa1c5Smrg#if HAVE_UTMPX_UT_SYSLEN 480a6d9b409Smrg u->ut_syslen = strlen(line); 4811e5fa1c5Smrg#endif 482a6d9b409Smrg } 483a6d9b409Smrg else 484a6d9b409Smrg bzero (u->ut_line, sizeof (u->ut_line)); 485a6d9b409Smrg if (addp && user) 4861e5fa1c5Smrg (void) strncpy (u->ut_user, user, sizeof (u->ut_user)); 487a6d9b409Smrg else 4881e5fa1c5Smrg bzero (u->ut_user, sizeof (u->ut_user)); 489a6d9b409Smrg 490a6d9b409Smrg if (line) { 491a6d9b409Smrg int i; 492a6d9b409Smrg /* 493a6d9b409Smrg * this is a bit crufty, but 494a6d9b409Smrg * follows the apparent conventions in 495a6d9b409Smrg * the ttys file. ut_id is only 4 bytes 496a6d9b409Smrg * long, and the last 4 bytes of the line 497a6d9b409Smrg * name are written into it, left justified. 498a6d9b409Smrg */ 499a6d9b409Smrg i = strlen (line); 500a6d9b409Smrg if (i >= sizeof (u->ut_id)) 501a6d9b409Smrg i -= sizeof (u->ut_id); 502a6d9b409Smrg else 503a6d9b409Smrg i = 0; 504a6d9b409Smrg (void) strncpy (u->ut_id, line + i, sizeof (u->ut_id)); 505a6d9b409Smrg 506a6d9b409Smrg /* make sure there is no entry using identical ut_id */ 507a6d9b409Smrg if (!UtmpxIdOpen(u->ut_id) && addp) { 508a6d9b409Smrg int limit = sizeof(letters) - 1; 509a6d9b409Smrg int t = 0; 510a6d9b409Smrg 511a6d9b409Smrg u->ut_id[1] = line[i]; 512a6d9b409Smrg u->ut_id[2] = line[i+1]; 513a6d9b409Smrg u->ut_id[3] = line[i+2]; 514a6d9b409Smrg do { 515a6d9b409Smrg u->ut_id[0] = letters[t]; 516a6d9b409Smrg t++; 517a6d9b409Smrg } while (!UtmpxIdOpen(u->ut_id) && (t < limit)); 518a6d9b409Smrg } 519a6d9b409Smrg if (!addp && strstr(line, ":") != NULL) { 520a6d9b409Smrg struct utmpx *tmpu; 521a6d9b409Smrg 522a6d9b409Smrg while ( (tmpu = getutxent()) != NULL ) { 523a6d9b409Smrg if ( (strcmp(tmpu->ut_host, line) == 0 ) && 524a6d9b409Smrg tmpu->ut_type != DEAD_PROCESS ) { 525a6d9b409Smrg strncpy(u->ut_id, tmpu->ut_id, 526a6d9b409Smrg sizeof(u->ut_id)); 527a6d9b409Smrg break; 528a6d9b409Smrg } 529a6d9b409Smrg } 530a6d9b409Smrg endutxent(); 531a6d9b409Smrg } 532a6d9b409Smrg } else 533a6d9b409Smrg bzero (u->ut_id, sizeof (u->ut_id)); 534a6d9b409Smrg 535a6d9b409Smrg if (addp) { 536a6d9b409Smrg u->ut_pid = getppid (); 537a6d9b409Smrg u->ut_type = USER_PROCESS; 538a6d9b409Smrg } else { 539a6d9b409Smrg u->ut_pid = 0; 540a6d9b409Smrg u->ut_type = DEAD_PROCESS; 541a6d9b409Smrg } 542a6d9b409Smrg u->ut_tv.tv_sec = date; 543a6d9b409Smrg u->ut_tv.tv_usec = 0; 544a6d9b409Smrg} 545a6d9b409Smrg#endif /* USE_UTMPX */ 546a6d9b409Smrg 5471e5fa1c5Smrg#if defined(USE_UTMP) && !defined(SYSV) 548a6d9b409Smrg/* 549a6d9b409Smrg * compute the slot-number for an X display. This is computed 550a6d9b409Smrg * by counting the lines in /etc/ttys and adding the line-number 551a6d9b409Smrg * that the display appears on in Xservers. This is a poor 552a6d9b409Smrg * design, but is limited by the non-existant interface to utmp. 553a6d9b409Smrg * If host_name is non-NULL, assume it contains the display name, 554a6d9b409Smrg * otherwise use the tty_line argument (i.e., the tty name). 555a6d9b409Smrg */ 556a6d9b409Smrg 557a6d9b409Smrgstatic int 558a6d9b409SmrgXslot (char *ttys_file, char *servers_file, char *tty_line, char *host_name, 559a6d9b409Smrg int addp) 560a6d9b409Smrg{ 561a6d9b409Smrg FILE *ttys, *servers; 562a6d9b409Smrg int c; 563a6d9b409Smrg int slot = 1; 564a6d9b409Smrg int column0 = 1; 565a6d9b409Smrg char servers_line[1024]; 566a6d9b409Smrg char disp_name[512]; 567a6d9b409Smrg int len; 568a6d9b409Smrg char *pos; 569a6d9b409Smrg 570a6d9b409Smrg /* remove screen number from the display name */ 571a6d9b409Smrg memset(disp_name, 0, sizeof(disp_name)); 572a6d9b409Smrg strncpy(disp_name, host_name ? host_name : tty_line, sizeof(disp_name)-1); 573a6d9b409Smrg pos = strrchr(disp_name, ':'); 574a6d9b409Smrg if (pos) { 575a6d9b409Smrg pos = strchr(pos, '.'); 576a6d9b409Smrg if (pos) 577a6d9b409Smrg *pos = '\0'; 578a6d9b409Smrg } 579a6d9b409Smrg sysnerr ((int)(long)(ttys = fopen (ttys_file, "r")), ttys_file); 580a6d9b409Smrg while ((c = getc (ttys)) != EOF) 581a6d9b409Smrg if (c == '\n') { 582a6d9b409Smrg ++slot; 583a6d9b409Smrg column0 = 1; 584a6d9b409Smrg } else 585a6d9b409Smrg column0 = 0; 586a6d9b409Smrg if (!column0) 587a6d9b409Smrg ++slot; 588a6d9b409Smrg (void) fclose (ttys); 589a6d9b409Smrg sysnerr ((int)(long)(servers = fopen (servers_file, "r")), servers_file); 590a6d9b409Smrg 591a6d9b409Smrg len = strlen (disp_name); 592a6d9b409Smrg column0 = 1; 593a6d9b409Smrg while (fgets (servers_line, sizeof (servers_line), servers)) { 594a6d9b409Smrg if (column0 && *servers_line != '#') { 595a6d9b409Smrg if (!strncmp (disp_name, servers_line, len) && 596a6d9b409Smrg (servers_line[len] == ' ' || 597a6d9b409Smrg servers_line[len] == '\t')) 598a6d9b409Smrg return slot; 599a6d9b409Smrg ++slot; 600a6d9b409Smrg } 601a6d9b409Smrg if (servers_line[strlen(servers_line)-1] != '\n') 602a6d9b409Smrg column0 = 0; 603a6d9b409Smrg else 604a6d9b409Smrg column0 = 1; 605a6d9b409Smrg } 606a6d9b409Smrg /* 607a6d9b409Smrg * display not found in Xservers file - allocate utmp entry dinamically 608a6d9b409Smrg */ 609a6d9b409Smrg return findslot (tty_line, host_name, addp, slot); 610a6d9b409Smrg} 611a6d9b409Smrg 612a6d9b409Smrg/* 613a6d9b409Smrg * find a free utmp slot for the X display. This allocates a new entry 614a6d9b409Smrg * past the regular tty entries if necessary, reusing existing entries 615a6d9b409Smrg * (identified by (line,hostname)) if possible. 616a6d9b409Smrg */ 617a6d9b409Smrgstatic int 618a6d9b409Smrgfindslot (char *line_name, char *host_name, int addp, int slot) 619a6d9b409Smrg{ 620a6d9b409Smrg int utmp; 621a6d9b409Smrg struct utmp entry; 622a6d9b409Smrg int found = 0; 623a6d9b409Smrg int freeslot = -1; 624a6d9b409Smrg 625a6d9b409Smrg syserr(utmp = open (utmp_file, O_RDONLY), "open utmp"); 626a6d9b409Smrg 627a6d9b409Smrg /* 628a6d9b409Smrg * first, try to locate a previous entry for this display 629a6d9b409Smrg * also record location of a free slots in case we need a new one 630a6d9b409Smrg */ 631a6d9b409Smrg syserr ((int) lseek (utmp, (long) slot * sizeof (struct utmp), 0), "lseek"); 632a6d9b409Smrg 633a6d9b409Smrg if (!host_name) 634a6d9b409Smrg host_name = ""; 635a6d9b409Smrg 636a6d9b409Smrg while (read (utmp, (char *) &entry, sizeof (entry)) == sizeof (entry)) { 637a6d9b409Smrg if (strncmp(entry.ut_line, line_name, 638a6d9b409Smrg sizeof(entry.ut_line)) == 0 639a6d9b409Smrg#ifndef __QNX__ 640a6d9b409Smrg && 641a6d9b409Smrg strncmp(entry.ut_host, host_name, 642a6d9b409Smrg sizeof(entry.ut_host)) == 0 643a6d9b409Smrg#endif 644a6d9b409Smrg ) { 645a6d9b409Smrg found = 1; 646a6d9b409Smrg break; 647a6d9b409Smrg } 648a6d9b409Smrg if (freeslot < 0 && *entry.ut_name == '\0') 649a6d9b409Smrg freeslot = slot; 650a6d9b409Smrg ++slot; 651a6d9b409Smrg } 652a6d9b409Smrg 653a6d9b409Smrg close (utmp); 654a6d9b409Smrg 655a6d9b409Smrg if (found) 656a6d9b409Smrg return slot; 657a6d9b409Smrg else if (!addp) 658a6d9b409Smrg return 0; /* trying to delete a non-existing entry */ 659a6d9b409Smrg else if (freeslot < 0) 660a6d9b409Smrg return slot; /* first slot past current entries */ 661a6d9b409Smrg else 662a6d9b409Smrg return freeslot; 663a6d9b409Smrg} 664a6d9b409Smrg#endif 665