summaryrefslogtreecommitdiffstats
path: root/src/util/pty/update_utmp.c
blob: ce8b546f20c5623140a86b22e73c73558e0d737c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
 * pty_update_utmp: Update or create a utmp entry
 * 
 * Copyright 1995 by the Massachusetts Institute of Technology.
 *
 * 
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of
 * M.I.T. not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission.  M.I.T. makes no representations about the suitability
 * of this software for any purpose.  It is provided "as is" without
 * express or implied warranty.
 * 
 */

#include <com_err.h>
#include "libpty.h"
#include "pty-int.h"

#if !defined(UTMP_FILE) && defined(_PATH_UTMP)
#define UTMP_FILE _PATH_UTMP
#endif

/* if it is *still* missing, assume SunOS */
#ifndef UTMP_FILE
#define	UTMP_FILE	"/etc/utmp"
#endif
#ifndef NO_UT_PID
#define WTMP_REQUIRES_USERNAME
#endif
long pty_update_utmp (process_type, pid, username, line, host, flags)
    int process_type;
    int pid;
    char *username, *line, *host;
    int flags;
{
    struct utmp ent, ut;
#ifndef HAVE_SETUTENT
    struct stat statb;
    int tty;
#endif
#ifdef HAVE_SETUTXENT
    struct utmpx utx;
#endif
#ifndef NO_UT_PID
    char *tmpx;
    char utmp_id[5];
#endif
    char userbuf[32];
    int fd;

    strncpy(ent.ut_line, line+sizeof("/dev/")-1, sizeof(ent.ut_line));
    ent.ut_time = time(0);
#ifdef NO_UT_PID
    if (process_type == PTY_LOGIN_PROCESS)
	return 0;
#else /* NO_UT_PID */
    ent.ut_pid = pid;
    switch (process_type) {
    case PTY_LOGIN_PROCESS:
	ent.ut_type = LOGIN_PROCESS;
	break;
    case PTY_USER_PROCESS:
	ent.ut_type = USER_PROCESS;
	break;
    case PTY_DEAD_PROCESS:
	ent.ut_type = DEAD_PROCESS;
	break;
    default:
	return PTY_UPDATE_UTMP_PROCTYPE_INVALID;
    }
#endif /*NO_UT_PID*/

#ifndef NO_UT_HOST
    if (host)
	strncpy(ent.ut_host, host, sizeof(ent.ut_host));
    else
	ent.ut_host[0] = '\0';
#endif

#ifndef NO_UT_PID
    if (!strcmp (line, "/dev/console")) {
#if (defined(sun) && defined(__SVR4))
      strncpy (ent.ut_id, "co", 4);
#else
      strncpy (ent.ut_id, "cons", 4);
#endif
    } else {
      tmpx = line + strlen(line)-1;
      if (*(tmpx-1) != '/') tmpx--; /* last two characters, unless it's a / */
#ifdef __hpux
      strcpy(utmp_id, tmpx);
#else
      sprintf(utmp_id, "kl%s", tmpx);
#endif
      strncpy(ent.ut_id, utmp_id, sizeof(ent.ut_id));
    }
    strncpy(ent.ut_user, username, sizeof(ent.ut_user));
#else
    strncpy(ent.ut_name, username, sizeof(ent.ut_name));
#endif
    if(username[0])
	strncpy(userbuf, username, sizeof(userbuf));
    else userbuf[0] = '\0';

#ifdef HAVE_SETUTENT

    utmpname(UTMP_FILE);
    setutent();
/* If we need to preserve the user name in the wtmp structure and
 * Our flags tell us we can obtain it from the utmp and we succeed in
 * obtaining it, we then save the utmp structure we obtain, write
 * out the utmp structure and change the username pointer so  it is used by
 * update_wtmp.*/
#ifdef WTMP_REQUIRES_USERNAME
    if (( !username[0]) && (flags&PTY_UTMP_USERNAME_VALID)
	&&line)  
	{
	  struct utmp *utptr;
	  strncpy(ut.ut_line, line, sizeof(ut.ut_line));
	  utptr = getutline(&ut);
	  if (utptr)
	    strncpy(userbuf,utptr->ut_user,sizeof(ut.ut_user));
	}
#endif

    pututline(&ent);
    endutent();
    
#ifdef HAVE_SETUTXENT
    setutxent();
#ifdef HAVE_GETUTMPX
    getutmpx(&ent, &utx);
#else
    /* For platforms like HPUX and Dec Unix which don't have getutmpx */
    strncpy(utx.ut_user, ent.ut_user, sizeof(ent.ut_user));
    strncpy(utx.ut_id, ent.ut_id, sizeof(ent.ut_id));
    strncpy(utx.ut_line, ent.ut_line, sizeof(ent.ut_line));
    utx.ut_pid = pid;		/* kludge for Irix, etc. to avoid trunc. */
    utx.ut_type = ent.ut_type;
#ifdef UT_EXIT_STRUCTURE_DIFFER
    utx.ut_exit.ut_exit = ent.ut_exit.e_exit;
#else
/* KLUDGE for now; eventually this will be a feature test... See PR#[40] */
#ifdef __hpux	
    utx.ut_exit.__e_termination = ent.ut_exit.e_termination;
    utx.ut_exit.__e_exit = ent.ut_exit.e_exit;
#else
    /*xxx do nothing for now; we don't even know the structure member exists*/
#endif
#endif
    utx.ut_tv.tv_sec = ent.ut_time;
    utx.ut_tv.tv_usec = 0;
#endif
    if (host)
      strncpy(utx.ut_host, host, sizeof(utx.ut_host));
    else
      utx.ut_host[0] = 0;
    pututxline(&utx);
    endutxent();
#endif /* HAVE_SETUTXENT */

#else /* HAVE_SETUTENT */
    if (flags&PTY_TTYSLOT_USABLE) 
	tty = ttyslot();
    else {
      int lc;
      tty = -1;
      if ((fd = open(UTMP_FILE, O_RDWR)) < 0)
	return errno;
      for (lc = 0;
	   lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET) != -1;
	   lc++) {
	if (read(fd, (char *) &ut, sizeof(struct utmp)) != sizeof(struct utmp))
	  break;
	if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
	  tty = lc;
#ifdef WTMP_REQUIRES_USERNAME
	  if (!username&&(flags&PTY_UTMP_USERNAME_VALID))
	    strncpy(userbuf, ut.ut_user, sizeof(ut.ut_user));
#endif
	  break;
	}
      }
      close(fd);
    }
    
    if (tty > 0 && (fd = open(UTMP_FILE, O_WRONLY, 0)) >= 0) {
      (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
      (void)write(fd, (char *)&ent, sizeof(struct utmp));
      (void)close(fd);
    }


#endif /* HAVE_SETUTENT */

    /* Don't record LOGIN_PROCESS entries. */
    if (process_type == PTY_LOGIN_PROCESS)
      return 0;
    else
      return ptyint_update_wtmp(&ent, host, userbuf);
}