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>
60 #if defined(__FreeBSD__) && OSMAJORVERSION > 8
74 /***************************************************************************
76 * External declarations
78 ***************************************************************************/
79 #if defined(AIXV3) && !defined(_POWER)
81 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
86 /***************************************************************************
88 * Procedure declarations
90 ***************************************************************************/
91 #if defined(AIXV3) && !defined(_POWER)
92 void dt_lastlogin ( char * user, struct lastlogin * llogin);
98 /***************************************************************************
102 ***************************************************************************/
106 char rt_line[8]; /* tty name */
107 rgy_$login_name_t rt_name; /* user id (full SID) */
108 char rt_host[16]; /* hostname, if remote */
109 long rt_time; /* time on */
126 static struct lastlogin last_login;
131 /***************************************************************************
135 * update utmp/wtmp files.
136 ***************************************************************************/
138 Account( struct display *d, char *user, char *line, pid_t pid,
139 #if NeedWidePrototypes
143 #endif /* NeedWidePrototypes */
146 #if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
147 struct utmp utmp; /* local struct for new entry */
148 struct utmp *u; /* pointer to entry in utmp file */
151 char* user_str = user ? user : "NULL";
152 char* line_str = line ? line : "NULL";
161 if (d->utmpId == NULL) return;
165 case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
166 case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
167 case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
168 case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
169 default: strcpy(buf, "UNKNOWN"); break;
172 Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
173 d->utmpId, user_str, line_str, pid, buf);
176 PamAccounting("dtlogin", d->name, d->utmpId, user,
177 line, pid, type, exitcode);
180 solaris_accounting("dtlogin", d->name, d->utmpId, user,
181 line, pid, type, exitcode);
188 bzero(&utmp, sizeof(struct utmp));
190 strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
191 utmp.ut_type = LOGIN_PROCESS;
194 if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
197 * make sure process ID's match if this is DEAD_PROCESS...
198 * don't update an already DEAD_PROCESS...
201 if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
202 (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) {
210 * fill in required fields of utmp structure...
212 * Note: for USER_PRCESS the "e_exit" field is overloaded to contain
213 * the method for counting this user. This is used later to
214 * determine if restricted user licenses have been exceeded.
215 * Currently, an unlimited number of foreign displays can log in.
218 if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
222 For AIX the Init process writes the exact mapped device name for console
223 to the utmp file (like hft/0), if a getty on /dev/console record exists
224 in the Inittab file.Hitherto, we need to have a similar logic to make
225 sure for having the correct entry in the utmp file in order for the correct
226 operation of the GettyRunning function. It should be noted that by having
227 the correct value in the d->gettyLine field, the utmp file eventuallly
228 updated by the Account function in dm.c will have the right value. And
229 thus the GettyRunning function returns the appropriate value. So, it
230 is important that the following logic be included here for AIX platform
232 Raghu Krovvidi 07.06.93
235 if (!strcmp(line,"console")) {
239 fd = open("/dev/console",O_RDONLY);
242 strcpy(u->ut_line,ttynm);
246 strncpy(u->ut_line, line, sizeof(u->ut_line));
249 strncpy(u->ut_line, line, sizeof(u->ut_line));
252 if (pid ) u->ut_pid = pid;
255 if (type == DEAD_PROCESS) {
256 u->ut_exit.e_termination = waitSig(exitcode);
257 u->ut_exit.e_exit = waitCode(exitcode);
259 (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
263 if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
265 strncpy(u->ut_host, d->name, sizeof(u->ut_host));
272 if (type == USER_PROCESS)
273 u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
276 (void) time(&u->ut_time);
281 * (Do not close utmp yet. If "u" points to the static structure, it is
282 * cleared upon close. This does not bode well for the following write
290 * write the same entry to wtmp...
293 if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
294 write(fd, u, sizeof(utmp));
306 /* Now fill in the "rgy utmp" struct */
307 if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
308 bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
309 rtmp.rt_time = u->ut_time;
312 /* Write entry to rtmp */
313 tty_slot = ttyslot();
315 if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
316 lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
317 write(rtmp_fd, (char *) r, sizeof(struct rtmp));
321 #if defined(AIXV3) && !defined(_POWER)
322 /* Log the lastlogin data .. RK 09.13.93 */
323 /** in AIX 4.1 this is taken care of during authentication **/
324 if(type == USER_PROCESS) {
326 char tempTtyName[128];
329 GetLoginInfo(d, &loginType, tempTtyName, &hostname);
330 time(&last_login.stime);
333 Debug("tty_last_login is (line=%s)\n",line);
334 last_login.stty = (char *)malloc(strlen(line) + 1);
335 strcpy(last_login.stty,line);
337 last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
338 strcpy(last_login.stty,tempTtyName);
341 last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
342 if (hostname == NULL) {
343 gethostname (last_login.shost , MAXHOSTNAMELEN);
345 strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
346 last_login.shost[MAXHOSTNAMELEN -1] = '\0';
349 Debug("logging lastlogin entry (user=%s)\n",user);
350 dt_lastlogin(user,&last_login);
351 free(last_login.stty);
352 free(last_login.shost);
357 #endif /* !CSRG_BASED */
363 /***************************************************************************
367 * see if a particular utmp ID is available
369 * return codes: 0 = ID is in use
371 ***************************************************************************/
374 UtmpIdOpen( char *utmpId )
376 struct utmp *u; /* pointer to entry in utmp file */
377 int status = 1; /* return code */
379 #if !defined(CSRG_BASED)
380 while ( (u = getutent()) != NULL ) {
382 if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
383 u->ut_type != DEAD_PROCESS ) {
397 #if defined(AIXV3) && !defined(_POWER)
398 void dt_lastlogin ( user, llogin)
400 struct lastlogin * llogin;
405 * We are loading all the lastlogin info into a struct and then dealing
406 * with that so if the technique of storing the values is redone it
409 /* set id back to root */
412 * Open up the user data base
414 setuserdb(S_READ | S_WRITE);
417 * setting new unsuccessful login attempts times
421 * Get the old Failure count and increment it
423 if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
426 llogin->fcount = (int)tmp_int;
429 * put all the new data
431 putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
433 putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
435 putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
437 putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
438 putuserattr(user, NULL, NULL, SEC_COMMIT);
441 * Close data base and zero out indicator fields
448 * New Successful login data
451 putuserattr(user, S_LASTTIME, (void *)llogin->stime,
453 putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
454 Debug("hostname logged is %s\n",llogin->shost);
455 putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
456 putuserattr(user, S_ULOGCNT, 0, SEC_INT);
457 putuserattr(user, NULL, NULL, SEC_COMMIT);