/* * ---------------------------------------------- * Author: doug@neverfear.org * Date: 2009-08-01 * * Examine the unix system login records. * To compile: gcc -o utmp-dump utmp-dump.c -lm * ---------------------------------------------- */ #include #include #include #include #include #include #define EMPTY 0 /* Record does not contain valid info (formerly known as UT_UNKNOWN on Linux) */ #define RUN_LVL 1 /* Change in system run-level (see init(8)) */ #define BOOT_TIME 2 /* Time of system boot (in ut_tv) */ #define NEW_TIME 3 /* Time after system clock change (in ut_tv) */ #define OLD_TIME 4 /* Time before system clock change (in ut_tv) */ #define INIT_PROCESS 5 /* Process spawned by init(8) */ #define LOGIN_PROCESS 6 /* Session leader process for user login */ #define USER_PROCESS 7 /* Normal process */ #define DEAD_PROCESS 8 /* Terminated process */ #define ACCOUNTING 9 /* Not implemented */ #define UT_LINESIZE 32 #define UT_NAMESIZE 32 #define UT_HOSTSIZE 256 #define BUF_LEN 256 #define REQ_CHAR_N 14 char * getproctype(int type) { switch(type) { case EMPTY: return "Empty"; case RUN_LVL: return "run-level"; case BOOT_TIME: return "System boot time"; case NEW_TIME: return "New clock time"; case OLD_TIME: return "Old clock time"; case INIT_PROCESS: return "init"; case LOGIN_PROCESS: return "login"; case USER_PROCESS: return "normal"; case DEAD_PROCESS: return "dead"; case ACCOUNTING: return "N/A"; default: return "N/A"; } } char * getprocname(pid_t pid) { if (pid != 0) { int filename_len = (floor(log10(pid)) + 1) + REQ_CHAR_N; char filename[filename_len + 1]; long filesize = 0; char buf[BUF_LEN]; int name_len = 0; char * name = NULL; int i; int bytes_read; snprintf(filename, filename_len + 1, "/proc/%d/cmdline", pid); filename[filename_len] = 0; FILE * fd = fopen(filename, "r"); if (fd) { while(!feof(fd)) { bytes_read = fread(buf, sizeof(char), BUF_LEN, fd); name_len += bytes_read; if (name == NULL) { name = (char*)calloc(name_len, sizeof(char)); } else { name = (char*)realloc(name, name_len); } for(i = 0; i < bytes_read; i++) { if (buf[i] != 0) { name[(name_len - bytes_read) + i] = buf[i]; } else { name[(name_len - bytes_read) + i] = ' '; } } } name[name_len - 1] = 0; fclose(fd); return name; } else { fprintf(stderr, "Error opening data for PID %d\n", pid); } } return NULL; } /* char * getprocname2(pid_t pid) { struct task_struct * my; my = find_process_by_pid(pid); printf("task->comm=%s\n", my->comm); return NULL; } */ void printutmp(struct utmp * utmp) { char * pname = NULL; if (utmp->ut_type != DEAD_PROCESS) { pname = getprocname(utmp->ut_pid); } printf("utmp {\n"); printf(" ut_user = '%s'\n", utmp->ut_user); printf(" ut_id = '%s'\n", utmp->ut_id); printf(" ut_line = '%s'\n", utmp->ut_line); if (pname != NULL) { printf(" ut_pid = %d (%s)\n", utmp->ut_pid, pname); } else { printf(" ut_pid = %d\n", utmp->ut_pid); } printf(" ut_type = %d (%s)\n", utmp->ut_type, getproctype(utmp->ut_type)); printf(" ut_time = %d\n", utmp->ut_time); printf(" ut_session = %d\n", utmp->ut_session); printf(" ut_host = '%s'\n", utmp->ut_host); printf(" ut_addr_v6 = %d\n", utmp->ut_addr_v6); printf(" ut_exit {\n"); printf(" e_termination = %d\n", utmp->ut_exit.e_termination); printf(" e_exit = %d\n", utmp->ut_exit.e_exit); printf(" }\n"); printf(" ut_tv {\n"); printf(" tv_sec = %d\n", utmp->ut_tv.tv_sec); printf(" tv_usec = %d\n", utmp->ut_tv.tv_usec); printf(" }\n"); printf("}\n\n"); if (pname != NULL) { free(pname); } } int main() { struct utmp * utmp; while((utmp = getutent()) != NULL) { printutmp(utmp); } endutent(); }