void utmpx_mark_dead(pid_t pid, int status, boolean_t blocking) { struct utmpx *up; int logged = 0; for (;;) { int found = 0; MUTEX_LOCK(&utmpx_lock); setutxent(); while (up = getutxent()) { if (up->ut_pid == pid) { found = 1; if (up->ut_type == DEAD_PROCESS) { /* * Cleaned up elsewhere. */ endutxent(); MUTEX_UNLOCK(&utmpx_lock); return; } up->ut_type = DEAD_PROCESS; up->ut_exit.e_termination = WTERMSIG(status); up->ut_exit.e_exit = WEXITSTATUS(status); (void) time(&up->ut_tv.tv_sec); if (pututxline(up) != NULL) { /* * Now attempt to add to the end of the * wtmp and wtmpx files. Do not create * if they don't already exist. */ updwtmpx(WTMPX_FILE, up); endutxent(); MUTEX_UNLOCK(&utmpx_lock); return; } } } endutxent(); MUTEX_UNLOCK(&utmpx_lock); if (!found || !blocking) return; if (!logged) { log_framework(LOG_INFO, "retrying utmpx_dead on PID " "%ld\n", pid); logged++; } (void) sleep(1); } }
/* * Return users currently connected on the system. */ static PyObject * psutil_users(PyObject *self, PyObject *args) { struct utmpx *ut; PyObject *py_tuple = NULL; PyObject *py_username = NULL; PyObject *py_tty = NULL; PyObject *py_hostname = NULL; PyObject *py_user_proc = NULL; PyObject *py_retlist = PyList_New(0); if (py_retlist == NULL) return NULL; setutxent(); while (NULL != (ut = getutxent())) { if (ut->ut_type == USER_PROCESS) py_user_proc = Py_True; else py_user_proc = Py_False; py_username = PyUnicode_DecodeFSDefault(ut->ut_user); if (! py_username) goto error; py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); if (! py_tty) goto error; py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); if (! py_hostname) goto error; py_tuple = Py_BuildValue( "(OOOfOi)", py_username, // username py_tty, // tty py_hostname, // hostname (float)ut->ut_tv.tv_sec, // tstamp py_user_proc, // (bool) user process ut->ut_pid // process id ); if (py_tuple == NULL) goto error; if (PyList_Append(py_retlist, py_tuple)) goto error; Py_DECREF(py_username); Py_DECREF(py_tty); Py_DECREF(py_hostname); Py_DECREF(py_tuple); } endutxent(); return py_retlist; error: Py_XDECREF(py_username); Py_XDECREF(py_tty); Py_XDECREF(py_hostname); Py_XDECREF(py_tuple); Py_DECREF(py_retlist); endutxent(); return NULL; }
static void utmpx_write_entry(short type, const char *msg, time_t tstamp) { struct utmpx u; struct utmpx *oup; size_t tmplen; bzero(&u, sizeof (struct utmpx)); u.ut_id[0] = u.ut_id[1] = u.ut_id[2] = u.ut_id[3] = '\0'; u.ut_pid = 0; u.ut_exit.e_termination = WTERMSIG(0); u.ut_exit.e_exit = WEXITSTATUS(0); u.ut_type = type; u.ut_tv.tv_sec = tstamp; MUTEX_LOCK(&utmpx_lock); setutxent(); if ((oup = getutxid(&u)) != NULL) { bcopy(oup->ut_user, u.ut_user, sizeof (u.ut_user)); bcopy(oup->ut_line, u.ut_line, sizeof (u.ut_line)); bcopy(oup->ut_host, u.ut_host, sizeof (u.ut_host)); tmplen = strlen(u.ut_host); if (tmplen) u.ut_syslen = min(tmplen + 1, sizeof (u.ut_host)); else u.ut_syslen = 0; } (void) sprintf(u.ut_line, "%.12s", msg); if (pututxline(&u) == NULL) { endutxent(); MUTEX_UNLOCK(&utmpx_lock); return; } updwtmpx(WTMPX_FILE, &u); endutxent(); MUTEX_UNLOCK(&utmpx_lock); utmpx_check(); }
/* Show utmp information via getutxent(3) @function utmp @return information (TABLE) */ static int Futmp(lua_State *L) { struct utmpx *utx = {0}; setutxent(); lua_createtable(L, 0, 7); while ((utx = getutxent())) { lua_pushstring(L, utx->ut_user); lua_setfield(L, -2, "user"); lua_pushstring(L, utx->ut_line); lua_setfield(L, -2, "tty"); lua_pushstring(L, utx->ut_host); lua_setfield(L, -2, "hostname"); lua_pushnumber(L, (float)utx->ut_tv.tv_sec); lua_setfield(L, -2, "timestamp"); lua_pushboolean(L, utx->ut_type & USER_PROCESS); lua_setfield(L, -2, "user_process"); lua_pushboolean(L, utx->ut_type & INIT_PROCESS); lua_setfield(L, -2, "init_process"); lua_pushboolean(L, utx->ut_type & LOGIN_PROCESS); lua_setfield(L, -2, "login_process"); } endutxent(); return 1; }
int main(int argc, char **argv) { struct utmpx u; const char file[256] = "/home/flueg/workspace/utmp/ftmpx"; memset(&u, 0, sizeof(struct utmpx)); if (utmpxname(file) == -1) perror("failed to set ftmpx file"); strcpy(u.ut_user, getpwuid(getuid())->pw_name); printf("ttyname is: %s\n", ttyname(0)+strlen("/dev/")); strcpy(u.ut_id, ttyname(0) + strlen("/dev/tty")); strcpy(u.ut_line, ttyname(0) + strlen("/dev/")); u.ut_pid = getpid(); u.ut_type = LOGIN_PROCESS; setutxent(); if (pututxline(&u) == NULL) perror("failed to pututxline.\n"); sleep(2); u.ut_type = DEAD_PROCESS; time((time_t *) &u.ut_tv.tv_sec); setutxent(); if (pututxline(&u) == NULL) perror("failed to pututxline.\n"); endutxent(); exit(0); }
int main(int argc, char *argv[]) { struct utmpx *ut; setutxent(); while ((ut = getutxent()) != NULL) { printf("%-10s ", ut->ut_user); printf("%-10s ", (ut->ut_type == EMPTY) ? "EMPTY" : (ut->ut_type == RUN_LVL) ? "RUN_LVL" : (ut->ut_type == BOOT_TIME) ? "BOOT_TIME": (ut->ut_type == NEW_TIME) ? "NEW_TIME" : (ut->ut_type == OLD_TIME) ? "OLD_TIME" : (ut->ut_type == INIT_PROCESS) ? "INIT_PR" : (ut->ut_type == LOGIN_PROCESS) ? "LOGIN_PR" : (ut->ut_type == USER_PROCESS) ? "USER_PR" : (ut->ut_type == DEAD_PROCESS) ? "DEAD_PR" : "?"); printf("%-7ld %-6s %-5s %-10s ", (long) ut->ut_pid, ut->ut_line, ut->ut_id, ut->ut_host); printf("%s", ctime((time_t *) &(ut->ut_tv.tv_sec))); } endutxent(); exit(EXIT_SUCCESS); }
/** goodNumberOfUsers method for SunOS implementation of OS Provider Goes through the utents, counting the number of type USER_PROCESS Works in isolated test env without new users logging in */ Boolean OSTestClient::goodNumberOfUsers( const Uint32 &nusers, Boolean verbose) { struct utmpx * utmpp; Uint32 numberOfUsers; if (verbose) cout<<"Checking NumberOfUsers " << nusers << endl; numberOfUsers = 0; // ATTN-SLC-P3-17-Apr-02: optimization? parse uptime instead? while ((utmpp = getutxent()) != NULL) { if (utmpp->ut_type == USER_PROCESS) { numberOfUsers++; } } endutxent(); if (verbose) cout << " Should be " << numberOfUsers << endl; // works in isolated test env without new users logging in return (nusers == numberOfUsers); }
static void doutmpx(void) { struct utmpx utmpx; char *t; memset((void *)&utmpx, 0, sizeof(utmpx)); utmpx.ut_tv = now; (void)strncpy(utmpx.ut_name, username, sizeof(utmpx.ut_name)); if (hostname) { (void)strncpy(utmpx.ut_host, hostname, sizeof(utmpx.ut_host)); utmpx.ut_ss = ss; } (void)strncpy(utmpx.ut_line, tty, sizeof(utmpx.ut_line)); utmpx.ut_type = USER_PROCESS; utmpx.ut_pid = getpid(); t = tty + strlen(tty); if (t - tty >= sizeof(utmpx.ut_id)) { (void)strncpy(utmpx.ut_id, t - sizeof(utmpx.ut_id), sizeof(utmpx.ut_id)); } else { (void)strncpy(utmpx.ut_id, tty, sizeof(utmpx.ut_id)); } if (pututxline(&utmpx) == NULL) syslog(LOG_NOTICE, "Cannot update utmpx: %m"); endutxent(); if (updwtmpx(_PATH_WTMPX, &utmpx) != 0) syslog(LOG_NOTICE, "Cannot update wtmpx: %m"); }
static void cleanup_utmp(void) { struct timeval tv; if (!pty_stamped_utmp) return; utmp_entry.ut_type = DEAD_PROCESS; memset(utmp_entry.ut_user, 0, lenof(utmp_entry.ut_user)); gettimeofday(&tv, NULL); utmp_entry.ut_tv.tv_sec = tv.tv_sec; utmp_entry.ut_tv.tv_usec = tv.tv_usec; updwtmpx(WTMPX_FILE, &utmp_entry); memset(utmp_entry.ut_line, 0, lenof(utmp_entry.ut_line)); utmp_entry.ut_tv.tv_sec = 0; utmp_entry.ut_tv.tv_usec = 0; setutxent(); pututxline(&utmp_entry); endutxent(); pty_stamped_utmp = 0; /* ensure we never double-cleanup */ }
static void remove_utmp_entry(main_server_st *s, struct proc_st* proc) { #ifdef HAVE_LIBUTIL struct utmpx entry; struct timespec tv; if (s->config->use_utmp == 0) return; memset(&entry, 0, sizeof(entry)); entry.ut_type = DEAD_PROCESS; if (proc->tun_lease.name[0] != 0) snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", proc->tun_lease.name); entry.ut_pid = proc->pid; setutxent(); pututxline(&entry); endutxent(); #if defined(WTMPX_FILE) gettime(&tv); entry.ut_tv.tv_sec = tv.tv_sec; entry.ut_tv.tv_usec = tv.tv_nsec / 1000; updwtmpx(WTMPX_FILE, &entry); #endif return; #endif }
static void _add_utmp(TE_Pty* pty, int spid) { memset(&pty->ut_entry, 0, sizeof(pty->ut_entry) ); #if 0 pty->ut_entry.ut_type = USER_PROCESS; pty->ut_entry.ut_pid = spid; // strcpy(pty->ut_entry.ut_line, pty->ptyname+5); // printf("ut name \"%s\" (%d)\n", pty->ut_entry.ut_user, getuid()); #ifdef __APPLE__ // strcpy(pty->ut_entry.ut_id, pty->ptyname+8); strcpy(pty->ut_entry.ut_user, getpwuid(getuid())->pw_name); gettimeofday(&pty->ut_entry.ut_tv, NULL); setutxent(); pututxline(&pty->ut_entry); endutxent(); #else strcpy(pty->ut_entry.ut_host, getenv("DISPLAY")); time_t tt; time(&tt); pty->ut_entry.ut_time = tt; pty->ut_entry.ut_addr = 0; setutent(); pututline(&pty->ut_entry); endutent(); #endif #endif }
int wall_main(int argc UNUSED_PARAM, char **argv) { struct utmpx *ut; char *msg; int fd; fd = STDIN_FILENO; if (argv[1]) { /* The applet is setuid. * Access to the file must be under user's uid/gid. */ fd = xopen_as_uid_gid(argv[1], O_RDONLY, getuid(), getgid()); } msg = xmalloc_read(fd, NULL); if (ENABLE_FEATURE_CLEAN_UP && argv[1]) close(fd); setutxent(); while ((ut = getutxent()) != NULL) { char *line; if (ut->ut_type != USER_PROCESS) continue; line = concat_path_file("/dev", ut->ut_line); xopen_xwrite_close(line, msg); free(line); } if (ENABLE_FEATURE_CLEAN_UP) { endutxent(); free(msg); } return EXIT_SUCCESS; }
int who_main(int argc UNUSED_PARAM, char **argv) { struct utmpx *ut; unsigned opt; int do_users = (ENABLE_USERS && (!ENABLE_WHO || applet_name[0] == 'u')); const char *fmt = "%s"; opt_complementary = "=0"; opt = getopt32(argv, do_users ? "" : "aH"); if (opt & 2) // -H puts("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST"); setutxent(); while ((ut = getutxent()) != NULL) { if (ut->ut_user[0] && ((opt & 1) || ut->ut_type == USER_PROCESS) ) { if (!do_users) { char str6[6]; char name[sizeof("/dev/") + sizeof(ut->ut_line) + 1]; struct stat st; time_t seconds; str6[0] = '?'; str6[1] = '\0'; strcpy(name, "/dev/"); safe_strncpy(ut->ut_line[0] == '/' ? name : name + sizeof("/dev/")-1, ut->ut_line, sizeof(ut->ut_line)+1 ); if (stat(name, &st) == 0) idle_string(str6, st.st_atime); /* manpages say ut_tv.tv_sec *is* time_t, * but some systems have it wrong */ seconds = ut->ut_tv.tv_sec; /* How wide time field can be? * "Nov 10 19:33:20": 15 chars * "2010-11-10 19:33": 16 chars */ printf("%-15.*s %-15.*s %-7s %-16.16s %.*s\n", (int)sizeof(ut->ut_user), ut->ut_user, (int)sizeof(ut->ut_line), ut->ut_line, str6, ctime(&seconds) + 4, (int)sizeof(ut->ut_host), ut->ut_host ); } else { printf(fmt, ut->ut_user); fmt = " %s"; } } } if (do_users) bb_putchar('\n'); if (ENABLE_FEATURE_CLEAN_UP) endutxent(); return EXIT_SUCCESS; }
static void logout_utmpx(struct utmpx *utmpx, const struct timeval *now) { utmpx->ut_type = DEAD_PROCESS; utmpx->ut_tv = *now; utmpx->ut_pid = 0; (void)pututxline(utmpx); endutxent(); }
static int _userinfo_generic(unsigned int * userinfo) { struct utmpx * ut; for(*userinfo = 0; (ut = getutxent()) != NULL;) if(ut->ut_type == USER_PROCESS) (*userinfo)++; endutxent(); return 0; }
int logoutx(const char *line, int status, int type) { struct utmpx *utp, ut; (void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line)); if ((utp = getutxline(&ut)) == NULL) { endutxent(); return 0; } utp->ut_type = type; if (WIFEXITED(status)) utp->ut_exit.e_exit = (uint16_t)WEXITSTATUS(status); if (WIFSIGNALED(status)) utp->ut_exit.e_termination = (uint16_t)WTERMSIG(status); (void)gettimeofday(&utp->ut_tv, NULL); (void)pututxline(utp); endutxent(); return 1; }
static PyObject* pyutmpx(PyObject* self, PyObject* args) { PyObject *ret = PyList_New(0); PyObject *l_utmp = PyList_New(0); PyObject *l_wtmp = PyList_New(0); struct utmpx *ut; setutxdb(UTXDB_ACTIVE, UTX_ACTIVE); while ((ut = getutxent()) != NULL) PyList_Append(l_utmp, Py_BuildValue("sssi", ut->ut_line, ut->ut_user, ut->ut_host, ut->ut_tv)); endutxent(); setutxdb(UTXDB_LOG, UTX_LOG); while ((ut = getutxent()) != NULL) PyList_Append(l_wtmp, Py_BuildValue("sssi", ut->ut_line, ut->ut_user, ut->ut_host, ut->ut_tv)); endutxent(); PyList_Append(ret, Py_BuildValue("N", l_utmp)); PyList_Append(ret, Py_BuildValue("N", l_wtmp)); return Py_BuildValue("N", ret); }
static int utmpx_write_library(struct logininfo *li, struct utmpx *utx) { setutxent(); pututxline(utx); # ifdef HAVE_ENDUTXENT endutxent(); # endif return 1; }
static void single(const char *cmd, char *ttyn) { struct utmpx *u; char found = B_FALSE; if (ttyn == NULL) ttyn = findttyname(STDIN_FILENO); /* * utmpx records on the console device are expected to be "console" * by other processes, such as dtlogin. */ ttyn = stripttyname(ttyn); /* update the utmpx file. */ while ((u = getutxent()) != NULL) { if (strcmp(u->ut_line, ttyn) == 0) { u->ut_tv.tv_sec = time(NULL); u->ut_type = USER_PROCESS; u->ut_pid = getpid(); if (strcmp(u->ut_user, "root") != 0) (void) strcpy(u->ut_user, "root"); (void) pututxline(u); found = B_TRUE; break; } } if (!found) { struct utmpx entryx; entryx.ut_tv.tv_sec = time(NULL); entryx.ut_type = USER_PROCESS; entryx.ut_pid = getpid(); (void) strcpy(entryx.ut_user, "root"); (void) strcpy(entryx.ut_line, ttyn); entryx.ut_tv.tv_usec = 0; entryx.ut_session = 0; entryx.ut_id[0] = 'c'; entryx.ut_id[1] = 'o'; entryx.ut_id[2] = 's'; entryx.ut_id[3] = 'u'; entryx.ut_syslen = 1; entryx.ut_host[0] = '\0'; entryx.ut_exit.e_termination = WTERMSIG(0); entryx.ut_exit.e_exit = WEXITSTATUS(0); (void) pututxline(&entryx); } endutxent(); (void) printf("Entering System Maintenance Mode\n\n"); if (execl(cmd, cmd, "-", (char *)0) < 0) exit(EXIT_FAILURE); }
static int users_read (void) { #if HAVE_GETUTXENT unsigned int users = 0; struct utmpx *entry = NULL; /* according to the *utent(3) man page none of the functions sets errno in case of an error, so we cannot do any error-checking here */ setutxent(); while (NULL != (entry = getutxent())) { if (USER_PROCESS == entry->ut_type) { ++users; } } endutxent(); users_submit (users); /* #endif HAVE_GETUTXENT */ #elif HAVE_GETUTENT unsigned int users = 0; struct utmp *entry = NULL; /* according to the *utent(3) man page none of the functions sets errno in case of an error, so we cannot do any error-checking here */ setutent(); while (NULL != (entry = getutent())) { if (USER_PROCESS == entry->ut_type) { ++users; } } endutent(); users_submit (users); /* #endif HAVE_GETUTENT */ #elif HAVE_LIBSTATGRAB sg_user_stats *us; us = sg_get_user_stats (); if (us == NULL) return (-1); users_submit ((gauge_t) us->num_entries); /* #endif HAVE_LIBSTATGRAB */ #else # error "No applicable input method." #endif return (0); } /* int users_read */
static bool_t loggedon(char *name) { register struct utmpx *ubuf; char *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL; /* * strip any realm or instance from principal so we can match * against unix userid. */ rcp1 = strdup(name); if (!rcp1) return (FALSE); rcp2 = strtok(rcp1, "@"); rcp3 = strtok(rcp2, "/"); /* * Scan through the "utmpx" file for the * entry for the person we want to send to. */ setutxent(); while ((ubuf = getutxent()) != NULL) { if (ubuf->ut_type == USER_PROCESS) { if (strncmp(rcp3, ubuf->ut_user, sizeof (ubuf->ut_user)) == 0) { free(rcp1); endutxent(); return (TRUE); } } } free(rcp1); endutxent(); if (kwarnd_debug) printf("loggedon: returning false for user `%s'\n", rcp1); return (FALSE); }
int main (int argc, char **argv) { int users = -1; int result = STATE_UNKNOWN; char *perf; struct utmpx *putmpx; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); perf = strdup (""); /* Parse extra opts if any */ argv = np_extra_opts (&argc, argv, progname); if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); users = 0; /* get currently logged users from utmpx */ setutxent (); while ((putmpx = getutxent ()) != NULL) if (putmpx->ut_type == USER_PROCESS) users++; endutxent (); /* check the user count against warning and critical thresholds */ if (users > cusers) result = STATE_CRITICAL; else if (users > wusers) result = STATE_WARNING; else if (users >= 0) result = STATE_OK; if (result == STATE_UNKNOWN) printf ("%s\n", _("Unable to read output")); else { asprintf (&perf, "%s", perfdata ("users", users, "", TRUE, wusers, TRUE, cusers, TRUE, 0, FALSE, 0)); printf (_("USERS %s - %d users currently logged in |%s\n"), state_text (result), users, perf); } return result; }
void login(struct utmp *ut) { struct utmpx ux; getutmpx(ut, &ux); /* ut_id will automatically be calculated in the call to pututxline() */ ux.ut_type |= UTMPX_AUTOFILL_MASK; setutxent(); pututxline(&ux); endutxent(); }
int utmpx_get_entry(struct logininfo *li) { struct utmpx *utx; if (setutxdb(UTXDB_LASTLOGIN, NULL) != 0) return (0); utx = getutxuser(li->username); if (utx == NULL) { endutxent(); return (0); } line_fullname(li->line, utx->ut_line, MIN_SIZEOF(li->line, utx->ut_line)); strlcpy(li->hostname, utx->ut_host, MIN_SIZEOF(li->hostname, utx->ut_host)); li->tv_sec = utx->ut_tv.tv_sec; li->tv_usec = utx->ut_tv.tv_usec; endutxent(); return (1); }
static int get_run_level(void) { #if defined(HAVE_UTMPX_H) && defined(RUN_LVL) int res=0; struct utmpx *ut,tmp; setutxent(); tmp.ut_type=RUN_LVL; ut=getutxid(&tmp); if(!ut) { endutxent(); return 5; } res=ut->ut_pid & 0xff; endutxent(); //g_message("runlevel %c\n",res); return res; #else return 5; #endif }
/* calculate number of users on the system */ static int ucount(void) { int nusers = 0; struct utmpx *ut; setutxent(); while ((ut = getutxent()) != NULL) if (ut->ut_type == USER_PROCESS) nusers++; endutxent(); return (nusers); }
static char * _getlogin() { /* find name of the controlling terminal of the calling process */ char *tty; /* if the controlling terminal name cannot be determined, return a NULL pointer. * `errno` will have been appropriately set by `ttyname(3)`. */ if ((tty = ttyname(STDIN_FILENO)) == NULL) return NULL; /* the static data structure used for all calls to this function */ static char login[GETLOGIN_LOGIN_MAX]; utmpname(GETLOGIN_UTMP_FILE); /* search for an entry in the utmp file where the ut_line field matches * that of the controlling terminal name */ errno = 0; setutxent(); if (errno != 0) return NULL; struct utmpx *entry, criteria; char *line; /* drop the leading slash, if any */ if (tty[0] == '/') ++tty; /* remove the `dev/` prefix from the ttyname, if existent */ if ((line = strchr(tty, '/')) == NULL) line = tty; else /* dev/pts/0 becomes pts/0 */ ++line; strncpy(criteria.ut_line, line, __UT_LINESIZE); if ((entry = getutxline(&criteria)) == NULL) return NULL; strncpy(login, entry->ut_user, GETLOGIN_LOGIN_MAX); /* finish the reading of the utmp file */ errno = 0; endutxent(); if (errno != 0) return NULL; return login; }
int get_boottime(struct timeval *tv) { struct utmpx *ut, key; memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; if ((ut = getutxid(&key)) != NULL) { tv->tv_sec = ut->ut_tv.tv_sec; tv->tv_usec = ut->ut_tv.tv_usec; endutxent(); } return ut != NULL; }
char* test_getlogin() { struct utmpx *ut; char *tty = ttyname(STDIN_FILENO); setutxent(); while ((ut = getutxent()) != NULL) { if (strcmp(ut->ut_line, tty + 5) == 0) { strncpy(user, ut->ut_user, 255); user[255] = '\0'; break; } } endutxent(); return user; }
static int utmp_get_runlevel(struct lxc_utmp *utmp_data) { #if HAVE_UTMPX_H struct utmpx *utmpx; #else struct utmp *utmpx; #endif char path[MAXPATHLEN]; struct lxc_handler *handler = utmp_data->handler; if (snprintf(path, MAXPATHLEN, "/proc/%d/root/run/utmp", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (!access(path, F_OK) && !utmpxname(path)) goto utmp_ok; if (snprintf(path, MAXPATHLEN, "/proc/%d/root/var/run/utmp", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (utmpxname(path)) { SYSERROR("failed to 'utmpxname'"); return -1; } utmp_ok: setutxent(); while ((utmpx = getutxent())) { if (utmpx->ut_type == RUN_LVL) { utmp_data->prev_runlevel = utmpx->ut_pid / 256; utmp_data->curr_runlevel = utmpx->ut_pid % 256; DEBUG("utmp handler - run level is %c/%c", utmp_data->prev_runlevel, utmp_data->curr_runlevel); } } endutxent(); return 0; }