10a5f38d4SDag-Erling Smørgrav /*-
21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
31de7b4b8SPedro F. Giffuni *
4e738085bSDag-Erling Smørgrav * Copyright (c) 2004 Dag-Erling Smørgrav
50a5f38d4SDag-Erling Smørgrav * All rights reserved.
60a5f38d4SDag-Erling Smørgrav *
70a5f38d4SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without
80a5f38d4SDag-Erling Smørgrav * modification, are permitted provided that the following conditions
90a5f38d4SDag-Erling Smørgrav * are met:
100a5f38d4SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright
110a5f38d4SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer
120a5f38d4SDag-Erling Smørgrav * in this position and unchanged.
130a5f38d4SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright
140a5f38d4SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the
150a5f38d4SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution.
160a5f38d4SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products
170a5f38d4SDag-Erling Smørgrav * derived from this software without specific prior written permission.
180a5f38d4SDag-Erling Smørgrav *
190a5f38d4SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
200a5f38d4SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
210a5f38d4SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
220a5f38d4SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
230a5f38d4SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
240a5f38d4SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
250a5f38d4SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
260a5f38d4SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
270a5f38d4SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
280a5f38d4SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290a5f38d4SDag-Erling Smørgrav */
300a5f38d4SDag-Erling Smørgrav
310a5f38d4SDag-Erling Smørgrav #include <sys/cdefs.h>
320a5f38d4SDag-Erling Smørgrav #include <err.h>
330a5f38d4SDag-Erling Smørgrav #include <grp.h>
340a5f38d4SDag-Erling Smørgrav #include <pwd.h>
350a5f38d4SDag-Erling Smørgrav #include <stdio.h>
360a5f38d4SDag-Erling Smørgrav #include <stdlib.h>
370a5f38d4SDag-Erling Smørgrav #include <string.h>
380a5f38d4SDag-Erling Smørgrav #include <time.h>
390a5f38d4SDag-Erling Smørgrav #include <unistd.h>
400a5f38d4SDag-Erling Smørgrav
410a5f38d4SDag-Erling Smørgrav struct xpasswd {
420a5f38d4SDag-Erling Smørgrav char *pw_name;
430a5f38d4SDag-Erling Smørgrav char *pw_passwd;
440a5f38d4SDag-Erling Smørgrav uid_t pw_uid;
450a5f38d4SDag-Erling Smørgrav gid_t pw_gid;
460a5f38d4SDag-Erling Smørgrav time_t pw_change;
470a5f38d4SDag-Erling Smørgrav char *pw_class;
480a5f38d4SDag-Erling Smørgrav char *pw_gecos;
490a5f38d4SDag-Erling Smørgrav char *pw_dir;
500a5f38d4SDag-Erling Smørgrav char *pw_shell;
510a5f38d4SDag-Erling Smørgrav time_t pw_expire;
520a5f38d4SDag-Erling Smørgrav int pw_selected;
530a5f38d4SDag-Erling Smørgrav };
540a5f38d4SDag-Erling Smørgrav
550a5f38d4SDag-Erling Smørgrav struct xgroup {
560a5f38d4SDag-Erling Smørgrav char *gr_name;
570a5f38d4SDag-Erling Smørgrav char *gr_passwd;
580a5f38d4SDag-Erling Smørgrav gid_t gr_gid;
590a5f38d4SDag-Erling Smørgrav char *gr_mem;
600a5f38d4SDag-Erling Smørgrav };
610a5f38d4SDag-Erling Smørgrav
620a5f38d4SDag-Erling Smørgrav static int everything = 1;
630a5f38d4SDag-Erling Smørgrav static int a_flag;
640a5f38d4SDag-Erling Smørgrav static int d_flag;
650a5f38d4SDag-Erling Smørgrav static const char *g_args;
660a5f38d4SDag-Erling Smørgrav static const char *l_args;
670a5f38d4SDag-Erling Smørgrav static int m_flag;
680a5f38d4SDag-Erling Smørgrav static int o_flag;
690a5f38d4SDag-Erling Smørgrav static int p_flag;
700a5f38d4SDag-Erling Smørgrav static int s_flag;
710a5f38d4SDag-Erling Smørgrav static int t_flag;
720a5f38d4SDag-Erling Smørgrav static int u_flag;
730a5f38d4SDag-Erling Smørgrav static int x_flag;
740a5f38d4SDag-Erling Smørgrav
750a5f38d4SDag-Erling Smørgrav static int
member(const char * elem,const char * list)760a5f38d4SDag-Erling Smørgrav member(const char *elem, const char *list)
770a5f38d4SDag-Erling Smørgrav {
780a5f38d4SDag-Erling Smørgrav char *p;
790a5f38d4SDag-Erling Smørgrav int len;
800a5f38d4SDag-Erling Smørgrav
810a5f38d4SDag-Erling Smørgrav p = strstr(list, elem);
820a5f38d4SDag-Erling Smørgrav len = strlen(elem);
830a5f38d4SDag-Erling Smørgrav
840a5f38d4SDag-Erling Smørgrav return (p != NULL &&
850a5f38d4SDag-Erling Smørgrav (p == list || p[-1] == ',') &&
860a5f38d4SDag-Erling Smørgrav (p[len] == '\0' || p[len] == ','));
870a5f38d4SDag-Erling Smørgrav }
880a5f38d4SDag-Erling Smørgrav
890a5f38d4SDag-Erling Smørgrav static void *
xmalloc(size_t size)900a5f38d4SDag-Erling Smørgrav xmalloc(size_t size)
910a5f38d4SDag-Erling Smørgrav {
920a5f38d4SDag-Erling Smørgrav void *newptr;
930a5f38d4SDag-Erling Smørgrav
940a5f38d4SDag-Erling Smørgrav if ((newptr = malloc(size)) == NULL)
950a5f38d4SDag-Erling Smørgrav err(1, "malloc()");
960a5f38d4SDag-Erling Smørgrav return (newptr);
970a5f38d4SDag-Erling Smørgrav }
980a5f38d4SDag-Erling Smørgrav
990a5f38d4SDag-Erling Smørgrav static void *
xrealloc(void * ptr,size_t size)1000a5f38d4SDag-Erling Smørgrav xrealloc(void *ptr, size_t size)
1010a5f38d4SDag-Erling Smørgrav {
1020a5f38d4SDag-Erling Smørgrav void *newptr;
1030a5f38d4SDag-Erling Smørgrav
1040a5f38d4SDag-Erling Smørgrav if ((newptr = realloc(ptr, size)) == NULL)
1050a5f38d4SDag-Erling Smørgrav err(1, "realloc()");
1060a5f38d4SDag-Erling Smørgrav return (newptr);
1070a5f38d4SDag-Erling Smørgrav }
1080a5f38d4SDag-Erling Smørgrav
1090a5f38d4SDag-Erling Smørgrav static char *
xstrdup(const char * str)1100a5f38d4SDag-Erling Smørgrav xstrdup(const char *str)
1110a5f38d4SDag-Erling Smørgrav {
1120a5f38d4SDag-Erling Smørgrav char *dupstr;
1130a5f38d4SDag-Erling Smørgrav
1140a5f38d4SDag-Erling Smørgrav if ((dupstr = strdup(str)) == NULL)
1150a5f38d4SDag-Erling Smørgrav err(1, "strdup()");
1160a5f38d4SDag-Erling Smørgrav return (dupstr);
1170a5f38d4SDag-Erling Smørgrav }
1180a5f38d4SDag-Erling Smørgrav
1190a5f38d4SDag-Erling Smørgrav static struct xgroup *grps;
1200a5f38d4SDag-Erling Smørgrav static size_t grpsz;
1210a5f38d4SDag-Erling Smørgrav static size_t ngrps;
1220a5f38d4SDag-Erling Smørgrav
1230a5f38d4SDag-Erling Smørgrav static void
get_groups(void)1240a5f38d4SDag-Erling Smørgrav get_groups(void)
1250a5f38d4SDag-Erling Smørgrav {
1260a5f38d4SDag-Erling Smørgrav struct group *grp;
1270a5f38d4SDag-Erling Smørgrav size_t len;
1280a5f38d4SDag-Erling Smørgrav int i;
1290a5f38d4SDag-Erling Smørgrav
1300a5f38d4SDag-Erling Smørgrav setgrent();
1310a5f38d4SDag-Erling Smørgrav for (;;) {
1320a5f38d4SDag-Erling Smørgrav if (ngrps == grpsz) {
1330a5f38d4SDag-Erling Smørgrav grpsz += grpsz ? grpsz : 128;
1340a5f38d4SDag-Erling Smørgrav grps = xrealloc(grps, grpsz * sizeof *grps);
1350a5f38d4SDag-Erling Smørgrav }
1360a5f38d4SDag-Erling Smørgrav if ((grp = getgrent()) == NULL)
1370a5f38d4SDag-Erling Smørgrav break;
1380a5f38d4SDag-Erling Smørgrav grps[ngrps].gr_name = xstrdup(grp->gr_name);
1390a5f38d4SDag-Erling Smørgrav grps[ngrps].gr_passwd = xstrdup(grp->gr_passwd);
1400a5f38d4SDag-Erling Smørgrav grps[ngrps].gr_gid = grp->gr_gid;
1410a5f38d4SDag-Erling Smørgrav grps[ngrps].gr_mem = xstrdup("");
1420a5f38d4SDag-Erling Smørgrav for (i = 0, len = 1; grp->gr_mem[i] != NULL; ++i)
1430a5f38d4SDag-Erling Smørgrav len += strlen(grp->gr_mem[i]) + 1;
1440a5f38d4SDag-Erling Smørgrav grps[ngrps].gr_mem = xmalloc(len);
1450a5f38d4SDag-Erling Smørgrav for (i = 0, len = 0; grp->gr_mem[i] != NULL; ++i)
1460a5f38d4SDag-Erling Smørgrav len += sprintf(grps[ngrps].gr_mem + len,
1470a5f38d4SDag-Erling Smørgrav i ? ",%s" : "%s", grp->gr_mem[i]);
1480a5f38d4SDag-Erling Smørgrav grps[ngrps].gr_mem[len] = '\0';
1490a5f38d4SDag-Erling Smørgrav ngrps++;
1500a5f38d4SDag-Erling Smørgrav }
1510a5f38d4SDag-Erling Smørgrav endgrent();
1520a5f38d4SDag-Erling Smørgrav }
1530a5f38d4SDag-Erling Smørgrav
1540a5f38d4SDag-Erling Smørgrav static struct xgroup *
find_group_bygid(gid_t gid)1550a5f38d4SDag-Erling Smørgrav find_group_bygid(gid_t gid)
1560a5f38d4SDag-Erling Smørgrav {
1570a5f38d4SDag-Erling Smørgrav unsigned int i;
1580a5f38d4SDag-Erling Smørgrav
1590a5f38d4SDag-Erling Smørgrav for (i = 0; i < ngrps; ++i)
1600a5f38d4SDag-Erling Smørgrav if (grps[i].gr_gid == gid)
1610a5f38d4SDag-Erling Smørgrav return (&grps[i]);
1620a5f38d4SDag-Erling Smørgrav return (NULL);
1630a5f38d4SDag-Erling Smørgrav }
1640a5f38d4SDag-Erling Smørgrav
1650a5f38d4SDag-Erling Smørgrav #if 0
1660a5f38d4SDag-Erling Smørgrav static struct xgroup *
1670a5f38d4SDag-Erling Smørgrav find_group_byname(const char *name)
1680a5f38d4SDag-Erling Smørgrav {
1690a5f38d4SDag-Erling Smørgrav unsigned int i;
1700a5f38d4SDag-Erling Smørgrav
1710a5f38d4SDag-Erling Smørgrav for (i = 0; i < ngrps; ++i)
1720a5f38d4SDag-Erling Smørgrav if (strcmp(grps[i].gr_name, name) == 0)
1730a5f38d4SDag-Erling Smørgrav return (&grps[i]);
1740a5f38d4SDag-Erling Smørgrav return (NULL);
1750a5f38d4SDag-Erling Smørgrav }
1760a5f38d4SDag-Erling Smørgrav #endif
1770a5f38d4SDag-Erling Smørgrav
1780a5f38d4SDag-Erling Smørgrav static struct xpasswd *pwds;
1790a5f38d4SDag-Erling Smørgrav static size_t pwdsz;
1800a5f38d4SDag-Erling Smørgrav static size_t npwds;
1810a5f38d4SDag-Erling Smørgrav
1820a5f38d4SDag-Erling Smørgrav static int
pwd_cmp_byname(const void * ap,const void * bp)1830a5f38d4SDag-Erling Smørgrav pwd_cmp_byname(const void *ap, const void *bp)
1840a5f38d4SDag-Erling Smørgrav {
1850a5f38d4SDag-Erling Smørgrav const struct passwd *a = ap;
1860a5f38d4SDag-Erling Smørgrav const struct passwd *b = bp;
1870a5f38d4SDag-Erling Smørgrav
1880a5f38d4SDag-Erling Smørgrav return (strcmp(a->pw_name, b->pw_name));
1890a5f38d4SDag-Erling Smørgrav }
1900a5f38d4SDag-Erling Smørgrav
1910a5f38d4SDag-Erling Smørgrav static int
pwd_cmp_byuid(const void * ap,const void * bp)1920a5f38d4SDag-Erling Smørgrav pwd_cmp_byuid(const void *ap, const void *bp)
1930a5f38d4SDag-Erling Smørgrav {
1940a5f38d4SDag-Erling Smørgrav const struct passwd *a = ap;
1950a5f38d4SDag-Erling Smørgrav const struct passwd *b = bp;
1960a5f38d4SDag-Erling Smørgrav
1970a5f38d4SDag-Erling Smørgrav return (a->pw_uid - b->pw_uid);
1980a5f38d4SDag-Erling Smørgrav }
1990a5f38d4SDag-Erling Smørgrav
2000a5f38d4SDag-Erling Smørgrav static void
get_users(void)2010a5f38d4SDag-Erling Smørgrav get_users(void)
2020a5f38d4SDag-Erling Smørgrav {
2030a5f38d4SDag-Erling Smørgrav struct passwd *pwd;
2040a5f38d4SDag-Erling Smørgrav
2050a5f38d4SDag-Erling Smørgrav setpwent();
2060a5f38d4SDag-Erling Smørgrav for (;;) {
2070a5f38d4SDag-Erling Smørgrav if (npwds == pwdsz) {
2080a5f38d4SDag-Erling Smørgrav pwdsz += pwdsz ? pwdsz : 128;
2090a5f38d4SDag-Erling Smørgrav pwds = xrealloc(pwds, pwdsz * sizeof *pwds);
2100a5f38d4SDag-Erling Smørgrav }
2110a5f38d4SDag-Erling Smørgrav if ((pwd = getpwent()) == NULL)
2120a5f38d4SDag-Erling Smørgrav break;
2130a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_name = xstrdup(pwd->pw_name);
2140a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_passwd = xstrdup(pwd->pw_passwd);
2150a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_uid = pwd->pw_uid;
2160a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_gid = pwd->pw_gid;
2170a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_change = pwd->pw_change;
2180a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_class = xstrdup(pwd->pw_class);
2190a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_gecos = xstrdup(pwd->pw_gecos);
2200a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_dir = xstrdup(pwd->pw_dir);
2210a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_shell = xstrdup(pwd->pw_shell);
2220a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_expire = pwd->pw_expire;
2230a5f38d4SDag-Erling Smørgrav pwds[npwds].pw_selected = 0;
2240a5f38d4SDag-Erling Smørgrav npwds++;
2250a5f38d4SDag-Erling Smørgrav }
2260a5f38d4SDag-Erling Smørgrav endpwent();
2270a5f38d4SDag-Erling Smørgrav }
2280a5f38d4SDag-Erling Smørgrav
2290a5f38d4SDag-Erling Smørgrav static void
select_users(void)2300a5f38d4SDag-Erling Smørgrav select_users(void)
2310a5f38d4SDag-Erling Smørgrav {
2320a5f38d4SDag-Erling Smørgrav unsigned int i, j;
2330a5f38d4SDag-Erling Smørgrav struct xgroup *grp;
2340a5f38d4SDag-Erling Smørgrav struct xpasswd *pwd;
2350a5f38d4SDag-Erling Smørgrav
2360a5f38d4SDag-Erling Smørgrav for (i = 0, pwd = pwds; i < npwds; ++i, ++pwd) {
2370a5f38d4SDag-Erling Smørgrav if (everything) {
2380a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2390a5f38d4SDag-Erling Smørgrav continue;
2400a5f38d4SDag-Erling Smørgrav }
2410a5f38d4SDag-Erling Smørgrav if (d_flag)
2420a5f38d4SDag-Erling Smørgrav if ((i > 0 && pwd->pw_uid == pwd[-1].pw_uid) ||
2430a5f38d4SDag-Erling Smørgrav (i < npwds - 1 && pwd->pw_uid == pwd[1].pw_uid)) {
2440a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2450a5f38d4SDag-Erling Smørgrav continue;
2460a5f38d4SDag-Erling Smørgrav }
2470a5f38d4SDag-Erling Smørgrav if (g_args) {
2480a5f38d4SDag-Erling Smørgrav for (j = 0, grp = grps; j < ngrps; ++j, ++grp) {
2490a5f38d4SDag-Erling Smørgrav if (member(grp->gr_name, g_args) &&
2500a5f38d4SDag-Erling Smørgrav member(pwd->pw_name, grp->gr_mem)) {
2510a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2520a5f38d4SDag-Erling Smørgrav break;
2530a5f38d4SDag-Erling Smørgrav }
2540a5f38d4SDag-Erling Smørgrav }
2550a5f38d4SDag-Erling Smørgrav if (pwd->pw_selected)
2560a5f38d4SDag-Erling Smørgrav continue;
2570a5f38d4SDag-Erling Smørgrav }
2580a5f38d4SDag-Erling Smørgrav if (l_args)
2590a5f38d4SDag-Erling Smørgrav if (member(pwd->pw_name, l_args)) {
2600a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2610a5f38d4SDag-Erling Smørgrav continue;
2620a5f38d4SDag-Erling Smørgrav }
2630a5f38d4SDag-Erling Smørgrav if (p_flag)
2640a5f38d4SDag-Erling Smørgrav if (pwd->pw_passwd[0] == '\0') {
2650a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2660a5f38d4SDag-Erling Smørgrav continue;
2670a5f38d4SDag-Erling Smørgrav }
2680a5f38d4SDag-Erling Smørgrav if (s_flag)
2690a5f38d4SDag-Erling Smørgrav if (pwd->pw_uid < 1000 || pwd->pw_uid == 65534) {
2700a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2710a5f38d4SDag-Erling Smørgrav continue;
2720a5f38d4SDag-Erling Smørgrav }
2730a5f38d4SDag-Erling Smørgrav if (u_flag)
2740a5f38d4SDag-Erling Smørgrav if (pwd->pw_uid >= 1000 && pwd->pw_uid != 65534) {
2750a5f38d4SDag-Erling Smørgrav pwd->pw_selected = 1;
2760a5f38d4SDag-Erling Smørgrav continue;
2770a5f38d4SDag-Erling Smørgrav }
2780a5f38d4SDag-Erling Smørgrav }
2790a5f38d4SDag-Erling Smørgrav }
2800a5f38d4SDag-Erling Smørgrav
2810a5f38d4SDag-Erling Smørgrav static void
sort_users(void)2820a5f38d4SDag-Erling Smørgrav sort_users(void)
2830a5f38d4SDag-Erling Smørgrav {
2840a5f38d4SDag-Erling Smørgrav if (t_flag)
2850a5f38d4SDag-Erling Smørgrav mergesort(pwds, npwds, sizeof *pwds, pwd_cmp_byname);
2860a5f38d4SDag-Erling Smørgrav else
2870a5f38d4SDag-Erling Smørgrav mergesort(pwds, npwds, sizeof *pwds, pwd_cmp_byuid);
2880a5f38d4SDag-Erling Smørgrav }
2890a5f38d4SDag-Erling Smørgrav
2900a5f38d4SDag-Erling Smørgrav static void
display_user(struct xpasswd * pwd)2910a5f38d4SDag-Erling Smørgrav display_user(struct xpasswd *pwd)
2920a5f38d4SDag-Erling Smørgrav {
2930a5f38d4SDag-Erling Smørgrav struct xgroup *grp;
2940a5f38d4SDag-Erling Smørgrav unsigned int i;
2950a5f38d4SDag-Erling Smørgrav char cbuf[16], ebuf[16];
2960a5f38d4SDag-Erling Smørgrav struct tm *tm;
2970a5f38d4SDag-Erling Smørgrav
2980a5f38d4SDag-Erling Smørgrav grp = find_group_bygid(pwd->pw_gid);
2990a5f38d4SDag-Erling Smørgrav printf(o_flag ? "%s:%ld:%s:%ld:%s" : "%-15s %-7ld %-15s %-7ld %s\n",
3000a5f38d4SDag-Erling Smørgrav pwd->pw_name, (long)pwd->pw_uid, grp ? grp->gr_name : "",
3010a5f38d4SDag-Erling Smørgrav (long)pwd->pw_gid, pwd->pw_gecos);
3020a5f38d4SDag-Erling Smørgrav if (m_flag) {
3030a5f38d4SDag-Erling Smørgrav for (i = 0, grp = grps; i < ngrps; ++i, ++grp) {
3040a5f38d4SDag-Erling Smørgrav if (grp->gr_gid == pwd->pw_gid ||
3050a5f38d4SDag-Erling Smørgrav !member(pwd->pw_name, grp->gr_mem))
3060a5f38d4SDag-Erling Smørgrav continue;
3070a5f38d4SDag-Erling Smørgrav printf(o_flag ? "%s:%s:%ld" : "%24s%-15s %-7ld\n",
3080a5f38d4SDag-Erling Smørgrav "", grp->gr_name, (long)grp->gr_gid);
3090a5f38d4SDag-Erling Smørgrav }
3100a5f38d4SDag-Erling Smørgrav }
3110a5f38d4SDag-Erling Smørgrav if (x_flag) {
3120a5f38d4SDag-Erling Smørgrav printf(o_flag ? "%s:%s" : "%24s%s\n", "", pwd->pw_dir);
3130a5f38d4SDag-Erling Smørgrav printf(o_flag ? "%s:%s" : "%24s%s\n", "", pwd->pw_shell);
3140a5f38d4SDag-Erling Smørgrav }
3150a5f38d4SDag-Erling Smørgrav if (a_flag) {
3160a5f38d4SDag-Erling Smørgrav tm = gmtime(&pwd->pw_change);
3170a5f38d4SDag-Erling Smørgrav strftime(cbuf, sizeof(cbuf), pwd->pw_change ? "%F" : "0", tm);
3180a5f38d4SDag-Erling Smørgrav tm = gmtime(&pwd->pw_expire);
3190a5f38d4SDag-Erling Smørgrav strftime(ebuf, sizeof(ebuf), pwd->pw_expire ? "%F" : "0", tm);
3200a5f38d4SDag-Erling Smørgrav printf(o_flag ? "%s:%s:%s" : "%24s%s %s\n", "", cbuf, ebuf);
3210a5f38d4SDag-Erling Smørgrav }
3220a5f38d4SDag-Erling Smørgrav if (o_flag)
3230a5f38d4SDag-Erling Smørgrav printf("\n");
3240a5f38d4SDag-Erling Smørgrav }
3250a5f38d4SDag-Erling Smørgrav
3260a5f38d4SDag-Erling Smørgrav static void
list_users(void)3270a5f38d4SDag-Erling Smørgrav list_users(void)
3280a5f38d4SDag-Erling Smørgrav {
3290a5f38d4SDag-Erling Smørgrav struct xpasswd *pwd;
3300a5f38d4SDag-Erling Smørgrav unsigned int i;
3310a5f38d4SDag-Erling Smørgrav
3320a5f38d4SDag-Erling Smørgrav for (i = 0, pwd = pwds; i < npwds; ++i, ++pwd)
3330a5f38d4SDag-Erling Smørgrav if (pwd->pw_selected)
3340a5f38d4SDag-Erling Smørgrav display_user(pwd);
3350a5f38d4SDag-Erling Smørgrav }
3360a5f38d4SDag-Erling Smørgrav
3370a5f38d4SDag-Erling Smørgrav static void
usage(void)3380a5f38d4SDag-Erling Smørgrav usage(void)
3390a5f38d4SDag-Erling Smørgrav {
3400a5f38d4SDag-Erling Smørgrav fprintf(stderr, "usage: logins [-admopstux] [-g group] [-l login]\n");
3410a5f38d4SDag-Erling Smørgrav exit(1);
3420a5f38d4SDag-Erling Smørgrav }
3430a5f38d4SDag-Erling Smørgrav
3440a5f38d4SDag-Erling Smørgrav int
main(int argc,char * const argv[])3450a5f38d4SDag-Erling Smørgrav main(int argc, char * const argv[])
3460a5f38d4SDag-Erling Smørgrav {
3470a5f38d4SDag-Erling Smørgrav int o;
3480a5f38d4SDag-Erling Smørgrav
3490a5f38d4SDag-Erling Smørgrav while ((o = getopt(argc, argv, "adg:l:mopstux")) != -1)
3500a5f38d4SDag-Erling Smørgrav switch (o) {
3510a5f38d4SDag-Erling Smørgrav case 'a':
3520a5f38d4SDag-Erling Smørgrav a_flag = 1;
3530a5f38d4SDag-Erling Smørgrav break;
3540a5f38d4SDag-Erling Smørgrav case 'd':
3550a5f38d4SDag-Erling Smørgrav everything = 0;
3560a5f38d4SDag-Erling Smørgrav d_flag = 1;
3570a5f38d4SDag-Erling Smørgrav break;
3580a5f38d4SDag-Erling Smørgrav case 'g':
3590a5f38d4SDag-Erling Smørgrav everything = 0;
3600a5f38d4SDag-Erling Smørgrav g_args = optarg;
3610a5f38d4SDag-Erling Smørgrav break;
3620a5f38d4SDag-Erling Smørgrav case 'l':
3630a5f38d4SDag-Erling Smørgrav everything = 0;
3640a5f38d4SDag-Erling Smørgrav l_args = optarg;
3650a5f38d4SDag-Erling Smørgrav break;
3660a5f38d4SDag-Erling Smørgrav case 'm':
3670a5f38d4SDag-Erling Smørgrav m_flag = 1;
3680a5f38d4SDag-Erling Smørgrav break;
3690a5f38d4SDag-Erling Smørgrav case 'o':
3700a5f38d4SDag-Erling Smørgrav o_flag = 1;
3710a5f38d4SDag-Erling Smørgrav break;
3720a5f38d4SDag-Erling Smørgrav case 'p':
3730a5f38d4SDag-Erling Smørgrav everything = 0;
3740a5f38d4SDag-Erling Smørgrav p_flag = 1;
3750a5f38d4SDag-Erling Smørgrav break;
3760a5f38d4SDag-Erling Smørgrav case 's':
3770a5f38d4SDag-Erling Smørgrav everything = 0;
3780a5f38d4SDag-Erling Smørgrav s_flag = 1;
3790a5f38d4SDag-Erling Smørgrav break;
3800a5f38d4SDag-Erling Smørgrav case 't':
3810a5f38d4SDag-Erling Smørgrav t_flag = 1;
3820a5f38d4SDag-Erling Smørgrav break;
3830a5f38d4SDag-Erling Smørgrav case 'u':
3840a5f38d4SDag-Erling Smørgrav everything = 0;
3850a5f38d4SDag-Erling Smørgrav u_flag = 1;
3860a5f38d4SDag-Erling Smørgrav break;
3870a5f38d4SDag-Erling Smørgrav case 'x':
3880a5f38d4SDag-Erling Smørgrav x_flag = 1;
3890a5f38d4SDag-Erling Smørgrav break;
3900a5f38d4SDag-Erling Smørgrav default:
3910a5f38d4SDag-Erling Smørgrav usage();
3920a5f38d4SDag-Erling Smørgrav }
3930a5f38d4SDag-Erling Smørgrav
3940a5f38d4SDag-Erling Smørgrav argc -= optind;
3950a5f38d4SDag-Erling Smørgrav argv += optind;
3960a5f38d4SDag-Erling Smørgrav
3970a5f38d4SDag-Erling Smørgrav if (argc > 0)
3980a5f38d4SDag-Erling Smørgrav usage();
3990a5f38d4SDag-Erling Smørgrav
4000a5f38d4SDag-Erling Smørgrav get_groups();
4010a5f38d4SDag-Erling Smørgrav get_users();
4020a5f38d4SDag-Erling Smørgrav select_users();
4030a5f38d4SDag-Erling Smørgrav sort_users();
4040a5f38d4SDag-Erling Smørgrav list_users();
4050a5f38d4SDag-Erling Smørgrav exit(0);
4060a5f38d4SDag-Erling Smørgrav }
407