1 /* $XConsortium: account.c /main/6 1996/10/30 11:12:13 drk $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
4 * (c) Copyright 1993, 1994 International Business Machines Corp. *
5 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
6 * (c) Copyright 1993, 1994 Novell, Inc. *
11 * routines for handling accounting
13 * ex. utmp/wtmp/btmp, user-license restrictions,
18 /***************************************************************************
22 ***************************************************************************/
26 #include <X11/apollosys.h> /* for pid_t struct in hp-ux sys/types.h */
27 #include <sys/types.h>
29 #include <sys/types.h>
47 /***************************************************************************
49 * External declarations
51 ***************************************************************************/
52 #if defined(AIXV3) && !defined(_POWER)
54 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
59 /***************************************************************************
61 * Procedure declarations
63 ***************************************************************************/
64 #if defined(AIXV3) && !defined(_POWER)
65 void dt_lastlogin ( char * user, struct lastlogin * llogin);
71 /***************************************************************************
75 ***************************************************************************/
79 char rt_line[8]; /* tty name */
80 rgy_$login_name_t rt_name; /* user id (full SID) */
81 char rt_host[16]; /* hostname, if remote */
82 long rt_time; /* time on */
99 static struct lastlogin last_login;
104 /***************************************************************************
108 * update utmp/wtmp files.
109 ***************************************************************************/
111 Account( struct display *d, char *user, char *line, pid_t pid,
112 #if NeedWidePrototypes
116 #endif /* NeedWidePrototypes */
119 struct utmp utmp; /* local struct for new entry */
120 struct utmp *u; /* pointer to entry in utmp file */
123 char* user_str = user ? user : "NULL";
124 char* line_str = line ? line : "NULL";
133 if (d->utmpId == NULL) return;
137 case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
138 case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
139 case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
140 case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
141 default: strcpy(buf, "UNKNOWN"); break;
144 Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
145 d->utmpId, user_str, line_str, pid, buf);
148 PamAccounting("dtlogin", d->name, d->utmpId, user,
149 line, pid, type, exitcode);
152 solaris_accounting("dtlogin", d->name, d->utmpId, user,
153 line, pid, type, exitcode);
160 bzero(&utmp, sizeof(struct utmp));
162 strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
163 utmp.ut_type = LOGIN_PROCESS;
166 if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
169 * make sure process ID's match if this is DEAD_PROCESS...
170 * don't update an already DEAD_PROCESS...
173 if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
174 (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) {
182 * fill in required fields of utmp structure...
184 * Note: for USER_PRCESS the "e_exit" field is overloaded to contain
185 * the method for counting this user. This is used later to
186 * determine if restricted user licenses have been exceeded.
187 * Currently, an unlimited number of foreign displays can log in.
190 if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
194 For AIX the Init process writes the exact mapped device name for console
195 to the utmp file (like hft/0), if a getty on /dev/console record exists
196 in the Inittab file.Hitherto, we need to have a similar logic to make
197 sure for having the correct entry in the utmp file in order for the correct
198 operation of the GettyRunning function. It should be noted that by having
199 the correct value in the d->gettyLine field, the utmp file eventuallly
200 updated by the Account function in dm.c will have the right value. And
201 thus the GettyRunning function returns the appropriate value. So, it
202 is important that the following logic be included here for AIX platform
204 Raghu Krovvidi 07.06.93
207 if (!strcmp(line,"console")) {
211 fd = open("/dev/console",O_RDONLY);
214 strcpy(u->ut_line,ttynm);
218 strncpy(u->ut_line, line, sizeof(u->ut_line));
221 strncpy(u->ut_line, line, sizeof(u->ut_line));
224 if (pid ) u->ut_pid = pid;
227 if (type == DEAD_PROCESS) {
228 u->ut_exit.e_termination = waitSig(exitcode);
229 u->ut_exit.e_exit = waitCode(exitcode);
231 (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
235 if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
237 strncpy(u->ut_host, d->name, sizeof(u->ut_host));
244 if (type == USER_PROCESS)
245 u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
248 (void) time(&u->ut_time);
253 * (Do not close utmp yet. If "u" points to the static structure, it is
254 * cleared upon close. This does not bode well for the following write
262 * write the same entry to wtmp...
265 if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
266 write(fd, u, sizeof(utmp));
278 /* Now fill in the "rgy utmp" struct */
279 if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
280 bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
281 rtmp.rt_time = u->ut_time;
284 /* Write entry to rtmp */
285 tty_slot = ttyslot();
287 if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
288 lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
289 write(rtmp_fd, (char *) r, sizeof(struct rtmp));
293 #if defined(AIXV3) && !defined(_POWER)
294 /* Log the lastlogin data .. RK 09.13.93 */
295 /** in AIX 4.1 this is taken care of during authentication **/
296 if(type == USER_PROCESS) {
298 char tempTtyName[128];
301 GetLoginInfo(d, &loginType, tempTtyName, &hostname);
302 time(&last_login.stime);
305 Debug("tty_last_login is (line=%s)\n",line);
306 last_login.stty = (char *)malloc(strlen(line) + 1);
307 strcpy(last_login.stty,line);
309 last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
310 strcpy(last_login.stty,tempTtyName);
313 last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
314 if (hostname == NULL) {
315 gethostname (last_login.shost , MAXHOSTNAMELEN);
317 strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
318 last_login.shost[MAXHOSTNAMELEN -1] = '\0';
321 Debug("logging lastlogin entry (user=%s)\n",user);
322 dt_lastlogin(user,&last_login);
323 free(last_login.stty);
324 free(last_login.shost);
334 /***************************************************************************
338 * see if a particular utmp ID is available
340 * return codes: 0 = ID is in use
342 ***************************************************************************/
345 UtmpIdOpen( char *utmpId )
347 struct utmp *u; /* pointer to entry in utmp file */
348 int status = 1; /* return code */
350 while ( (u = getutent()) != NULL ) {
352 if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
353 u->ut_type != DEAD_PROCESS ) {
366 #if defined(AIXV3) && !defined(_POWER)
367 void dt_lastlogin ( user, llogin)
369 struct lastlogin * llogin;
374 * We are loading all the lastlogin info into a struct and then dealing
375 * with that so if the technique of storing the values is redone it
378 /* set id back to root */
381 * Open up the user data base
383 setuserdb(S_READ | S_WRITE);
386 * setting new unsuccessful login attempts times
390 * Get the old Failure count and increment it
392 if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
395 llogin->fcount = (int)tmp_int;
398 * put all the new data
400 putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
402 putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
404 putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
406 putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
407 putuserattr(user, NULL, NULL, SEC_COMMIT);
410 * Close data base and zero out indicator fields
417 * New Successful login data
420 putuserattr(user, S_LASTTIME, (void *)llogin->stime,
422 putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
423 Debug("hostname logged is %s\n",llogin->shost);
424 putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
425 putuserattr(user, S_ULOGCNT, 0, SEC_INT);
426 putuserattr(user, NULL, NULL, SEC_COMMIT);