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 libraries 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 ***************************************************************************/
46 #include <sys/types.h>
54 #if defined(__FreeBSD__) && OSMAJORVERSION > 8
68 /***************************************************************************
70 * External declarations
72 ***************************************************************************/
73 #if defined(AIXV3) && !defined(_POWER)
75 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
80 /***************************************************************************
82 * Procedure declarations
84 ***************************************************************************/
85 #if defined(AIXV3) && !defined(_POWER)
86 void dt_lastlogin ( char * user, struct lastlogin * llogin);
92 /***************************************************************************
96 ***************************************************************************/
100 char rt_line[8]; /* tty name */
101 rgy_$login_name_t rt_name; /* user id (full SID) */
102 char rt_host[16]; /* hostname, if remote */
103 long rt_time; /* time on */
120 static struct lastlogin last_login;
125 /***************************************************************************
129 * update utmp/wtmp files.
130 ***************************************************************************/
132 Account( struct display *d, char *user, char *line, pid_t pid,
133 #if NeedWidePrototypes
137 #endif /* NeedWidePrototypes */
140 #if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
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) - 1);
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) snprintf(u->ut_user, sizeof(u->ut_user), "%s", 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 snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
243 snprintf(u->ut_line, sizeof(u->ut_line), "%s", 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 snprintf(u->ut_host, sizeof(u->ut_host), "%s", d->name);
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 if(-1 == write(fd, u, sizeof(utmp))) {
289 perror(strerror(errno));
302 /* Now fill in the "rgy utmp" struct */
303 if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
304 bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
305 rtmp.rt_time = u->ut_time;
308 /* Write entry to rtmp */
309 tty_slot = ttyslot();
311 if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
312 lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
313 write(rtmp_fd, (char *) r, sizeof(struct rtmp));
317 #if defined(AIXV3) && !defined(_POWER)
318 /* Log the lastlogin data .. RK 09.13.93 */
319 /** in AIX 4.1 this is taken care of during authentication **/
320 if(type == USER_PROCESS) {
322 char tempTtyName[128];
325 GetLoginInfo(d, &loginType, tempTtyName, &hostname);
326 time(&last_login.stime);
329 Debug("tty_last_login is (line=%s)\n",line);
330 last_login.stty = (char *)malloc(strlen(line) + 1);
331 strcpy(last_login.stty,line);
333 last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
334 strcpy(last_login.stty,tempTtyName);
337 last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
338 if (hostname == NULL) {
339 gethostname (last_login.shost , MAXHOSTNAMELEN);
341 strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
342 last_login.shost[MAXHOSTNAMELEN -1] = '\0';
345 Debug("logging lastlogin entry (user=%s)\n",user);
346 dt_lastlogin(user,&last_login);
347 free(last_login.stty);
348 free(last_login.shost);
353 #endif /* !CSRG_BASED */
359 /***************************************************************************
363 * see if a particular utmp ID is available
365 * return codes: 0 = ID is in use
367 ***************************************************************************/
370 UtmpIdOpen( char *utmpId )
372 struct utmp *u; /* pointer to entry in utmp file */
373 int status = 1; /* return code */
375 #if !defined(CSRG_BASED)
376 while ( (u = getutent()) != NULL ) {
378 if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
379 u->ut_type != DEAD_PROCESS ) {
393 #if defined(AIXV3) && !defined(_POWER)
394 void dt_lastlogin ( user, llogin)
396 struct lastlogin * llogin;
401 * We are loading all the lastlogin info into a struct and then dealing
402 * with that so if the technique of storing the values is redone it
405 /* set id back to root */
408 * Open up the user data base
410 setuserdb(S_READ | S_WRITE);
413 * setting new unsuccessful login attempts times
417 * Get the old Failure count and increment it
419 if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
422 llogin->fcount = (int)tmp_int;
425 * put all the new data
427 putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
429 putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
431 putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
433 putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
434 putuserattr(user, NULL, NULL, SEC_COMMIT);
437 * Close data base and zero out indicator fields
444 * New Successful login data
447 putuserattr(user, S_LASTTIME, (void *)llogin->stime,
449 putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
450 Debug("hostname logged is %s\n",llogin->shost);
451 putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
452 putuserattr(user, S_ULOGCNT, 0, SEC_INT);
453 putuserattr(user, NULL, NULL, SEC_COMMIT);