/* count the number of users */ static int get_unique ( void ) { apr_pool_t *subpool; apr_hash_t *hashuser; char *name; void *user; unsigned int numunique = 0; struct utmp *utmpstruct; apr_pool_create(&subpool, pool); hashuser = apr_hash_make(subpool); apr_thread_mutex_lock(mutex); setutent(); while ((utmpstruct = getutent())) { if ((utmpstruct->ut_type == USER_PROCESS) && (utmpstruct->ut_name[0] != '\0')) { name = apr_pstrndup(subpool, utmpstruct->ut_name, UT_NAMESIZE); user = name; /* use key for value, not interested in it anyway */ apr_hash_set(hashuser, name, APR_HASH_KEY_STRING, user); } } endutent(); apr_thread_mutex_unlock(mutex); numunique = apr_hash_count(hashuser); apr_pool_destroy(subpool); return numunique; }
/* * Return currently connected users as a list of tuples. */ static PyObject* get_system_users(PyObject* self, PyObject* args) { PyObject *ret_list = PyList_New(0); PyObject *tuple = NULL; PyObject *user_proc = NULL; struct utmp *ut; setutent(); while (NULL != (ut = getutent())) { if (ut->ut_type == USER_PROCESS) user_proc = Py_True; else user_proc = Py_False; tuple = Py_BuildValue("(sssfO)", ut->ut_user, // username ut->ut_line, // tty ut->ut_host, // hostname (float)ut->ut_tv.tv_sec, // tstamp user_proc // (bool) user process ); PyList_Append(ret_list, tuple); Py_DECREF(tuple); } endutent(); return ret_list; }
static void cleanup_utmp(void) { #ifndef OMIT_UTMP FILE *wtmp; time_t uttime; if (!pty_stamped_utmp) return; utmp_entry.ut_type = DEAD_PROCESS; memset(utmp_entry.ut_user, 0, lenof(utmp_entry.ut_user)); time(&uttime); utmp_entry.ut_time = uttime; if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); fclose(wtmp); } memset(utmp_entry.ut_line, 0, lenof(utmp_entry.ut_line)); utmp_entry.ut_time = 0; #if defined HAVE_PUTUTLINE utmpname(UTMP_FILE); setutent(); pututline(&utmp_entry); endutent(); #endif pty_stamped_utmp = 0; /* ensure we never double-cleanup */ #endif }
static int simulate_logout (const char *line) { int n; for (n = 0; n < num_entries; n++) { if (strcmp (line, entry[n].ut_line) == 0) { entry[n].ut_type = DEAD_PROCESS; strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user)); #if _HAVE_UT_TV - 0 || defined UTMPX entry[n].ut_tv.tv_sec = (entry_time += 1000); #else entry[n].ut_time = (entry_time += 1000); #endif setutent (); if (pututline (&entry[n]) == NULL) { perror("cannot write UTMP entry"); ++errors; return 1; } endutent (); return 0; } } printf ("no entry found for `%s'", line); ++errors; return 1; }
static void user_busy(const char *name, uid_t uid) { struct utmp *utent; /* * We see if the user is logged in by looking for the user name * in the utmp file. */ setutent (); while ((utent = getutent ())) { #ifdef USER_PROCESS if (utent->ut_type != USER_PROCESS) continue; #else if (utent->ut_user[0] == '\0') continue; #endif if (strncmp(utent->ut_user, name, sizeof utent->ut_user)) continue; fprintf(stderr, _("%s: user %s is currently logged in\n"), Prog, name); exit(E_USER_BUSY); } }
int runlevel_main(int argc UNUSED_PARAM, char **argv) { struct utmp *ut; char prev; if (argv[1]) utmpname(argv[1]); setutent(); while ((ut = getutent()) != NULL) { if (ut->ut_type == RUN_LVL) { prev = ut->ut_pid / 256; if (prev == 0) prev = 'N'; printf("%c %c\n", prev, ut->ut_pid % 256); if (ENABLE_FEATURE_CLEAN_UP) endutent(); return 0; } } puts("unknown"); if (ENABLE_FEATURE_CLEAN_UP) endutent(); return 1; }
int uv_uptime(double* uptime) { struct utmp *utmp_buf; size_t entries = 0; time_t boot_time; boot_time = 0; utmpname(UTMP_FILE); setutent(); while ((utmp_buf = getutent()) != NULL) { if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS) ++entries; if (utmp_buf->ut_type == BOOT_TIME) boot_time = utmp_buf->ut_time; } endutent(); if (boot_time == 0) return UV_ENOSYS; *uptime = time(NULL) - boot_time; return 0; }
/* * See if we were started directly from init. * Get the runlevel from /var/run/utmp or the environment. */ int get_runlevel(void) { struct utmp *ut; char *r; /* * First see if we were started directly from init. */ if (getenv("INIT_VERSION") && (r = getenv("RUNLEVEL")) != NULL) return *r; /* * Find runlevel in utmp. */ setutent(); while ((ut = getutent()) != NULL) { if (ut->ut_type == RUN_LVL) return (ut->ut_pid & 255); } endutent(); /* This should not happen but warn the user! */ fprintf(stderr, "WARNING: could not determine runlevel" " - doing soft %s\n", progname); fprintf(stderr, " (it's better to use shutdown instead of %s" " from the command line)\n", progname); return -1; }
static int user_busy_utmp (const char *name) { #ifdef USE_UTMPX struct utmpx *utent; setutxent (); while ((utent = getutxent ()) != NULL) #else /* !USE_UTMPX */ struct utmp *utent; setutent (); while ((utent = getutent ()) != NULL) #endif /* !USE_UTMPX */ { if (utent->ut_type != USER_PROCESS) { continue; } if (strncmp (utent->ut_user, name, sizeof utent->ut_user) != 0) { continue; } if (kill (utent->ut_pid, 0) != 0) { continue; } fprintf (stderr, _("%s: user %s is currently logged in\n"), Prog, name); return 1; } return 0; }
static int getUptime(void) { struct sysinfo s_info; error = sysinfo(&s_info); int days, hours, minutes; long int upmind, upminh, uptimes; uptimes = s_info.uptime; /* returned in seconds */ days = uptimes / ONEDAY; upmind = uptimes - (days * ONEDAY); hours = upmind / ONEHOUR; upminh = upmind - hours * ONEHOUR; minutes = upminh / ONEMINUTE; float av1, av2, av3; av1 = s_info.loads[0] / LOADS_SCALE; av2 = s_info.loads[1] / LOADS_SCALE; av3 = s_info.loads[2] / LOADS_SCALE; /* This next block is stolen fron GNU uptime */ struct utmp *utmpstruct; int numuser = 0; setutent(); while ((utmpstruct = getutent())) { if ((utmpstruct->ut_type == USER_PROCESS) && (utmpstruct->ut_name[0] != '\0')) numuser++; } endutent(); printf(" up %i day%s, %02i:%02i, %i user%s, load average: %2.2f, %2.2f, %2.2f\n", days, (days != 1) ? "s" : "", hours, minutes, numuser, (numuser != 1) ? "s" : "", av1, av2, av3); return error; }
struct utmp * getutid(struct utmp * utmp_entry) { struct utmp * utmp; if (ut_fd==-1) setutent(); if (ut_fd==-1) return NULL; while ((utmp=__getutent(ut_fd))!=NULL) { if ((utmp_entry->ut_type==RUN_LVL || utmp_entry->ut_type==BOOT_TIME || utmp_entry->ut_type==NEW_TIME || utmp_entry->ut_type==OLD_TIME) && utmp->ut_type==utmp_entry->ut_type) return utmp; if ((utmp_entry->ut_type==INIT_PROCESS || utmp_entry->ut_type==DEAD_PROCESS || utmp_entry->ut_type==LOGIN_PROCESS || utmp_entry->ut_type==USER_PROCESS) && !strcmp(utmp->ut_id, utmp_entry->ut_id)) return utmp; } return NULL; }
struct utmp * getutline(struct utmp * utmp_entry) { struct utmp * utmp; if (ut_fd==-1) setutent(); if (ut_fd==-1) return NULL; #if 0 /* This is driving me nuts. It's not an implementation problem - it's a matter of how things _SHOULD_ behave. Groan. */ lseek(ut_fd, SEEK_CUR, -sizeof(struct utmp)); #endif while ((utmp=__getutent(ut_fd))!=NULL) { if ((utmp->ut_type==USER_PROCESS || utmp->ut_type==LOGIN_PROCESS) && !strcmp(utmp->ut_line, utmp_entry->ut_line)) return utmp; } return NULL; }
static int count_users(void) { int total = 0; #if HAVE_UTMPX_H #define setutent setutxent #define pututline pututxline #define getutent getutxent #define endutent endutxent struct utmpx *utmp_p; #else struct utmp *utmp_p; #endif setutent(); while ((utmp_p = getutent()) != NULL) { #ifndef UTMP_HAS_NO_TYPE if (utmp_p->ut_type != USER_PROCESS) continue; #endif #ifndef UTMP_HAS_NO_PID /* This block of code fixes zombie user PIDs in the utmp/utmpx file that would otherwise be counted as a current user */ if (kill(utmp_p->ut_pid, 0) == -1 && errno == ESRCH) { utmp_p->ut_type = DEAD_PROCESS; pututline(utmp_p); continue; } #endif ++total; } endutent(); return total; }
static void makeutmp(int runlevel) { D_("Making utmp file for runlevel %d\n", runlevel); struct utmp utmp; time_t t; /* * this is created by bootmisc, if this isn't there we can't set * runlevel. */ if (access(UTMP_FILE, F_OK) < 0) { F_("/var/run/utmp does not exist, this should be created by " "bootmisc.i\n"); return; } /* TODO, is this a good idea or a bad idea? utmpname("/var/run/utmp"); */ setutent(); memset(&utmp, 0, sizeof(utmp)); utmp.ut_type = RUN_LVL; utmp.ut_pid = ('#' << 8) + runlevel + '0'; time(&t); utmp.ut_time = (int)t; if (!pututline(&utmp)) { F_("pututline failed\n"); endutent(); return; } endutent(); return; }
static int check_login_time(const char *ruser, time_t timestamp) { struct utmp utbuf, *ut; time_t oldest_login = 0; setutent(); while( #ifdef HAVE_GETUTENT_R !getutent_r(&utbuf, &ut) #else (ut = getutent()) != NULL #endif ) { if (ut->ut_type != USER_PROCESS) { continue; } if (strncmp(ruser, ut->ut_user, sizeof(ut->ut_user) != 0)) { continue; } if (oldest_login == 0 || oldest_login > ut->ut_tv.tv_sec) { oldest_login = ut->ut_tv.tv_sec; } } endutent(); if(oldest_login == 0 || timestamp < oldest_login) { return PAM_AUTH_ERR; } return PAM_SUCCESS; }
/* * Notify all available ttys about device insertion. * * Return the number of ttys notified. */ static int notify_all_ttys(const char *manufacturer, const char *product, const char *devnode) { struct utmp *ut = NULL; int ttys_notified = 0; setutent(); /* Don't free ut, it is statically allocated. */ while ((ut = getutent()) != NULL) { /* Skip invalid entries. */ if (ut->ut_type != USER_PROCESS) continue; if (notify_tty(ut->ut_line, manufacturer, product, devnode) == -1) { log_fn("Could not notify %s (@%s) about device %s (%s %s).", ut->ut_user, ut->ut_line, devnode, manufacturer, product); } else { log_fn("Notified %s (@%s) about device %s (%s %s).", ut->ut_user, ut->ut_line, devnode, manufacturer, product); ttys_notified++; } } endutent(); return ttys_notified; }
int check_utmp (int total_unused) { /* replace total_unused with the minimum of * total_unused and the shortest utmp idle time. */ typedef struct utmp utmp_t; utmp_t *u; int min_idle=2*max_unused; utmpname(UTMP_FILE); setutent(); while ((u=getutent())) { if (u->ut_type == USER_PROCESS) { /* get tty. From w.c in procps by Charles Blake. */ char tty[5 + sizeof u->ut_line + 1] = "/dev/"; int i; for (i=0; i < sizeof u->ut_line; i++) { /* clean up tty if garbled */ if (isalnum(u->ut_line[i]) || (u->ut_line[i]=='/')) { tty[i+5] = u->ut_line[i]; } else { tty[i+5] = '\0'; } } int cur_idle=idletime(tty); min_idle = (cur_idle < min_idle) ? cur_idle : min_idle; } } /* The shortest idle time is the real idle time */ total_unused = (min_idle < total_unused) ? min_idle : total_unused; if (debug && total_unused == min_idle) printf("sleepd: activity: utmp %d seconds\n", min_idle); return total_unused; }
static int do_check (void) { struct utmp *ut; int n; setutent (); n = 0; while ((ut = getutent ())) { if (n < num_entries && memcmp (ut, &entry[n], sizeof (struct utmp))) { printf ("UTMP entry does not match"); ++errors; return 1; } n++; } if (n != num_entries) { printf ("number of UTMP entries is incorrect"); ++errors; return 1; } endutent (); return 0; }
void utmp_login(char *tty, const char *username, const char *hostname) { struct utmp utmp; int fd; prepare_utmp (&utmp, tty, username, hostname); #ifdef HAVE_SETUTENT utmpname(_PATH_UTMP); setutent(); pututline(&utmp); endutent(); #else #ifdef HAVE_TTYSLOT { int ttyno; ttyno = ttyslot(); if (ttyno > 0 && (fd = open(_PATH_UTMP, O_WRONLY, 0)) >= 0) { lseek(fd, (long)(ttyno * sizeof(struct utmp)), SEEK_SET); write(fd, &utmp, sizeof(struct utmp)); close(fd); } } #endif /* HAVE_TTYSLOT */ #endif /* HAVE_SETUTENT */ if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { write(fd, &utmp, sizeof(struct utmp)); close(fd); } }
int who_main(int argc, char **argv) { char str6[6]; struct utmp *ut; struct stat st; char *name; if (argc > 1) { bb_show_usage(); } setutent(); printf("USER TTY IDLE TIME HOST\n"); while ((ut = getutent()) != NULL) { if (ut->ut_user[0] && ut->ut_type == USER_PROCESS) { time_t thyme = ut->ut_tv.tv_sec; /* ut->ut_line is device name of tty - "/dev/" */ name = concat_path_file("/dev", ut->ut_line); str6[0] = '?'; str6[1] = '\0'; if (stat(name, &st) == 0) idle_string(str6, st.st_atime); printf("%-10s %-8s %-9s %-14.14s %s\n", ut->ut_user, ut->ut_line, str6, ctime(&thyme) + 4, ut->ut_host); if (ENABLE_FEATURE_CLEAN_UP) free(name); } } if (ENABLE_FEATURE_CLEAN_UP) endutent(); return 0; }
/* * get_current_utmp - return the most probable utmp entry for the current * session * * The utmp file is scanned for an entry with the same process ID. * The line enterred by the *getty / telnetd, etc. should also match * the current terminal. * * When an entry is returned by get_current_utmp, and if the utmp * structure has a ut_id field, this field should be used to update * the entry information. * * Return NULL if no entries exist in utmp for the current process. */ /*@null@*/ /*@only@*/struct utmp *get_current_utmp (void) { struct utmp *ut; struct utmp *ret = NULL; setutent (); /* First, try to find a valid utmp entry for this process. */ while ((ut = getutent ()) != NULL) { if ( (ut->ut_pid == getpid ()) #ifdef HAVE_STRUCT_UTMP_UT_ID && ('\0' != ut->ut_id[0]) #endif #ifdef HAVE_STRUCT_UTMP_UT_TYPE && ( (LOGIN_PROCESS == ut->ut_type) || (USER_PROCESS == ut->ut_type)) #endif /* A process may have failed to close an entry * Check if this entry refers to the current tty */ && is_my_tty (ut->ut_line)) { break; } } if (NULL != ut) { ret = (struct utmp *) xmalloc (sizeof (*ret)); memcpy (ret, ut, sizeof (*ret)); } endutent (); return ret; }
int main(int argc, char **argv) { struct utmp *ut; const char *user, *host; printf("%8s %8s %16s %8s %4s\n", "NAME", "LINE", "HOST", "TIME", "PID"); setutent(); while (NULL != (ut = getutent())) { host = strlen(ut->ut_host) ? ut->ut_host : localhost; user = ut->ut_user; switch (ut->ut_type) { case USER_PROCESS: break; case LOGIN_PROCESS: user = login; break; case DEAD_PROCESS: default: continue; } printf("%8s %8s %16s %8s %4d\n", user, ut->ut_line, host, "", ut->ut_pid); } return 0; }
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 who_main(int argc UNUSED_PARAM, char **argv) { struct utmp *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 printf("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST\n"); setutent(); while ((ut = getutent()) != 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) endutent(); return EXIT_SUCCESS; }
int main(int argc, char **argv) { extern int optind; int ch; struct iovec iov; struct utmp *utmpptr; char *p; char line[sizeof(utmpptr->ut_line) + 1]; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((ch = getopt(argc, argv, "n")) != -1) { switch (ch) { case 'n': if (geteuid() == 0) nobanner = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc > 1) usage(); makemsg(*argv); setutent(); iov.iov_base = mbuf; iov.iov_len = mbufsize; while((utmpptr = getutent())) { if (!utmpptr->ut_name[0] || !strncmp(utmpptr->ut_name, IGNOREUSER, sizeof(utmpptr->ut_name))) continue; #ifdef USER_PROCESS if (utmpptr->ut_type != USER_PROCESS) continue; #endif /* Joey Hess reports that use-sessreg in /etc/X11/wdm/ produces ut_line entries like :0, and a write to /dev/:0 fails. */ if (utmpptr->ut_line[0] == ':') continue; xstrncpy(line, utmpptr->ut_line, sizeof(utmpptr->ut_line)); if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL) warnx("%s", p); } endutent(); exit(EXIT_SUCCESS); }
struct utmp * getutent () { if (utmp_fd == -2) setutent (); if (read (utmp_fd, &utmp_data, sizeof (utmp_data)) < sizeof (utmp_data)) return 0; return &utmp_data; }
struct utmp * getutent(void) { if (ut_fd==-1) setutent(); if (ut_fd==-1) return NULL; return __getutent(ut_fd); }
static int utmp_write_library(struct logininfo *li, struct utmp *ut) { setutent(); pututline(ut); # ifdef HAVE_ENDUTENT endutent(); # endif return (1); }
int logout (const char *line) { struct UT tmp; struct UT *ut; int result = 0; /* if (utmpname (_PATH_UTMP) == -1) return 0; - why? * this makes it impossible for caller to use other file! * Does any standard or historical precedent says this must be done? */ /* Open UTMP file. */ setutent (); /* Fill in search information. */ #if _HAVE_UT_TYPE - 0 tmp.ut_type = USER_PROCESS; #endif strncpy (tmp.ut_line, line, sizeof tmp.ut_line); /* Read the record. */ if ((ut = getutline(&tmp)) != NULL) { /* Clear information about who & from where. */ memset (ut->ut_name, 0, sizeof ut->ut_name); #if _HAVE_UT_HOST - 0 memset (ut->ut_host, 0, sizeof ut->ut_host); #endif #if _HAVE_UT_TV - 0 # if !defined __WORDSIZE_TIME64_COMPAT32 gettimeofday (&ut->ut_tv, NULL); # else { struct timeval tv; gettimeofday (&tv, NULL); ut->ut_tv.tv_sec = tv.tv_sec; ut->ut_tv.tv_usec = tv.tv_usec; } # endif #else time (&ut->ut_time); #endif #if _HAVE_UT_TYPE - 0 ut->ut_type = DEAD_PROCESS; #endif if (pututline (ut) != NULL) result = 1; } /* Close UTMP file. */ endutent (); return result; }
struct utmp * getutent(void) { static struct utmp utmp; if (ut_fd==-1) setutent(); if (ut_fd==-1) return NULL; if (read(ut_fd, (char *) &utmp, sizeof(struct utmp))!=sizeof(struct utmp)) return NULL; return &utmp; }