summaryrefslogtreecommitdiff
path: root/sessreg.c
diff options
context:
space:
mode:
Diffstat (limited to 'sessreg.c')
-rw-r--r--sessreg.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/sessreg.c b/sessreg.c
new file mode 100644
index 0000000..748608a
--- /dev/null
+++ b/sessreg.c
@@ -0,0 +1,495 @@
+/*
+ * $Xorg: sessreg.c,v 1.5 2000/08/17 19:54:15 cpqbld Exp $
+ *
+ * Copyright 1990, 1998 The Open Group
+ *
+ * All Rights Reserved.
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of The Open Group shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization
+ * from The Open Group.
+ *
+ * Author: Keith Packard, MIT X Consortium
+ * Lastlog support and dynamic utmp entry allocation
+ * by Andreas Stolcke <stolcke@icsi.berkeley.edu>
+ */
+
+/*
+ * sessreg
+ *
+ * simple wtmp/utmp frobber
+ *
+ * usage: sessreg [ -w <wtmp-file> ] [ -u <utmp-file> ]
+ * [ -l <line> ]
+ * [ -h <host-name> ] / BSD only
+ * [ -s <slot-number> ] [ -x Xservers-file ] / BSD only
+ * [ -t <ttys-file> ] / BSD only
+ * [ -a ] [ -d ] user-name
+ *
+ * one of -a or -d must be specified
+ */
+
+
+# include <X11/Xos.h>
+# include <X11/Xfuncs.h>
+# include <stdio.h>
+# include <utmp.h>
+
+#if defined(SYSV) || defined(_SEQUENT_)
+#define NO_LASTLOG
+#endif
+
+#ifndef NO_LASTLOG
+# ifndef CSRG_BASED
+# include <lastlog.h>
+# endif
+# include <pwd.h>
+#endif
+
+#if defined(SVR4) || defined(linux)
+#define SYSV /* nice System V utmp interface still the same */
+#endif
+
+#ifndef WTMP_FILE
+# ifdef _PATH_WTMP
+# define WTMP_FILE _PATH_WTMP
+# else
+# define WTMP_FILE "/usr/adm/wtmp"
+# endif
+#endif
+#ifndef UTMP_FILE
+# ifdef _PATH_UTMP
+# define UTMP_FILE _PATH_UTMP
+# else
+# define UTMP_FILE "/etc/utmp"
+# endif
+#endif
+#ifndef NO_LASTLOG
+# ifndef LLOG_FILE
+# ifdef _PATH_LASTLOG
+# define LLOG_FILE _PATH_LASTLOG
+# else
+# define LLOG_FILE "/usr/adm/lastlog"
+# endif
+# endif
+#endif
+#ifndef SYSV
+# ifndef TTYS_FILE
+# define TTYS_FILE "/etc/ttys"
+# endif
+#endif
+
+#ifdef X_NOT_STDC_ENV
+#define Time_t long
+extern Time_t time ();
+#else
+#include <time.h>
+#define Time_t time_t
+#endif
+#ifdef X_NOT_POSIX
+extern long lseek ();
+extern char *ttyname ();
+#endif
+
+int wflag, uflag, lflag;
+char *wtmp_file, *utmp_file, *line;
+int utmp_none, wtmp_none;
+/*
+ * BSD specific variables. To make life much easier for Xstartup/Xreset
+ * maintainers, these arguments are accepted but ignored for sysV
+ */
+int hflag, sflag, xflag, tflag;
+char *host_name;
+int slot_number;
+char *xservers_file, *ttys_file;
+char *user_name;
+int aflag, dflag;
+#ifndef NO_LASTLOG
+char *llog_file;
+int llog_none, Lflag;
+#endif
+
+char *program_name;
+
+usage (x)
+{
+ if (x) {
+ fprintf (stderr, "%s: usage %s {-a -d} [-w wtmp-file] [-u utmp-file]", program_name, program_name);
+#ifndef NO_LASTLOG
+ fprintf (stderr, " [-L lastlog-file]");
+#endif
+ fprintf (stderr, "\n");
+ fprintf (stderr, " [-t ttys-file] [-l line-name] [-h host-name]\n");
+ fprintf (stderr, " [-s slot-number] [-x servers-file] user-name\n");
+ exit (1);
+ }
+ return x;
+}
+
+char *
+getstring (avp, flagp)
+char ***avp;
+int *flagp;
+{
+ char **a = *avp;
+
+ usage ((*flagp)++);
+ if (*++*a)
+ return *a;
+ ++a;
+ usage (!*a);
+ *avp = a;
+ return *a;
+}
+
+syserr (x, s)
+int x;
+char *s;
+{
+ if (x == -1) {
+ perror (s);
+ exit (1);
+ }
+ return x;
+}
+
+sysnerr (x, s)
+int x;
+char *s;
+{
+ if (x == 0) {
+ perror (s);
+ exit (1);
+ }
+ return x;
+}
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+#ifndef SYSV
+ int utmp;
+#endif
+ char *line_tmp;
+ int wtmp;
+ Time_t current_time;
+ struct utmp utmp_entry;
+
+ program_name = argv[0];
+ while (*++argv && **argv == '-') {
+ switch (*++*argv) {
+ case 'w':
+ wtmp_file = getstring (&argv, &wflag);
+ if (!strcmp (wtmp_file, "none"))
+ wtmp_none = 1;
+ break;
+ case 'u':
+ utmp_file = getstring (&argv, &uflag);
+ if (!strcmp (utmp_file, "none"))
+ utmp_none = 1;
+ break;
+#ifndef NO_LASTLOG
+ case 'L':
+ llog_file = getstring (&argv, &Lflag);
+ if (!strcmp (llog_file, "none"))
+ llog_none = 1;
+ break;
+#endif
+ case 't':
+ ttys_file = getstring (&argv, &tflag);
+ break;
+ case 'l':
+ line = getstring (&argv, &lflag);
+ break;
+ case 'h':
+ host_name = getstring (&argv, &hflag);
+ break;
+ case 's':
+ slot_number = atoi (getstring (&argv, &sflag));
+ break;
+ case 'x':
+ xservers_file = getstring (&argv, &xflag);
+ break;
+ case 'a':
+ aflag++;
+ break;
+ case 'd':
+ dflag++;
+ break;
+ default:
+ usage (1);
+ }
+ }
+ usage (!(user_name = *argv++));
+ usage (*argv != 0);
+ /*
+ * complain if neither aflag nor dflag are set,
+ * or if both are set.
+ */
+ usage (!(aflag ^ dflag));
+ usage (xflag && !lflag);
+ /* set up default file names */
+ if (!wflag)
+ wtmp_file = WTMP_FILE;
+ if (!uflag)
+ utmp_file = UTMP_FILE;
+#ifndef NO_LASTLOG
+ if (!Lflag)
+ llog_file = LLOG_FILE;
+#endif
+#if !defined(SYSV) && !defined(linux)
+ if (!tflag)
+ ttys_file = TTYS_FILE;
+ if (!sflag && !utmp_none) {
+ if (xflag)
+ sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot");
+ else
+ sysnerr (slot_number = ttyslot (), "ttyslot");
+ }
+#endif
+ if (!lflag) {
+ sysnerr ((int) (line_tmp = ttyname (0)), "ttyname");
+ line = strrchr(line_tmp, '/');
+ if (line)
+ line = line + 1;
+ else
+ line = line_tmp;
+ }
+ current_time = time ((Time_t *) 0);
+ set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag);
+ if (!utmp_none) {
+#ifdef SYSV
+ utmpname (utmp_file);
+ setutent ();
+ (void) getutid (&utmp_entry);
+ pututline (&utmp_entry);
+ endutent ();
+#else
+ utmp = open (utmp_file, O_RDWR);
+ if (utmp != -1) {
+ syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek");
+ sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry))
+ == sizeof (utmp_entry), "write utmp entry");
+ close (utmp);
+ }
+#endif
+ }
+ if (!wtmp_none) {
+ wtmp = open (wtmp_file, O_WRONLY|O_APPEND);
+ if (wtmp != -1) {
+ sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry))
+ == sizeof (utmp_entry), "write wtmp entry");
+ close (wtmp);
+ }
+ }
+#ifndef NO_LASTLOG
+ if (aflag && !llog_none) {
+ int llog;
+ struct passwd *pwd = getpwnam(user_name);
+
+ sysnerr( pwd != NULL, "get user id");
+ llog = open (llog_file, O_WRONLY);
+
+ if (llog != -1) {
+ struct lastlog ll;
+
+ bzero((char *)&ll, sizeof(ll));
+ ll.ll_time = current_time;
+ if (line)
+ (void) strncpy (ll.ll_line, line, sizeof (ll.ll_line));
+ if (host_name)
+ (void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host));
+
+ sysnerr (lseek(llog, (long) pwd->pw_uid*sizeof(ll), 0) != -1, "seeking lastlog entry");
+ sysnerr (write (llog, (char *) &ll, sizeof (ll))
+ == sizeof (ll), "write lastlog entry");
+ close (llog);
+ }
+ }
+#endif
+ return 0;
+}
+
+/*
+ * fill in the appropriate records of the utmp entry
+ */
+
+set_utmp (u, line, user, host, date, addp)
+struct utmp *u;
+char *line, *user, *host;
+Time_t date;
+{
+ if (line)
+ (void) strncpy (u->ut_line, line, sizeof (u->ut_line));
+ else
+ bzero (u->ut_line, sizeof (u->ut_line));
+ if (addp && user)
+ (void) strncpy (u->ut_name, user, sizeof (u->ut_name));
+ else
+ bzero (u->ut_name, sizeof (u->ut_name));
+#ifdef SYSV
+ if (line) {
+ int i;
+ /*
+ * this is a bit crufty, but
+ * follows the apparent conventions in
+ * the ttys file. ut_id is only 4 bytes
+ * long, and the last 4 bytes of the line
+ * name are written into it, left justified.
+ */
+ i = strlen (line);
+ if (i >= sizeof (u->ut_id))
+ i -= sizeof (u->ut_id);
+ else
+ i = 0;
+ (void) strncpy (u->ut_id, line + i, sizeof (u->ut_id));
+ } else
+ bzero (u->ut_id, sizeof (u->ut_id));
+ if (addp) {
+ u->ut_pid = getppid ();
+ u->ut_type = USER_PROCESS;
+ } else {
+ u->ut_pid = 0;
+ u->ut_type = DEAD_PROCESS;
+ }
+#else
+ if (addp && host)
+ (void) strncpy (u->ut_host, host, sizeof (u->ut_host));
+ else
+ bzero (u->ut_host, sizeof (u->ut_host));
+#endif
+ u->ut_time = date;
+}
+
+#ifndef SYSV
+/*
+ * compute the slot-number for an X display. This is computed
+ * by counting the lines in /etc/ttys and adding the line-number
+ * that the display appears on in Xservers. This is a poor
+ * design, but is limited by the non-existant interface to utmp.
+ * If host_name is non-NULL, assume it contains the display name,
+ * otherwise use the tty_line argument (i.e., the tty name).
+ */
+
+Xslot (ttys_file, servers_file, tty_line, host_name, addp)
+char *ttys_file;
+char *servers_file;
+char *tty_line;
+char *host_name;
+int addp;
+{
+ FILE *ttys, *servers;
+ int c;
+ int slot = 1;
+ int column0 = 1;
+ char servers_line[1024];
+ char disp_name[512];
+ int len;
+ char *pos;
+
+ /* remove screen number from the display name */
+ strcpy(disp_name, host_name ? host_name : tty_line);
+ pos = strrchr(disp_name, ':');
+ if (pos) {
+ pos = strchr(pos, '.');
+ if (pos)
+ *pos = '\0';
+ }
+ sysnerr (ttys = fopen (ttys_file, "r"), ttys_file);
+ while ((c = getc (ttys)) != EOF)
+ if (c == '\n') {
+ ++slot;
+ column0 = 1;
+ } else
+ column0 = 0;
+ if (!column0)
+ ++slot;
+ (void) fclose (ttys);
+ sysnerr (servers = fopen (servers_file, "r"), servers_file);
+
+ len = strlen (disp_name);
+ column0 = 1;
+ while (fgets (servers_line, sizeof (servers_line), servers)) {
+ if (column0 && *servers_line != '#') {
+ if (!strncmp (disp_name, servers_line, len) &&
+ (servers_line[len] == ' ' ||
+ servers_line[len] == '\t'))
+ return slot;
+ ++slot;
+ }
+ if (servers_line[strlen(servers_line)-1] != '\n')
+ column0 = 0;
+ else
+ column0 = 1;
+ }
+ /*
+ * display not found in Xservers file - allocate utmp entry dinamically
+ */
+ return findslot (tty_line, host_name, addp, slot);
+}
+
+/*
+ * find a free utmp slot for the X display. This allocates a new entry
+ * past the regular tty entries if necessary, reusing existing entries
+ * (identified by (line,hostname)) if possible.
+ */
+findslot (line_name, host_name, addp, slot)
+char *line_name;
+char *host_name;
+int addp;
+int slot;
+{
+ int utmp;
+ struct utmp entry;
+ int found = 0;
+ int freeslot = -1;
+
+ syserr(utmp = open (utmp_file, O_RDONLY), "open utmp");
+
+ /*
+ * first, try to locate a previous entry for this display
+ * also record location of a free slots in case we need a new one
+ */
+ syserr ((int) lseek (utmp, (long) slot * sizeof (struct utmp), 0), "lseek");
+
+ if (!host_name)
+ host_name = "";
+
+ while (read (utmp, (char *) &entry, sizeof (entry)) == sizeof (entry)) {
+ if (strncmp(entry.ut_line, line_name,
+ sizeof(entry.ut_line)) == 0 &&
+ strncmp(entry.ut_host, host_name,
+ sizeof(entry.ut_host)) == 0) {
+ found = 1;
+ break;
+ }
+ if (freeslot < 0 && *entry.ut_name == '\0')
+ freeslot = slot;
+ ++slot;
+ }
+
+ close (utmp);
+
+ if (found)
+ return slot;
+ else if (!addp)
+ return 0; /* trying to delete a non-existing entry */
+ else if (freeslot < 0)
+ return slot; /* first slot past current entries */
+ else
+ return freeslot;
+}
+#endif