Reimplements users(1) in C++.

This reduces the lines of code by roughly 50% (not counting the COPYRIGHT
header) and makes it more readable by using standard algorithms.

Approved by:	bapt
This commit is contained in:
Pietro Cerutti 2014-07-10 12:15:02 +00:00
parent 479fcb4e32
commit 33aa643fa0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=268491
2 changed files with 27 additions and 66 deletions

View File

@ -1,6 +1,7 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
PROG= users
WARNS= 3
PROG_CXX= users
.include <bsd.prog.mk>

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1987, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 2014 Pietro Cerutti <gahr@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -27,83 +27,43 @@
* SUCH DAMAGE.
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1980, 1987, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifndef lint
#if 0
static char sccsid[] = "@(#)users.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/param.h>
#include <sys/types.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utmpx.h>
typedef char namebuf[sizeof(((struct utmpx *)0)->ut_user) + 1];
typedef int (*scmp)(const void *, const void *);
static void usage(void);
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
int
main(int argc, char **argv)
main(int argc, char **)
{
namebuf *names = NULL;
int ncnt = 0;
int nmax = 0;
int cnt;
struct utmpx *ut;
int ch;
vector<string> names;
while ((ch = getopt(argc, argv, "")) != -1)
switch(ch) {
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc > 1) {
cerr << "usage: users" << endl;
return (1);
}
setutxent();
while ((ut = getutxent()) != NULL) {
if (ut->ut_type != USER_PROCESS)
continue;
if (ncnt >= nmax) {
nmax += 32;
names = realloc(names, sizeof(*names) * nmax);
if (!names) {
errx(1, "realloc");
/* NOTREACHED */
}
}
strlcpy(names[ncnt], ut->ut_user, sizeof(*names));
++ncnt;
names.push_back(ut->ut_user);
}
endutxent();
if (ncnt > 0) {
qsort(names, ncnt, sizeof(*names), (scmp)strcmp);
printf("%s", names[0]);
for (cnt = 1; cnt < ncnt; ++cnt)
if (strcmp(names[cnt], names[cnt - 1]) != 0)
printf(" %s", names[cnt]);
printf("\n");
}
exit(0);
}
static void
usage(void)
{
fprintf(stderr, "usage: users\n");
exit(1);
if (names.size() == 0) {
return (0);
}
sort(begin(names), end(names));
vector<string>::iterator last(unique(begin(names), end(names)));
copy(begin(names), last-1, ostream_iterator<string>(cout, " "));
cout << *(last-1) << endl;
}