
/*
 *  utmp.c -- routines to get the list of users logged in from utmp.
 *
 *  options:
 *  -DBSD		use bsd header files
 *  -DDEBUG		make program verbose
 *  -D_AIX		use ibm aix style utmp routines.
 *
 */

#define _POSIX_SOURCE 1

#include <sys/types.h>
#ifndef BSD
#include <unistd.h>
#endif
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <pwd.h>
#include <utmp.h>
#include "cleanup.h"

#define MAXUSERS 1024
#define ROOTUID 0
#define DAEMONUID 1

#ifndef _PATH_UTMP
#define _PATH_UTMP "/etc/utmp"
#endif

/* Get list of uids of logged in users */

#ifndef _AIX

struct cl_user *get_logged_in()
{
    int fd, i, j;
    char login[9];
    struct utmp u;
    struct passwd *p;
    static struct cl_user users[MAXUSERS];

    fd = open(_PATH_UTMP, O_RDONLY);
    if (fd < 0) {
        perror("cleanup: can't open " _PATH_UTMP);
	return(NULL);
    }

    /* Always include root & daemon */
    strcpy(users[0].name, "root");
    users[0].uid = ROOTUID;
    strcpy(users[1].name, "daemon");
    users[1].uid = DAEMONUID;
    i = 2;
#ifdef DEBUG
    printf("Logged in: 0, 1");
#endif

    /* make sure that this string will always end in 0 */
    login[8] = 0;

    while (read(fd, &u, sizeof(u)) > 0 && i < MAXUSERS) {
	if (u.ut_name[0] == 0)
	    continue;
#ifdef USER_PROCESS
        if (u.ut_type != USER_PROCESS)
            continue;
#endif
	strncpy(login, u.ut_name, 8);
	p = getpwnam(login);
	if (p == 0)
	    fprintf(stderr, "cleanup: Warning, could not get uid for user %s\n", login);
	else {
	    /* first check for duplicates */
	    for (j = 0; j < i; j++) {
		if (p->pw_uid == users[j].uid)
		    break;
	    }
	    if (i == j) {
		strncpy(users[i].name, p->pw_name, 8);
		users[i].name[8] = 0;
		users[i++].uid = p->pw_uid;
#ifdef DEBUG
		printf(", %d", p->pw_uid);
#endif
	    }
	}
    }
    users[i].uid = -1;
    close(fd);

#ifdef DEBUG
    printf("\n");
#endif
    return(users);
}

#else /* _AIX */

int *get_logged_in()
{
    int fd, i, j;
    char login[9];
    int pwuid;
    struct utmp *u;
    static int uids[MAXUSERS];

    /* Always include root & daemon */
    i=0;
    uids[i++] = ROOTUID;
    uids[i++] = DAEMONUID;
#ifdef DEBUG
    printf("Logged in: 0, 1");
#endif

    /* make sure that this string will always end in NULL */
    login[8] = 0;

    if (setuserdb(S_READ) < 0) {
	fprintf(stderr, "cleanup: can't open user database\n");
	/* this should probably completely blow out if this call fails */
	return(NULL);
    }
    while((u = getutent()) != 0 && i < MAXUSERS) {
	if (u->ut_name[0] == 0)
	    continue;
        if (u->ut_type != USER_PROCESS)
	    continue;

	strncpy(login, u->ut_name, 8);
	if (getuserattr(login, S_ID, &pwuid, SEC_INT) < 0)
	    fprintf(stderr,"cleanup: Warning, could not get uid for user %s\n",
		    login);
	else {
	    /* first check for duplicates */
	    for (j = 0; j < i; j++)
		if (pwuid == uids[j])
		    break;
	    if (i == j) {
		uids[i++] = pwuid;
#ifdef DEBUG
		printf(", %d", pwuid);
#endif
            }
        }
    }
    uids[i] = -1;
    endutent();
    enduserdb();
}

#endif /* _AIX */
