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 #if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
142 struct utmp utmp; /* local struct for new entry */
143 struct utmp *u; /* pointer to entry in utmp file */
146 char* user_str = user ? user : "NULL";
147 char* line_str = line ? line : "NULL";
156 if (d->utmpId == NULL) return;
160 case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
161 case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
162 case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
163 case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
164 default: strcpy(buf, "UNKNOWN"); break;
167 Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
168 d->utmpId, user_str, line_str, pid, buf);
171 PamAccounting("dtlogin", d->name, d->utmpId, user,
172 line, pid, type, exitcode);
175 solaris_accounting("dtlogin", d->name, d->utmpId, user,
176 line, pid, type, exitcode);
183 bzero(&utmp, sizeof(struct utmp));
185 strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
186 utmp.ut_type = LOGIN_PROCESS;
189 if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
192 * make sure process ID's match if this is DEAD_PROCESS...
193 * don't update an already DEAD_PROCESS...
196 if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
197 (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) {
205 * fill in required fields of utmp structure...
207 * Note: for USER_PRCESS the "e_exit" field is overloaded to contain
208 * the method for counting this user. This is used later to
209 * determine if restricted user licenses have been exceeded.
210 * Currently, an unlimited number of foreign displays can log in.
213 if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
217 For AIX the Init process writes the exact mapped device name for console
218 to the utmp file (like hft/0), if a getty on /dev/console record exists
219 in the Inittab file.Hitherto, we need to have a similar logic to make
220 sure for having the correct entry in the utmp file in order for the correct
221 operation of the GettyRunning function. It should be noted that by having
222 the correct value in the d->gettyLine field, the utmp file eventuallly
223 updated by the Account function in dm.c will have the right value. And
224 thus the GettyRunning function returns the appropriate value. So, it
225 is important that the following logic be included here for AIX platform
227 Raghu Krovvidi 07.06.93
230 if (!strcmp(line,"console")) {
234 fd = open("/dev/console",O_RDONLY);
237 strcpy(u->ut_line,ttynm);
241 strncpy(u->ut_line, line, sizeof(u->ut_line));
244 strncpy(u->ut_line, line, sizeof(u->ut_line));
247 if (pid ) u->ut_pid = pid;
250 if (type == DEAD_PROCESS) {
251 u->ut_exit.e_termination = waitSig(exitcode);
252 u->ut_exit.e_exit = waitCode(exitcode);
254 (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
258 if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
260 strncpy(u->ut_host, d->name, sizeof(u->ut_host));
267 if (type == USER_PROCESS)
268 u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
271 (void) time(&u->ut_time);
276 * (Do not close utmp yet. If "u" points to the static structure, it is
277 * cleared upon close. This does not bode well for the following write
285 * write the same entry to wtmp...
288 if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
289 write(fd, u, sizeof(utmp));
301 /* Now fill in the "rgy utmp" struct */
302 if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
303 bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
304 rtmp.rt_time = u->ut_time;
307 /* Write entry to rtmp */
308 tty_slot = ttyslot();
310 if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
311 lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
312 write(rtmp_fd, (char *) r, sizeof(struct rtmp));
316 #if defined(AIXV3) && !defined(_POWER)
317 /* Log the lastlogin data .. RK 09.13.93 */
318 /** in AIX 4.1 this is taken care of during authentication **/
319 if(type == USER_PROCESS) {
321 char tempTtyName[128];
324 GetLoginInfo(d, &loginType, tempTtyName, &hostname);
325 time(&last_login.stime);
328 Debug("tty_last_login is (line=%s)\n",line);
329 last_login.stty = (char *)malloc(strlen(line) + 1);
330 strcpy(last_login.stty,line);
332 last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
333 strcpy(last_login.stty,tempTtyName);
336 last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
337 if (hostname == NULL) {
338 gethostname (last_login.shost , MAXHOSTNAMELEN);
340 strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
341 last_login.shost[MAXHOSTNAMELEN -1] = '\0';
344 Debug("logging lastlogin entry (user=%s)\n",user);
345 dt_lastlogin(user,&last_login);
346 free(last_login.stty);
347 free(last_login.shost);
352 #endif /* !CSRG_BASED */
358 /***************************************************************************
362 * see if a particular utmp ID is available
364 * return codes: 0 = ID is in use
366 ***************************************************************************/
369 UtmpIdOpen( char *utmpId )
371 struct utmp *u; /* pointer to entry in utmp file */
372 int status = 1; /* return code */
374 #if !defined(CSRG_BASED)
375 while ( (u = getutent()) != NULL ) {
377 if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
378 u->ut_type != DEAD_PROCESS ) {
392 #if defined(AIXV3) && !defined(_POWER)
393 void dt_lastlogin ( user, llogin)
395 struct lastlogin * llogin;
400 * We are loading all the lastlogin info into a struct and then dealing
401 * with that so if the technique of storing the values is redone it
404 /* set id back to root */
407 * Open up the user data base
409 setuserdb(S_READ | S_WRITE);
412 * setting new unsuccessful login attempts times
416 * Get the old Failure count and increment it
418 if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
421 llogin->fcount = (int)tmp_int;
424 * put all the new data
426 putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
428 putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
430 putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
432 putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
433 putuserattr(user, NULL, NULL, SEC_COMMIT);
436 * Close data base and zero out indicator fields
443 * New Successful login data
446 putuserattr(user, S_LASTTIME, (void *)llogin->stime,
448 putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
449 Debug("hostname logged is %s\n",llogin->shost);
450 putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
451 putuserattr(user, S_ULOGCNT, 0, SEC_INT);
452 putuserattr(user, NULL, NULL, SEC_COMMIT);