sessreg.c revision a6d9b409
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
31a6d9b409Smrg * copy of this software and associated documentation files (the
32a6d9b409Smrg * "Software"), to deal in the Software without restriction, including
33a6d9b409Smrg * without limitation the rights to use, copy, modify, merge, publish,
34a6d9b409Smrg * distribute, and/or sell copies of the Software, and to permit persons
35a6d9b409Smrg * to whom the Software is furnished to do so, provided that the above
36a6d9b409Smrg * copyright notice(s) and this permission notice appear in all copies of
37a6d9b409Smrg * the Software and that both the above copyright notice(s) and this
38a6d9b409Smrg * permission notice appear in supporting documentation.
39a6d9b409Smrg *
40a6d9b409Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
41a6d9b409Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42a6d9b409Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
43a6d9b409Smrg * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
44a6d9b409Smrg * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
45a6d9b409Smrg * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
46a6d9b409Smrg * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
47a6d9b409Smrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
48a6d9b409Smrg * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49a6d9b409Smrg *
50a6d9b409Smrg * Except as contained in this notice, the name of a copyright holder
51a6d9b409Smrg * shall not be used in advertising or otherwise to promote the sale, use
52a6d9b409Smrg * or other dealings in this Software without prior written authorization
53a6d9b409Smrg * of the copyright holder.
54a6d9b409Smrg */
55a6d9b409Smrg
56a6d9b409Smrg/*
57a6d9b409Smrg * Author:  Keith Packard, MIT X Consortium
58a6d9b409Smrg * Lastlog support and dynamic utmp entry allocation
59a6d9b409Smrg *   by Andreas Stolcke <stolcke@icsi.berkeley.edu>
60a6d9b409Smrg */
61a6d9b409Smrg
62a6d9b409Smrg/*
63a6d9b409Smrg * sessreg
64a6d9b409Smrg *
65a6d9b409Smrg * simple wtmp/utmp frobber
66a6d9b409Smrg *
67a6d9b409Smrg * usage: sessreg [ -w <wtmp-file> ] [ -u <utmp-file> ]
68a6d9b409Smrg *		  [ -l <line> ]
69a6d9b409Smrg *		  [ -h <host-name> ]				/ BSD only
70a6d9b409Smrg *		  [ -s <slot-number> ] [ -x Xservers-file ]	/ BSD only
71a6d9b409Smrg *		  [ -t <ttys-file> ]				/ BSD only
72a6d9b409Smrg *	          [ -a ] [ -d ] user-name
73a6d9b409Smrg *
74a6d9b409Smrg * one of -a or -d must be specified
75a6d9b409Smrg */
76a6d9b409Smrg
77a6d9b409Smrg#include "sessreg.h"
78a6d9b409Smrg
79a6d9b409Smrg# include	<X11/Xos.h>
80a6d9b409Smrg# include	<X11/Xfuncs.h>
81a6d9b409Smrg# include	<stdio.h>
82a6d9b409Smrg# include	<stdlib.h>
83a6d9b409Smrg# include	<utmp.h>
84a6d9b409Smrg
85a6d9b409Smrg#if defined(__SVR4) || defined(SVR4) || defined(linux) || defined(__GLIBC__)
86a6d9b409Smrg# define SYSV
87a6d9b409Smrg#endif
88a6d9b409Smrg
89a6d9b409Smrg#include <time.h>
90a6d9b409Smrg#define Time_t time_t
91a6d9b409Smrg#ifdef X_NOT_POSIX
92a6d9b409Smrgextern long	lseek ();
93a6d9b409Smrgextern char	*ttyname ();
94a6d9b409Smrg#endif
95a6d9b409Smrg
96a6d9b409Smrgstatic void set_utmp (struct utmp *u, char *line, char *user, char *host, Time_t date, int addp);
97a6d9b409Smrg
98a6d9b409Smrg#ifdef USE_UTMPX
99a6d9b409Smrgstatic void set_utmpx (struct utmpx *u, const char *line, const char *user,
100a6d9b409Smrg		       const char *host, Time_t date, int addp);
101a6d9b409Smrg#endif
102a6d9b409Smrg
103a6d9b409Smrgint	wflag, uflag, lflag;
104a6d9b409Smrgchar	*wtmp_file, *utmp_file, *line;
105a6d9b409Smrg#ifdef USE_UTMPX
106a6d9b409Smrgstatic char *wtmpx_file = NULL, *utmpx_file = NULL;
107a6d9b409Smrg#endif
108a6d9b409Smrgint	utmp_none, wtmp_none;
109a6d9b409Smrg/*
110a6d9b409Smrg * BSD specific variables.  To make life much easier for Xstartup/Xreset
111a6d9b409Smrg * maintainers, these arguments are accepted but ignored for sysV
112a6d9b409Smrg */
113a6d9b409Smrgint	hflag, sflag, xflag, tflag;
114a6d9b409Smrgchar	*host_name = NULL;
115a6d9b409Smrgint	slot_number;
116a6d9b409Smrgchar	*xservers_file, *ttys_file;
117a6d9b409Smrgchar	*user_name;
118a6d9b409Smrgint	aflag, dflag;
119a6d9b409Smrg#ifndef NO_LASTLOG
120a6d9b409Smrgchar	*llog_file;
121a6d9b409Smrgint	llog_none, Lflag;
122a6d9b409Smrg#endif
123a6d9b409Smrg
124a6d9b409Smrgchar	*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{
187a6d9b409Smrg#ifndef SYSV
188a6d9b409Smrg	int		utmp;
189a6d9b409Smrg#endif
190a6d9b409Smrg	char		*line_tmp;
191a6d9b409Smrg#ifndef USE_UTMPX
192a6d9b409Smrg	int		wtmp;
193a6d9b409Smrg#endif
194a6d9b409Smrg	Time_t		current_time;
195a6d9b409Smrg	struct utmp	utmp_entry;
196a6d9b409Smrg#ifdef USE_UTMPX
197a6d9b409Smrg	struct utmpx	utmpx_entry;
198a6d9b409Smrg#endif
199a6d9b409Smrg
200a6d9b409Smrg	program_name = argv[0];
201a6d9b409Smrg	while (*++argv && **argv == '-') {
202a6d9b409Smrg		switch (*++*argv) {
203a6d9b409Smrg		case 'w':
204a6d9b409Smrg			wtmp_file = getstring (&argv, &wflag);
205a6d9b409Smrg			if (!strcmp (wtmp_file, "none"))
206a6d9b409Smrg				wtmp_none = 1;
207a6d9b409Smrg			break;
208a6d9b409Smrg		case 'u':
209a6d9b409Smrg			utmp_file = getstring (&argv, &uflag);
210a6d9b409Smrg			if (!strcmp (utmp_file, "none"))
211a6d9b409Smrg				utmp_none = 1;
212a6d9b409Smrg			break;
213a6d9b409Smrg#ifndef NO_LASTLOG
214a6d9b409Smrg		case 'L':
215a6d9b409Smrg			llog_file = getstring (&argv, &Lflag);
216a6d9b409Smrg			if (!strcmp (llog_file, "none"))
217a6d9b409Smrg				llog_none = 1;
218a6d9b409Smrg			break;
219a6d9b409Smrg#endif
220a6d9b409Smrg		case 't':
221a6d9b409Smrg			ttys_file = getstring (&argv, &tflag);
222a6d9b409Smrg			break;
223a6d9b409Smrg		case 'l':
224a6d9b409Smrg			line = getstring (&argv, &lflag);
225a6d9b409Smrg			break;
226a6d9b409Smrg		case 'h':
227a6d9b409Smrg			host_name = getstring (&argv, &hflag);
228a6d9b409Smrg			break;
229a6d9b409Smrg		case 's':
230a6d9b409Smrg			slot_number = atoi (getstring (&argv, &sflag));
231a6d9b409Smrg			break;
232a6d9b409Smrg		case 'x':
233a6d9b409Smrg			xservers_file = getstring (&argv, &xflag);
234a6d9b409Smrg			break;
235a6d9b409Smrg		case 'a':
236a6d9b409Smrg			aflag++;
237a6d9b409Smrg			break;
238a6d9b409Smrg		case 'd':
239a6d9b409Smrg			dflag++;
240a6d9b409Smrg			break;
241a6d9b409Smrg		default:
242a6d9b409Smrg			usage (1);
243a6d9b409Smrg		}
244a6d9b409Smrg	}
245a6d9b409Smrg	usage (!(user_name = *argv++));
246a6d9b409Smrg	usage (*argv != 0);
247a6d9b409Smrg	/*
248a6d9b409Smrg	 * complain if neither aflag nor dflag are set,
249a6d9b409Smrg	 * or if both are set.
250a6d9b409Smrg	 */
251a6d9b409Smrg	usage (!(aflag ^ dflag));
252a6d9b409Smrg	usage (xflag && !lflag);
253a6d9b409Smrg	/* set up default file names */
254a6d9b409Smrg	if (!wflag) {
255a6d9b409Smrg		wtmp_file = WTMP_FILE;
256a6d9b409Smrg#ifdef USE_UTMPX
257a6d9b409Smrg		wtmpx_file = WTMPX_FILE;
258a6d9b409Smrg#endif
259a6d9b409Smrg	}
260a6d9b409Smrg#ifndef NO_UTMP
261a6d9b409Smrg	if (!uflag) {
262a6d9b409Smrg		utmp_file = UTMP_FILE;
263a6d9b409Smrg#ifdef USE_UTMPX
264a6d9b409Smrg		utmpx_file = UTMPX_FILE;
265a6d9b409Smrg#endif
266a6d9b409Smrg	}
267a6d9b409Smrg#else
268a6d9b409Smrg	utmp_none = 1;
269a6d9b409Smrg#endif
270a6d9b409Smrg#ifndef NO_LASTLOG
271a6d9b409Smrg	if (!Lflag)
272a6d9b409Smrg		llog_file = LLOG_FILE;
273a6d9b409Smrg#endif
274a6d9b409Smrg#if !defined(SYSV) && !defined(linux) && !defined(__QNX__)
275a6d9b409Smrg	if (!tflag)
276a6d9b409Smrg		ttys_file = TTYS_FILE;
277a6d9b409Smrg	if (!sflag && !utmp_none) {
278a6d9b409Smrg		if (xflag)
279a6d9b409Smrg			sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot");
280a6d9b409Smrg		else
281a6d9b409Smrg			sysnerr (slot_number = ttyslot (), "ttyslot");
282a6d9b409Smrg	}
283a6d9b409Smrg#endif
284a6d9b409Smrg	if (!lflag) {
285a6d9b409Smrg		sysnerr ((line_tmp = ttyname (0)) != NULL, "ttyname");
286a6d9b409Smrg		line = strrchr(line_tmp, '/');
287a6d9b409Smrg		if (line)
288a6d9b409Smrg			line = line + 1;
289a6d9b409Smrg		else
290a6d9b409Smrg			line = line_tmp;
291a6d9b409Smrg	}
292a6d9b409Smrg	time (&current_time);
293a6d9b409Smrg	set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag);
294a6d9b409Smrg
295a6d9b409Smrg#ifdef USE_UTMPX
296a6d9b409Smrg	/* need to set utmpxname() before calling set_utmpx() for
297a6d9b409Smrg	   UtmpxIdOpen to work */
298a6d9b409Smrg	if (utmpx_file != NULL) {
299a6d9b409Smrg	        utmpxname (utmpx_file);
300a6d9b409Smrg	}
301a6d9b409Smrg	set_utmpx (&utmpx_entry, line, user_name,
302a6d9b409Smrg		   host_name, current_time, aflag);
303a6d9b409Smrg#endif
304a6d9b409Smrg
305a6d9b409Smrg	if (!utmp_none) {
306a6d9b409Smrg#ifdef USE_UTMPX
307a6d9b409Smrg	    if (utmpx_file != NULL) {
308a6d9b409Smrg		setutxent ();
309a6d9b409Smrg		(void) getutxid (&utmpx_entry);
310a6d9b409Smrg		pututxline (&utmpx_entry);
311a6d9b409Smrg		endutxent ();
312a6d9b409Smrg	    }
313a6d9b409Smrg#endif
314a6d9b409Smrg#ifdef SYSV
315a6d9b409Smrg		utmpname (utmp_file);
316a6d9b409Smrg		setutent ();
317a6d9b409Smrg		(void) getutid (&utmp_entry);
318a6d9b409Smrg		pututline (&utmp_entry);
319a6d9b409Smrg		endutent ();
320a6d9b409Smrg#else
321a6d9b409Smrg		utmp = open (utmp_file, O_RDWR);
322a6d9b409Smrg		if (utmp != -1) {
323a6d9b409Smrg			syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek");
324a6d9b409Smrg			sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry))
325a6d9b409Smrg				        == sizeof (utmp_entry), "write utmp entry");
326a6d9b409Smrg			close (utmp);
327a6d9b409Smrg		}
328a6d9b409Smrg#endif
329a6d9b409Smrg	}
330a6d9b409Smrg	if (!wtmp_none) {
331a6d9b409Smrg#ifdef USE_UTMPX
332a6d9b409Smrg		if (wtmpx_file != NULL) {
333a6d9b409Smrg			updwtmpx(wtmpx_file, &utmpx_entry);
334a6d9b409Smrg		}
335a6d9b409Smrg#else
336a6d9b409Smrg		wtmp = open (wtmp_file, O_WRONLY|O_APPEND);
337a6d9b409Smrg		if (wtmp != -1) {
338a6d9b409Smrg			sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry))
339a6d9b409Smrg				        == sizeof (utmp_entry), "write wtmp entry");
340a6d9b409Smrg			close (wtmp);
341a6d9b409Smrg		}
342a6d9b409Smrg#endif
343a6d9b409Smrg	}
344a6d9b409Smrg#ifndef NO_LASTLOG
345a6d9b409Smrg	if (aflag && !llog_none) {
346a6d9b409Smrg	        int llog;
347a6d9b409Smrg	        struct passwd *pwd = getpwnam(user_name);
348a6d9b409Smrg
349a6d9b409Smrg	        sysnerr( pwd != NULL, "get user id");
350a6d9b409Smrg	        llog = open (llog_file, O_RDWR);
351a6d9b409Smrg
352a6d9b409Smrg		if (llog != -1) {
353a6d9b409Smrg			struct lastlog ll;
354a6d9b409Smrg
355a6d9b409Smrg			sysnerr (lseek(llog, (long) pwd->pw_uid*sizeof(ll), 0)
356a6d9b409Smrg				        != -1, "seeking lastlog entry");
357a6d9b409Smrg			bzero((char *)&ll, sizeof(ll));
358a6d9b409Smrg			ll.ll_time = current_time;
359a6d9b409Smrg			if (line)
360a6d9b409Smrg			 (void) strncpy (ll.ll_line, line, sizeof (ll.ll_line));
361a6d9b409Smrg			if (host_name)
362a6d9b409Smrg			 (void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host));
363a6d9b409Smrg
364a6d9b409Smrg			sysnerr (write (llog, (char *) &ll, sizeof (ll))
365a6d9b409Smrg				        == sizeof (ll), "write lastlog entry");
366a6d9b409Smrg			close (llog);
367a6d9b409Smrg		}
368a6d9b409Smrg	}
369a6d9b409Smrg#endif
370a6d9b409Smrg	return 0;
371a6d9b409Smrg}
372a6d9b409Smrg
373a6d9b409Smrg/*
374a6d9b409Smrg * fill in the appropriate records of the utmp entry
375a6d9b409Smrg */
376a6d9b409Smrg
377a6d9b409Smrgstatic void
378a6d9b409Smrgset_utmp (struct utmp *u, char *line, char *user, char *host, Time_t date, int addp)
379a6d9b409Smrg{
380a6d9b409Smrg	bzero (u, sizeof (*u));
381a6d9b409Smrg	if (line)
382a6d9b409Smrg		(void) strncpy (u->ut_line, line, sizeof (u->ut_line));
383a6d9b409Smrg	else
384a6d9b409Smrg		bzero (u->ut_line, sizeof (u->ut_line));
385a6d9b409Smrg	if (addp && user)
386a6d9b409Smrg		(void) strncpy (u->ut_name, user, sizeof (u->ut_name));
387a6d9b409Smrg	else
388a6d9b409Smrg		bzero (u->ut_name, sizeof (u->ut_name));
389a6d9b409Smrg#ifdef SYSV
390a6d9b409Smrg	if (line) {
391a6d9b409Smrg		int	i;
392a6d9b409Smrg		/*
393a6d9b409Smrg		 * this is a bit crufty, but
394a6d9b409Smrg		 * follows the apparent conventions in
395a6d9b409Smrg		 * the ttys file.  ut_id is only 4 bytes
396a6d9b409Smrg		 * long, and the last 4 bytes of the line
397a6d9b409Smrg		 * name are written into it, left justified.
398a6d9b409Smrg		 */
399a6d9b409Smrg		i = strlen (line);
400a6d9b409Smrg		if (i >= sizeof (u->ut_id))
401a6d9b409Smrg			i -= sizeof (u->ut_id);
402a6d9b409Smrg		else
403a6d9b409Smrg			i = 0;
404a6d9b409Smrg		(void) strncpy (u->ut_id, line + i, sizeof (u->ut_id));
405a6d9b409Smrg	} else
406a6d9b409Smrg		bzero (u->ut_id, sizeof (u->ut_id));
407a6d9b409Smrg	if (addp) {
408a6d9b409Smrg		u->ut_pid = getppid ();
409a6d9b409Smrg		u->ut_type = USER_PROCESS;
410a6d9b409Smrg	} else {
411a6d9b409Smrg		u->ut_pid = 0;
412a6d9b409Smrg		u->ut_type = DEAD_PROCESS;
413a6d9b409Smrg	}
414a6d9b409Smrg#endif
415a6d9b409Smrg#if (!defined(SYSV) && !defined(__QNX__)) || defined(linux)
416a6d9b409Smrg	if (addp && host)
417a6d9b409Smrg		(void) strncpy (u->ut_host, host, sizeof (u->ut_host));
418a6d9b409Smrg	else
419a6d9b409Smrg		bzero (u->ut_host, sizeof (u->ut_host));
420a6d9b409Smrg#endif
421a6d9b409Smrg	u->ut_time = date;
422a6d9b409Smrg}
423a6d9b409Smrg
424a6d9b409Smrg#ifdef USE_UTMPX
425a6d9b409Smrgstatic int
426a6d9b409SmrgUtmpxIdOpen( char *utmpId )
427a6d9b409Smrg{
428a6d9b409Smrg	struct utmpx *u;	/* pointer to entry in utmp file           */
429a6d9b409Smrg	int    status = 1;	/* return code                             */
430a6d9b409Smrg
431a6d9b409Smrg	while ( (u = getutxent()) != NULL ) {
432a6d9b409Smrg
433a6d9b409Smrg		if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
434a6d9b409Smrg		     u->ut_type != DEAD_PROCESS ) {
435a6d9b409Smrg
436a6d9b409Smrg			status = 0;
437a6d9b409Smrg			break;
438a6d9b409Smrg		}
439a6d9b409Smrg	}
440a6d9b409Smrg
441a6d9b409Smrg	endutent();
442a6d9b409Smrg	return (status);
443a6d9b409Smrg}
444a6d9b409Smrg
445a6d9b409Smrgstatic void
446a6d9b409Smrgset_utmpx (struct utmpx *u, const char *line, const char *user,
447a6d9b409Smrg	   const char *host, Time_t date, int addp)
448a6d9b409Smrg{
449a6d9b409Smrg	static const char letters[] =
450a6d9b409Smrg	       "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
451a6d9b409Smrg
452a6d9b409Smrg        if (line)
453a6d9b409Smrg	{
454a6d9b409Smrg                if(strcmp(line, ":0") == 0)
455a6d9b409Smrg                        (void) strcpy(u->ut_line, "console");
456a6d9b409Smrg                else
457a6d9b409Smrg                        (void) strncpy (u->ut_line, line, sizeof (u->ut_line));
458a6d9b409Smrg
459a6d9b409Smrg		strncpy(u->ut_host, line, sizeof(u->ut_host));
460a6d9b409Smrg		u->ut_syslen = strlen(line);
461a6d9b409Smrg	}
462a6d9b409Smrg        else
463a6d9b409Smrg                bzero (u->ut_line, sizeof (u->ut_line));
464a6d9b409Smrg        if (addp && user)
465a6d9b409Smrg                (void) strncpy (u->ut_name, user, sizeof (u->ut_name));
466a6d9b409Smrg        else
467a6d9b409Smrg                bzero (u->ut_name, sizeof (u->ut_name));
468a6d9b409Smrg
469a6d9b409Smrg        if (line) {
470a6d9b409Smrg                int     i;
471a6d9b409Smrg                /*
472a6d9b409Smrg                 * this is a bit crufty, but
473a6d9b409Smrg                 * follows the apparent conventions in
474a6d9b409Smrg                 * the ttys file.  ut_id is only 4 bytes
475a6d9b409Smrg                 * long, and the last 4 bytes of the line
476a6d9b409Smrg                 * name are written into it, left justified.
477a6d9b409Smrg                 */
478a6d9b409Smrg                i = strlen (line);
479a6d9b409Smrg                if (i >= sizeof (u->ut_id))
480a6d9b409Smrg                        i -= sizeof (u->ut_id);
481a6d9b409Smrg                else
482a6d9b409Smrg                        i = 0;
483a6d9b409Smrg                (void) strncpy (u->ut_id, line + i, sizeof (u->ut_id));
484a6d9b409Smrg
485a6d9b409Smrg		/* make sure there is no entry using identical ut_id */
486a6d9b409Smrg		if (!UtmpxIdOpen(u->ut_id) && addp) {
487a6d9b409Smrg                        int limit = sizeof(letters) - 1;
488a6d9b409Smrg                        int t = 0;
489a6d9b409Smrg
490a6d9b409Smrg                        u->ut_id[1] = line[i];
491a6d9b409Smrg                        u->ut_id[2] = line[i+1];
492a6d9b409Smrg                        u->ut_id[3] = line[i+2];
493a6d9b409Smrg                        do {
494a6d9b409Smrg                                u->ut_id[0] = letters[t];
495a6d9b409Smrg                                t++;
496a6d9b409Smrg                        } while (!UtmpxIdOpen(u->ut_id) && (t < limit));
497a6d9b409Smrg                }
498a6d9b409Smrg                if (!addp && strstr(line, ":") != NULL) {
499a6d9b409Smrg                        struct utmpx *tmpu;
500a6d9b409Smrg
501a6d9b409Smrg                        while ( (tmpu = getutxent()) != NULL ) {
502a6d9b409Smrg                                if ( (strcmp(tmpu->ut_host, line) == 0 ) &&
503a6d9b409Smrg                                        tmpu->ut_type != DEAD_PROCESS ) {
504a6d9b409Smrg                                        strncpy(u->ut_id, tmpu->ut_id,
505a6d9b409Smrg						sizeof(u->ut_id));
506a6d9b409Smrg                                        break;
507a6d9b409Smrg                                }
508a6d9b409Smrg                        }
509a6d9b409Smrg                        endutxent();
510a6d9b409Smrg                }
511a6d9b409Smrg        } else
512a6d9b409Smrg                bzero (u->ut_id, sizeof (u->ut_id));
513a6d9b409Smrg
514a6d9b409Smrg        if (addp) {
515a6d9b409Smrg                u->ut_pid = getppid ();
516a6d9b409Smrg                u->ut_type = USER_PROCESS;
517a6d9b409Smrg        } else {
518a6d9b409Smrg                u->ut_pid = 0;
519a6d9b409Smrg                u->ut_type = DEAD_PROCESS;
520a6d9b409Smrg        }
521a6d9b409Smrg	u->ut_tv.tv_sec = date;
522a6d9b409Smrg	u->ut_tv.tv_usec = 0;
523a6d9b409Smrg}
524a6d9b409Smrg#endif /* USE_UTMPX */
525a6d9b409Smrg
526a6d9b409Smrg#ifndef SYSV
527a6d9b409Smrg/*
528a6d9b409Smrg * compute the slot-number for an X display.  This is computed
529a6d9b409Smrg * by counting the lines in /etc/ttys and adding the line-number
530a6d9b409Smrg * that the display appears on in Xservers.  This is a poor
531a6d9b409Smrg * design, but is limited by the non-existant interface to utmp.
532a6d9b409Smrg * If host_name is non-NULL, assume it contains the display name,
533a6d9b409Smrg * otherwise use the tty_line argument (i.e., the tty name).
534a6d9b409Smrg */
535a6d9b409Smrg
536a6d9b409Smrgstatic int
537a6d9b409SmrgXslot (char *ttys_file, char *servers_file, char *tty_line, char *host_name,
538a6d9b409Smrg       int addp)
539a6d9b409Smrg{
540a6d9b409Smrg	FILE	*ttys, *servers;
541a6d9b409Smrg	int	c;
542a6d9b409Smrg	int	slot = 1;
543a6d9b409Smrg	int	column0 = 1;
544a6d9b409Smrg	char	servers_line[1024];
545a6d9b409Smrg	char	disp_name[512];
546a6d9b409Smrg	int	len;
547a6d9b409Smrg	char	*pos;
548a6d9b409Smrg
549a6d9b409Smrg	/* remove screen number from the display name */
550a6d9b409Smrg	memset(disp_name, 0, sizeof(disp_name));
551a6d9b409Smrg	strncpy(disp_name, host_name ? host_name : tty_line, sizeof(disp_name)-1);
552a6d9b409Smrg	pos = strrchr(disp_name, ':');
553a6d9b409Smrg	if (pos) {
554a6d9b409Smrg	    pos = strchr(pos, '.');
555a6d9b409Smrg	    if (pos)
556a6d9b409Smrg		*pos = '\0';
557a6d9b409Smrg	}
558a6d9b409Smrg	sysnerr ((int)(long)(ttys = fopen (ttys_file, "r")), ttys_file);
559a6d9b409Smrg	while ((c = getc (ttys)) != EOF)
560a6d9b409Smrg		if (c == '\n') {
561a6d9b409Smrg			++slot;
562a6d9b409Smrg			column0 = 1;
563a6d9b409Smrg		} else
564a6d9b409Smrg			column0 = 0;
565a6d9b409Smrg	if (!column0)
566a6d9b409Smrg		++slot;
567a6d9b409Smrg	(void) fclose (ttys);
568a6d9b409Smrg	sysnerr ((int)(long)(servers = fopen (servers_file, "r")), servers_file);
569a6d9b409Smrg
570a6d9b409Smrg	len = strlen (disp_name);
571a6d9b409Smrg	column0 = 1;
572a6d9b409Smrg	while (fgets (servers_line, sizeof (servers_line), servers)) {
573a6d9b409Smrg		if (column0 && *servers_line != '#') {
574a6d9b409Smrg			if (!strncmp (disp_name, servers_line, len) &&
575a6d9b409Smrg			    (servers_line[len] == ' ' ||
576a6d9b409Smrg			     servers_line[len] == '\t'))
577a6d9b409Smrg				return slot;
578a6d9b409Smrg			++slot;
579a6d9b409Smrg		}
580a6d9b409Smrg		if (servers_line[strlen(servers_line)-1] != '\n')
581a6d9b409Smrg			column0 = 0;
582a6d9b409Smrg		else
583a6d9b409Smrg			column0 = 1;
584a6d9b409Smrg	}
585a6d9b409Smrg	/*
586a6d9b409Smrg	 * display not found in Xservers file - allocate utmp entry dinamically
587a6d9b409Smrg	 */
588a6d9b409Smrg	return findslot (tty_line, host_name, addp, slot);
589a6d9b409Smrg}
590a6d9b409Smrg
591a6d9b409Smrg/*
592a6d9b409Smrg * find a free utmp slot for the X display.  This allocates a new entry
593a6d9b409Smrg * past the regular tty entries if necessary, reusing existing entries
594a6d9b409Smrg * (identified by (line,hostname)) if possible.
595a6d9b409Smrg */
596a6d9b409Smrgstatic int
597a6d9b409Smrgfindslot (char *line_name, char *host_name, int addp, int slot)
598a6d9b409Smrg{
599a6d9b409Smrg	int	utmp;
600a6d9b409Smrg	struct	utmp entry;
601a6d9b409Smrg	int	found = 0;
602a6d9b409Smrg	int	freeslot = -1;
603a6d9b409Smrg
604a6d9b409Smrg	syserr(utmp = open (utmp_file, O_RDONLY), "open utmp");
605a6d9b409Smrg
606a6d9b409Smrg	/*
607a6d9b409Smrg	 * first, try to locate a previous entry for this display
608a6d9b409Smrg	 * also record location of a free slots in case we need a new one
609a6d9b409Smrg	 */
610a6d9b409Smrg	syserr ((int) lseek (utmp, (long) slot * sizeof (struct utmp), 0), "lseek");
611a6d9b409Smrg
612a6d9b409Smrg	if (!host_name)
613a6d9b409Smrg		host_name = "";
614a6d9b409Smrg
615a6d9b409Smrg	while (read (utmp, (char *) &entry, sizeof (entry)) == sizeof (entry)) {
616a6d9b409Smrg		if (strncmp(entry.ut_line, line_name,
617a6d9b409Smrg			sizeof(entry.ut_line)) == 0
618a6d9b409Smrg#ifndef __QNX__
619a6d9b409Smrg                    &&
620a6d9b409Smrg		    strncmp(entry.ut_host, host_name,
621a6d9b409Smrg			sizeof(entry.ut_host)) == 0
622a6d9b409Smrg#endif
623a6d9b409Smrg                   ) {
624a6d9b409Smrg			found = 1;
625a6d9b409Smrg			break;
626a6d9b409Smrg		}
627a6d9b409Smrg		if (freeslot < 0 && *entry.ut_name == '\0')
628a6d9b409Smrg			freeslot = slot;
629a6d9b409Smrg		++slot;
630a6d9b409Smrg	}
631a6d9b409Smrg
632a6d9b409Smrg	close (utmp);
633a6d9b409Smrg
634a6d9b409Smrg	if (found)
635a6d9b409Smrg		return slot;
636a6d9b409Smrg	else if (!addp)
637a6d9b409Smrg		return 0;	/* trying to delete a non-existing entry */
638a6d9b409Smrg	else if (freeslot < 0)
639a6d9b409Smrg		return slot;	/* first slot past current entries */
640a6d9b409Smrg	else
641a6d9b409Smrg		return freeslot;
642a6d9b409Smrg}
643a6d9b409Smrg#endif
644