2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: account.c /main/6 1996/10/30 11:12:13 drk $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
33 * routines for handling accounting
35 * ex. utmp/wtmp/btmp, user-license restrictions,
40 /***************************************************************************
44 ***************************************************************************/
48 #include <X11/apollosys.h> /* for pid_t struct in hp-ux sys/types.h */
49 #include <sys/types.h>
51 #include <sys/types.h>
69 /***************************************************************************
71 * External declarations
73 ***************************************************************************/
74 #if defined(AIXV3) && !defined(_POWER)
76 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
81 /***************************************************************************
83 * Procedure declarations
85 ***************************************************************************/
86 #if defined(AIXV3) && !defined(_POWER)
87 void dt_lastlogin ( char * user, struct lastlogin * llogin);
93 /***************************************************************************
97 ***************************************************************************/
101 char rt_line[8]; /* tty name */
102 rgy_$login_name_t rt_name; /* user id (full SID) */
103 char rt_host[16]; /* hostname, if remote */
104 long rt_time; /* time on */
121 static struct lastlogin last_login;
126 /***************************************************************************
130 * update utmp/wtmp files.
131 ***************************************************************************/
133 Account( struct display *d, char *user, char *line, pid_t pid,
134 #if NeedWidePrototypes
138 #endif /* NeedWidePrototypes */
141 struct utmp utmp; /* local struct for new entry */
142 struct utmp *u; /* pointer to entry in utmp file */
145 char* user_str = user ? user : "NULL";
146 char* line_str = line ? line : "NULL";
155 if (d->utmpId == NULL) return;
159 case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
160 case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
161 case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
162 case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
163 default: strcpy(buf, "UNKNOWN"); break;
166 Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
167 d->utmpId, user_str, line_str, pid, buf);
170 PamAccounting("dtlogin", d->name, d->utmpId, user,
171 line, pid, type, exitcode);
174 solaris_accounting("dtlogin", d->name, d->utmpId, user,
175 line, pid, type, exitcode);
182 bzero(&utmp, sizeof(struct utmp));
184 strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
185 utmp.ut_type = LOGIN_PROCESS;
188 if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
191 * make sure process ID's match if this is DEAD_PROCESS...
192 * don't update an already DEAD_PROCESS...
195 if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
196 (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) {
204 * fill in required fields of utmp structure...
206 * Note: for USER_PRCESS the "e_exit" field is overloaded to contain
207 * the method for counting this user. This is used later to
208 * determine if restricted user licenses have been exceeded.
209 * Currently, an unlimited number of foreign displays can log in.
212 if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
216 For AIX the Init process writes the exact mapped device name for console
217 to the utmp file (like hft/0), if a getty on /dev/console record exists
218 in the Inittab file.Hitherto, we need to have a similar logic to make
219 sure for having the correct entry in the utmp file in order for the correct
220 operation of the GettyRunning function. It should be noted that by having
221 the correct value in the d->gettyLine field, the utmp file eventuallly
222 updated by the Account function in dm.c will have the right value. And
223 thus the GettyRunning function returns the appropriate value. So, it
224 is important that the following logic be included here for AIX platform
226 Raghu Krovvidi 07.06.93
229 if (!strcmp(line,"console")) {
233 fd = open("/dev/console",O_RDONLY);
236 strcpy(u->ut_line,ttynm);
240 strncpy(u->ut_line, line, sizeof(u->ut_line));
243 strncpy(u->ut_line, line, sizeof(u->ut_line));
246 if (pid ) u->ut_pid = pid;
249 if (type == DEAD_PROCESS) {
250 u->ut_exit.e_termination = waitSig(exitcode);
251 u->ut_exit.e_exit = waitCode(exitcode);
253 (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
257 if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
259 strncpy(u->ut_host, d->name, sizeof(u->ut_host));
266 if (type == USER_PROCESS)
267 u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
270 (void) time(&u->ut_time);
275 * (Do not close utmp yet. If "u" points to the static structure, it is
276 * cleared upon close. This does not bode well for the following write
284 * write the same entry to wtmp...
287 if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
288 write(fd, u, sizeof(utmp));
300 /* Now fill in the "rgy utmp" struct */
301 if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
302 bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
303 rtmp.rt_time = u->ut_time;
306 /* Write entry to rtmp */
307 tty_slot = ttyslot();
309 if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
310 lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
311 write(rtmp_fd, (char *) r, sizeof(struct rtmp));
315 #if defined(AIXV3) && !defined(_POWER)
316 /* Log the lastlogin data .. RK 09.13.93 */
317 /** in AIX 4.1 this is taken care of during authentication **/
318 if(type == USER_PROCESS) {
320 char tempTtyName[128];
323 GetLoginInfo(d, &loginType, tempTtyName, &hostname);
324 time(&last_login.stime);
327 Debug("tty_last_login is (line=%s)\n",line);
328 last_login.stty = (char *)malloc(strlen(line) + 1);
329 strcpy(last_login.stty,line);
331 last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
332 strcpy(last_login.stty,tempTtyName);
335 last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
336 if (hostname == NULL) {
337 gethostname (last_login.shost , MAXHOSTNAMELEN);
339 strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
340 last_login.shost[MAXHOSTNAMELEN -1] = '\0';
343 Debug("logging lastlogin entry (user=%s)\n",user);
344 dt_lastlogin(user,&last_login);
345 free(last_login.stty);
346 free(last_login.shost);
356 /***************************************************************************
360 * see if a particular utmp ID is available
362 * return codes: 0 = ID is in use
364 ***************************************************************************/
367 UtmpIdOpen( char *utmpId )
369 struct utmp *u; /* pointer to entry in utmp file */
370 int status = 1; /* return code */
372 while ( (u = getutent()) != NULL ) {
374 if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
375 u->ut_type != DEAD_PROCESS ) {
388 #if defined(AIXV3) && !defined(_POWER)
389 void dt_lastlogin ( user, llogin)
391 struct lastlogin * llogin;
396 * We are loading all the lastlogin info into a struct and then dealing
397 * with that so if the technique of storing the values is redone it
400 /* set id back to root */
403 * Open up the user data base
405 setuserdb(S_READ | S_WRITE);
408 * setting new unsuccessful login attempts times
412 * Get the old Failure count and increment it
414 if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
417 llogin->fcount = (int)tmp_int;
420 * put all the new data
422 putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
424 putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
426 putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
428 putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
429 putuserattr(user, NULL, NULL, SEC_COMMIT);
432 * Close data base and zero out indicator fields
439 * New Successful login data
442 putuserattr(user, S_LASTTIME, (void *)llogin->stime,
444 putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
445 Debug("hostname logged is %s\n",llogin->shost);
446 putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
447 putuserattr(user, S_ULOGCNT, 0, SEC_INT);
448 putuserattr(user, NULL, NULL, SEC_COMMIT);