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) - 1);
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 snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
249 snprintf(u->ut_line, sizeof(u->ut_line), "%s", 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 snprintf(u->ut_host, sizeof(u->ut_host), "%s", d->name);
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 if(-1 == write(fd, u, sizeof(utmp))) {
295 perror(strerror(errno));
308 /* Now fill in the "rgy utmp" struct */
309 if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
310 bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
311 rtmp.rt_time = u->ut_time;
314 /* Write entry to rtmp */
315 tty_slot = ttyslot();
317 if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
318 lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
319 write(rtmp_fd, (char *) r, sizeof(struct rtmp));
323 #if defined(AIXV3) && !defined(_POWER)
324 /* Log the lastlogin data .. RK 09.13.93 */
325 /** in AIX 4.1 this is taken care of during authentication **/
326 if(type == USER_PROCESS) {
328 char tempTtyName[128];
331 GetLoginInfo(d, &loginType, tempTtyName, &hostname);
332 time(&last_login.stime);
335 Debug("tty_last_login is (line=%s)\n",line);
336 last_login.stty = (char *)malloc(strlen(line) + 1);
337 strcpy(last_login.stty,line);
339 last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
340 strcpy(last_login.stty,tempTtyName);
343 last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
344 if (hostname == NULL) {
345 gethostname (last_login.shost , MAXHOSTNAMELEN);
347 strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
348 last_login.shost[MAXHOSTNAMELEN -1] = '\0';
351 Debug("logging lastlogin entry (user=%s)\n",user);
352 dt_lastlogin(user,&last_login);
353 free(last_login.stty);
354 free(last_login.shost);
359 #endif /* !CSRG_BASED */
365 /***************************************************************************
369 * see if a particular utmp ID is available
371 * return codes: 0 = ID is in use
373 ***************************************************************************/
376 UtmpIdOpen( char *utmpId )
378 struct utmp *u; /* pointer to entry in utmp file */
379 int status = 1; /* return code */
381 #if !defined(CSRG_BASED)
382 while ( (u = getutent()) != NULL ) {
384 if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
385 u->ut_type != DEAD_PROCESS ) {
399 #if defined(AIXV3) && !defined(_POWER)
400 void dt_lastlogin ( user, llogin)
402 struct lastlogin * llogin;
407 * We are loading all the lastlogin info into a struct and then dealing
408 * with that so if the technique of storing the values is redone it
411 /* set id back to root */
414 * Open up the user data base
416 setuserdb(S_READ | S_WRITE);
419 * setting new unsuccessful login attempts times
423 * Get the old Failure count and increment it
425 if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
428 llogin->fcount = (int)tmp_int;
431 * put all the new data
433 putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
435 putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
437 putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
439 putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
440 putuserattr(user, NULL, NULL, SEC_COMMIT);
443 * Close data base and zero out indicator fields
450 * New Successful login data
453 putuserattr(user, S_LASTTIME, (void *)llogin->stime,
455 putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
456 Debug("hostname logged is %s\n",llogin->shost);
457 putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
458 putuserattr(user, S_ULOGCNT, 0, SEC_INT);
459 putuserattr(user, NULL, NULL, SEC_COMMIT);