summaryrefslogtreecommitdiff
path: root/src/who.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1994-11-18 05:15:04 +0000
committerJim Meyering <jim@meyering.net>1994-11-18 05:15:04 +0000
commit5fce52076eeb01dfb1717bc9b43fa5ab46f5eaf1 (patch)
tree73eab5bd452977f134284526161fe6045562dabe /src/who.c
parent42c03d3135bd3b05f5e829436adefbc16a9b0a1a (diff)
downloadcoreutils-5fce52076eeb01dfb1717bc9b43fa5ab46f5eaf1.tar.xz
(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.
Diffstat (limited to 'src/who.c')
-rw-r--r--src/who.c472
1 files changed, 266 insertions, 206 deletions
diff --git a/src/who.c b/src/who.c
index acfd1d097..e9e962898 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 <utmp file> */
-#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 <blurf> <glop> */
- 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; i<n; i++)
+ {
+ if (this->ut_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<n_entries; i++)
+ {
+ int c;
+ fputs (u[i], stdout);
+ c = (i < n_entries-1 ? ' ' : '\n');
+ putchar (c);
+ }
+
+ for (i=0; i<n_entries; i++)
+ free (u[i]);
+ free (u);
+}
+
+#endif /* USERS */
#ifdef WHO
@@ -454,6 +382,66 @@ scan_entries (n)
}
}
+#endif /* WHO */
+
+/* Read the utmp file FILENAME into UTMP_CONTENTS and return the
+ number of entries it contains. */
+
+static int
+read_utmp (filename)
+ char *filename;
+{
+ FILE *utmp;
+ struct stat file_stats;
+ int n_read;
+ size_t size;
+
+ utmp = fopen (filename, "r");
+ if (utmp == NULL)
+ error (1, errno, "%s", filename);
+
+ fstat (fileno (utmp), &file_stats);
+ size = file_stats.st_size;
+ if (size > 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 <utmp file> */
+#ifdef WHO
+ if (my_line_only)
+ who_am_i (argv[optind]);
+ else
+#endif /* WHO */
+ who (argv[optind]);
+ break;
+
+#ifdef WHO
+ case 2: /* who <blurf> <glop> */
+ who_am_i (UTMP_FILE);
+ break;
+#endif /* WHO */
+
+ default: /* lose */
+ usage (1);
+ }
+
+ exit (0);
+}