lastlogin.c (1de7b4b805ddbf2429da511c053686ac4591ed89) lastlogin.c (427b88d77eb888fad96ba984ca413a89f30252d7)
1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 1996 John M. Vinopal
1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 1996 John M. Vinopal
5 * Copyright (c) 2018 Philip Paeps
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright

--- 28 unchanged lines hidden (view full) ---

41#include <err.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <time.h>
46#include <unistd.h>
47#include <utmpx.h>
48
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright

--- 28 unchanged lines hidden (view full) ---

42#include <err.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <time.h>
47#include <unistd.h>
48#include <utmpx.h>
49
50#include <libxo/xo.h>
51
49 int main(int, char **);
50static void output(struct utmpx *);
51static void usage(void);
52static int utcmp_user(const void *, const void *);
53
54static int order = 1;
55static const char *file = NULL;
56static int (*utcmp)(const void *, const void *) = utcmp_user;

--- 17 unchanged lines hidden (view full) ---

74}
75
76int
77main(int argc, char *argv[])
78{
79 int ch, i, ulistsize;
80 struct utmpx *u, *ulist;
81
52 int main(int, char **);
53static void output(struct utmpx *);
54static void usage(void);
55static int utcmp_user(const void *, const void *);
56
57static int order = 1;
58static const char *file = NULL;
59static int (*utcmp)(const void *, const void *) = utcmp_user;

--- 17 unchanged lines hidden (view full) ---

77}
78
79int
80main(int argc, char *argv[])
81{
82 int ch, i, ulistsize;
83 struct utmpx *u, *ulist;
84
85 argc = xo_parse_args(argc, argv);
86 if (argc < 0)
87 exit(1);
88
82 while ((ch = getopt(argc, argv, "f:rt")) != -1) {
83 switch (ch) {
84 case 'f':
85 file = optarg;
86 break;
87 case 'r':
88 order = -1;
89 break;
90 case 't':
91 utcmp = utcmp_time;
92 break;
93 default:
94 usage();
95 }
96 }
97 argc -= optind;
98 argv += optind;
99
89 while ((ch = getopt(argc, argv, "f:rt")) != -1) {
90 switch (ch) {
91 case 'f':
92 file = optarg;
93 break;
94 case 'r':
95 order = -1;
96 break;
97 case 't':
98 utcmp = utcmp_time;
99 break;
100 default:
101 usage();
102 }
103 }
104 argc -= optind;
105 argv += optind;
106
107 xo_open_container("lastlogin-information");
108 xo_open_list("lastlogin");
109
100 if (argc > 0) {
101 /* Process usernames given on the command line. */
102 for (i = 0; i < argc; i++) {
103 if (setutxdb(UTXDB_LASTLOGIN, file) != 0)
110 if (argc > 0) {
111 /* Process usernames given on the command line. */
112 for (i = 0; i < argc; i++) {
113 if (setutxdb(UTXDB_LASTLOGIN, file) != 0)
104 err(1, "failed to open lastlog database");
114 xo_err(1, "failed to open lastlog database");
105 if ((u = getutxuser(argv[i])) == NULL) {
115 if ((u = getutxuser(argv[i])) == NULL) {
106 warnx("user '%s' not found", argv[i]);
116 xo_warnx("user '%s' not found", argv[i]);
107 continue;
108 }
109 output(u);
110 endutxent();
111 }
112 } else {
113 /* Read all lastlog entries, looking for active ones. */
114 if (setutxdb(UTXDB_LASTLOGIN, file) != 0)
117 continue;
118 }
119 output(u);
120 endutxent();
121 }
122 } else {
123 /* Read all lastlog entries, looking for active ones. */
124 if (setutxdb(UTXDB_LASTLOGIN, file) != 0)
115 err(1, "failed to open lastlog database");
125 xo_err(1, "failed to open lastlog database");
116 ulist = NULL;
117 ulistsize = 0;
118 while ((u = getutxent()) != NULL) {
119 if (u->ut_type != USER_PROCESS)
120 continue;
121 if ((ulistsize % 16) == 0) {
122 ulist = realloc(ulist,
123 (ulistsize + 16) * sizeof(struct utmpx));
124 if (ulist == NULL)
126 ulist = NULL;
127 ulistsize = 0;
128 while ((u = getutxent()) != NULL) {
129 if (u->ut_type != USER_PROCESS)
130 continue;
131 if ((ulistsize % 16) == 0) {
132 ulist = realloc(ulist,
133 (ulistsize + 16) * sizeof(struct utmpx));
134 if (ulist == NULL)
125 err(1, "malloc");
135 xo_err(1, "malloc");
126 }
127 ulist[ulistsize++] = *u;
128 }
129 endutxent();
130
131 qsort(ulist, ulistsize, sizeof(struct utmpx), utcmp);
132 for (i = 0; i < ulistsize; i++)
133 output(&ulist[i]);
134 }
135
136 }
137 ulist[ulistsize++] = *u;
138 }
139 endutxent();
140
141 qsort(ulist, ulistsize, sizeof(struct utmpx), utcmp);
142 for (i = 0; i < ulistsize; i++)
143 output(&ulist[i]);
144 }
145
146 xo_close_list("lastlogin");
147 xo_close_container("lastlogin-information");
148 xo_finish();
149
136 exit(0);
137}
138
139/* Duplicate the output of last(1) */
140static void
141output(struct utmpx *u)
142{
143 time_t t = u->ut_tv.tv_sec;
144
150 exit(0);
151}
152
153/* Duplicate the output of last(1) */
154static void
155output(struct utmpx *u)
156{
157 time_t t = u->ut_tv.tv_sec;
158
145 printf("%-10s %-8s %-22.22s %s",
146 u->ut_user, u->ut_line, u->ut_host, ctime(&t));
159 xo_open_instance("lastlogin");
160 xo_emit("{:user/%-10s/%s} {:tty/%-8s/%s} {:from/%-22.22s/%s}",
161 u->ut_user, u->ut_line, u->ut_host);
162 xo_attr("seconds", "%lu", (unsigned long)t);
163 xo_emit(" {:login-time/%.24s/%.24s}\n", ctime(&t));
164 xo_close_instance("lastlogin");
147}
148
149static void
150usage(void)
151{
165}
166
167static void
168usage(void)
169{
152 fprintf(stderr, "usage: lastlogin [-f file] [-rt] [user ...]\n");
170 xo_error("usage: lastlogin [-f file] [-rt] [user ...]\n");
171 xo_finish();
153 exit(1);
154}
172 exit(1);
173}