From 5fce52076eeb01dfb1717bc9b43fa5ab46f5eaf1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 18 Nov 1994 05:15:04 +0000 Subject: [PATCH] (list_entries): Delete. Split in two actually... (list_entries_users, list_entries_who, userid_compare): New functions. (list_entries_users): Sort the user names. Reported by Michael I Bushnell. Topologically sort the functions and remove fwd declarations. --- src/who.c | 472 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 266 insertions(+), 206 deletions(-) diff --git a/src/who.c b/src/who.c index acfd1d0..e9e9628 100644 --- a/src/who.c +++ b/src/who.c @@ -85,23 +85,10 @@ #endif /* USERS */ #endif /* WHO */ -char *xmalloc (); void error (); -char *ttyname (); int gethostname (); - -static int read_utmp (); -#ifdef WHO -static const char *idle_string (); -static STRUCT_UTMP *search_entries (); -static void print_entry (); -static void print_heading (); -static void scan_entries (); -static void who_am_i (); -#endif /* WHO */ -static void list_entries (); -static void usage (); -static void who (); +char *ttyname (); +char *xmalloc (); /* The name this program was run with. */ char *program_name; @@ -146,164 +133,60 @@ static struct option const longopts[] = {NULL, 0, NULL, 0} }; -void -main (argc, argv) - int argc; - char **argv; -{ - int optc, longind; -#ifdef WHO - int my_line_only = 0; -#endif /* WHO */ - - program_name = argv[0]; - -#ifdef WHO - while ((optc = getopt_long (argc, argv, "imqsuwHT", longopts, &longind)) -#else - while ((optc = getopt_long (argc, argv, "", longopts, &longind)) -#endif /* WHO */ - != EOF) - { - switch (optc) - { - case 0: - break; - -#ifdef WHO - case 'm': - my_line_only = 1; - break; - - case 'q': - short_list = 1; - break; - - case 's': - break; - - case 'i': - case 'u': - include_idle = 1; - break; - - case 'H': - include_heading = 1; - break; - - case 'w': - case 'T': - include_mesg = 1; - break; -#endif /* WHO */ - - default: - error (0, 0, "too many arguments"); - usage (1); - } - } - - if (show_version) - { - printf ("%s - %s\n", COMMAND_NAME, version_string); - exit (0); - } - - if (show_help) - usage (0); - - switch (argc - optind) - { - case 0: /* who */ -#ifdef WHO - if (my_line_only) - who_am_i (UTMP_FILE); - else -#endif /* WHO */ - who (UTMP_FILE); - break; +static STRUCT_UTMP *utmp_contents; - case 1: /* who */ -#ifdef WHO - if (my_line_only) - who_am_i (argv[optind]); - else -#endif /* WHO */ - who (argv[optind]); - break; +#if defined (WHO) || defined (USERS) -#ifdef WHO - case 2: /* who */ - who_am_i (UTMP_FILE); - break; -#endif /* WHO */ +/* Copy UT->ut_name into storage obtained from malloc. Then remove any + trailing spaces from the copy, NUL terminate it, and return the copy. */ - default: /* lose */ - usage (1); - } - - exit (0); +static char * +extract_trimmed_name (const STRUCT_UTMP *ut) +{ + char *p, *trimmed_name; + + trimmed_name = xmalloc (sizeof (ut->ut_name) + 1); + strncpy (trimmed_name, ut->ut_name, sizeof (ut->ut_name)); + /* Append a trailing space character. Some systems pad names shorter than + the maximum with spaces, others pad with NULs. Remove any spaces. */ + trimmed_name[sizeof (ut->ut_name)] = ' '; + p = index (trimmed_name, ' '); + if (p != NULL) + *p = '\0'; + return trimmed_name; } -static STRUCT_UTMP *utmp_contents; +#endif /* WHO || USERS */ -/* Display a list of who is on the system, according to utmp file FILENAME. */ - -static void -who (filename) - char *filename; -{ - int users; +#if WHO - users = read_utmp (filename); -#ifdef WHO - if (short_list) - list_entries (users); - else - scan_entries (users); -#else -#ifdef USERS - list_entries (users); -#endif /* USERS */ -#endif /* WHO */ -} - -/* Read the utmp file FILENAME into UTMP_CONTENTS and return the - number of entries it contains. */ +/* Return a string representing the time between WHEN and the time + that this function is first run. */ -static int -read_utmp (filename) - char *filename; +static const char * +idle_string (when) + time_t when; { - FILE *utmp; - struct stat file_stats; - int n_read; - size_t size; + static time_t now = 0; + static char idle[10]; + time_t seconds_idle; - utmp = fopen (filename, "r"); - if (utmp == NULL) - error (1, errno, "%s", filename); + if (now == 0) + time (&now); - fstat (fileno (utmp), &file_stats); - size = file_stats.st_size; - if (size > 0) - utmp_contents = (STRUCT_UTMP *) xmalloc (size); - else + seconds_idle = now - when; + if (seconds_idle < 60) /* One minute. */ + return " . "; + if (seconds_idle < (24 * 60 * 60)) /* One day. */ { - fclose (utmp); - return 0; + sprintf (idle, "%02d:%02d", + (int) (seconds_idle / (60 * 60)), + (int) ((seconds_idle % (60 * 60)) / 60)); + return (const char *) idle; } - - /* Use < instead of != in case the utmp just grew. */ - n_read = fread (utmp_contents, 1, size, utmp); - if (ferror (utmp) || fclose (utmp) == EOF - || n_read < size) - error (1, errno, "%s", filename); - - return size / sizeof (STRUCT_UTMP); + return " old "; } -#ifdef WHO /* Display a line of information about entry THIS. */ static void @@ -329,7 +212,7 @@ print_entry (this) } else { - strcpy(line, DEV_DIR_WITH_TRAILING_SLASH); + strcpy (line, DEV_DIR_WITH_TRAILING_SLASH); strncpy (line + DEV_DIR_LEN, this->ut_line, sizeof (this->ut_line)); line[DEV_DIR_LEN + sizeof (this->ut_line)] = '\0'; } @@ -370,19 +253,18 @@ print_entry (this) putchar ('\n'); } -#endif /* WHO */ -#if defined (WHO) || defined (USERS) /* Print the username of each valid entry and the number of valid entries in `utmp_contents', which should have N elements. */ static void -list_entries (n) +list_entries_who (n) int n; { register STRUCT_UTMP *this = utmp_contents; - register int entries = 0; + int entries; + entries = 0; while (n--) { if (this->ut_name[0] @@ -391,30 +273,76 @@ list_entries (n) #endif ) { - char trimmed_name[sizeof (this->ut_name) + 1]; - int i; - - strncpy (trimmed_name, this->ut_name, sizeof (this->ut_name)); - trimmed_name[sizeof (this->ut_name)] = ' '; - for (i = 0; i <= sizeof (this->ut_name); i++) - { - if (trimmed_name[i] == ' ') - break; - } - trimmed_name[i] = '\0'; + char *trimmed_name; + + trimmed_name = extract_trimmed_name (this); printf ("%s ", trimmed_name); + free (trimmed_name); entries++; } this++; } -#ifdef WHO printf ("\n# users=%u\n", entries); -#else - putchar('\n'); +} + #endif /* WHO */ + +#ifdef USERS + +static int +userid_compare (const void *v_a, const void *v_b) +{ + char **a = (char **) v_a; + char **b = (char **) v_b; + return strcmp (*a, *b); } -#endif /* defined (WHO) || defined (USERS) */ + +static void +list_entries_users (n) + int n; +{ + register STRUCT_UTMP *this = utmp_contents; + char **u; + int i; + int n_entries; + + n_entries = 0; + u = (char **) xmalloc (n * sizeof (u[0])); + for (i=0; iut_name[0] +#ifdef USER_PROCESS + && this->ut_type == USER_PROCESS +#endif + ) + { + char *trimmed_name; + + trimmed_name = extract_trimmed_name (this); + + u[n_entries] = trimmed_name; + ++n_entries; + } + this++; + } + + qsort (u, n_entries, sizeof (u[0]), userid_compare); + + for (i=0; i 0) + utmp_contents = (STRUCT_UTMP *) xmalloc (size); + else + { + fclose (utmp); + return 0; + } + + /* Use < instead of != in case the utmp just grew. */ + n_read = fread (utmp_contents, 1, size, utmp); + if (ferror (utmp) || fclose (utmp) == EOF + || n_read < size) + error (1, errno, "%s", filename); + + return size / sizeof (STRUCT_UTMP); +} + +/* Display a list of who is on the system, according to utmp file FILENAME. */ + +static void +who (filename) + char *filename; +{ + int users; + + users = read_utmp (filename); +#ifdef WHO + if (short_list) + list_entries_who (users); + else + scan_entries (users); +#else +#ifdef USERS + list_entries_users (users); +#endif /* USERS */ +#endif /* WHO */ +} + +#ifdef WHO + /* Search `utmp_contents', which should have N entries, for an entry with a `ut_line' field identical to LINE. Return the first matching entry found, or NULL if there @@ -512,33 +500,6 @@ who_am_i (filename) print_entry (utmp_entry); } -/* Return a string representing the time between WHEN and the time - that this function is first run. */ - -static const char * -idle_string (when) - time_t when; -{ - static time_t now = 0; - static char idle[10]; - time_t seconds_idle; - - if (now == 0) - time (&now); - - seconds_idle = now - when; - if (seconds_idle < 60) /* One minute. */ - return " . "; - if (seconds_idle < (24 * 60 * 60)) /* One day. */ - { - sprintf (idle, "%02d:%02d", - (int) (seconds_idle / (60 * 60)), - (int) ((seconds_idle % (60 * 60)) / 60)); - return (const char *) idle; - } - return " old "; -} - static void usage (status) int status; @@ -570,7 +531,7 @@ If ARG1 ARG2 given, -m presumed: `am i' or `mom likes' are usual.\n\ } #endif /* WHO */ -#if defined (USERS) +#ifdef USERS static void usage (status) int status; @@ -592,3 +553,102 @@ If FILE not given, uses /etc/utmp. /etc/wtmp as FILE is common.\n\ exit (status); } #endif /* USERS */ + +void +main (argc, argv) + int argc; + char **argv; +{ + int optc, longind; +#ifdef WHO + int my_line_only = 0; +#endif /* WHO */ + + program_name = argv[0]; + +#ifdef WHO + while ((optc = getopt_long (argc, argv, "imqsuwHT", longopts, &longind)) +#else + while ((optc = getopt_long (argc, argv, "", longopts, &longind)) +#endif /* WHO */ + != EOF) + { + switch (optc) + { + case 0: + break; + +#ifdef WHO + case 'm': + my_line_only = 1; + break; + + case 'q': + short_list = 1; + break; + + case 's': + break; + + case 'i': + case 'u': + include_idle = 1; + break; + + case 'H': + include_heading = 1; + break; + + case 'w': + case 'T': + include_mesg = 1; + break; +#endif /* WHO */ + + default: + error (0, 0, "too many arguments"); + usage (1); + } + } + + if (show_version) + { + printf ("%s - %s\n", COMMAND_NAME, version_string); + exit (0); + } + + if (show_help) + usage (0); + + switch (argc - optind) + { + case 0: /* who */ +#ifdef WHO + if (my_line_only) + who_am_i (UTMP_FILE); + else +#endif /* WHO */ + who (UTMP_FILE); + break; + + case 1: /* who */ +#ifdef WHO + if (my_line_only) + who_am_i (argv[optind]); + else +#endif /* WHO */ + who (argv[optind]); + break; + +#ifdef WHO + case 2: /* who */ + who_am_i (UTMP_FILE); + break; +#endif /* WHO */ + + default: /* lose */ + usage (1); + } + + exit (0); +} -- 2.7.4