kern: Make sure gcc47 - gcc50 don't check for set-not-used
[dragonfly.git] / usr.bin / lastcomm / lastcomm.c
1 /*
2  * Copyright (c) 1980, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#) Copyright (c) 1980, 1993 The Regents of the University of California.  All rights reserved.
30  * @(#)lastcomm.c       8.1 (Berkeley) 6/6/93
31  * $FreeBSD: src/usr.bin/lastcomm/lastcomm.c,v 1.20.2.1 2007/04/18 05:53:50 dds Exp $
32  */
33
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <sys/acct.h>
37
38 #include <ctype.h>
39 #include <err.h>
40 #include <fcntl.h>
41 #include <pwd.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include "pathnames.h"
47
48 time_t   expand(u_int);
49 char    *flagbits(int);
50 const    char *getdev(dev_t);
51 int      requested(char *[], struct acct *);
52 static   void usage(void);
53
54 #define AC_UTIME 1 /* user */
55 #define AC_STIME 2 /* system */
56 #define AC_ETIME 4 /* elapsed */
57 #define AC_CTIME 8 /* user + system time, default */
58
59 #define AC_BTIME 16 /* starting time */
60 #define AC_FTIME 32 /* exit time (starting time + elapsed time )*/
61
62 #define AC_HZ ((double)AHZ)
63
64 int
65 main(int argc, char *argv[])
66 {
67         char *p;
68         struct acct ab;
69         struct stat sb;
70         FILE *fp;
71         off_t size = 0;
72         time_t t;
73         int ch;
74         const char *acctfile;
75         int flags = 0;
76
77         acctfile = _PATH_ACCT;
78         while ((ch = getopt(argc, argv, "f:usecSE")) != -1)
79                 switch((char)ch) {
80                 case 'f':
81                         acctfile = optarg;
82                         break;
83
84                 case 'u': 
85                         flags |= AC_UTIME; /* user time */
86                         break;
87                 case 's':
88                         flags |= AC_STIME; /* system time */
89                         break;
90                 case 'e':
91                         flags |= AC_ETIME; /* elapsed time */
92                         break;
93                 case 'c':
94                         flags |= AC_CTIME; /* user + system time */
95                         break;
96
97                 case 'S':
98                         flags |= AC_BTIME; /* starting time */
99                         break;
100                 case 'E':
101                         /* exit time (starting time + elapsed time )*/
102                         flags |= AC_FTIME; 
103                         break;
104
105                 case '?':
106                 default:
107                         usage();
108                 }
109
110         /* default user + system time and starting time */
111         if (!flags) {
112             flags = AC_CTIME | AC_BTIME;
113         }
114
115         argc -= optind;
116         argv += optind;
117
118         if (strcmp(acctfile, "-") == 0)
119                 fp = stdin;
120         else {
121                 /* Open the file. */
122                 if ((fp = fopen(acctfile, "r")) == NULL ||
123                     fstat(fileno(fp), &sb))
124                         err(1, "could not open %s", acctfile);
125
126                 /*
127                  * Round off to integral number of accounting records,
128                  * probably not necessary, but it doesn't hurt.
129                  */
130                 size = sb.st_size - sb.st_size % sizeof(struct acct);
131
132                 /* Check if any records to display. */
133                 if ((unsigned)size < sizeof(struct acct))
134                         exit(0);
135         }
136
137         do {
138                 int rv;
139
140                 if (fp != stdin) {
141                         size -= sizeof(struct acct);
142                         if (fseeko(fp, size, SEEK_SET) == -1)
143                                 err(1, "seek %s failed", acctfile);
144                 }
145
146                 if ((rv = fread(&ab, sizeof(struct acct), 1, fp)) != 1) {
147                         if (feof(fp))
148                                 break;
149                         else
150                                 err(1, "read %s returned %d", acctfile, rv);
151                 }
152
153                 if (ab.ac_comm[0] == '\0') {
154                         ab.ac_comm[0] = '?';
155                         ab.ac_comm[1] = '\0';
156                 } else
157                         for (p = &ab.ac_comm[0];
158                             p < &ab.ac_comm[AC_COMM_LEN] && *p; ++p)
159                                 if (!isprint(*p))
160                                         *p = '?';
161                 if (*argv && !requested(argv, &ab))
162                         continue;
163
164                 (void)printf("%-*.*s %-7s %-*s %-8s",
165                              AC_COMM_LEN, AC_COMM_LEN, ab.ac_comm,
166                              flagbits(ab.ac_flag),
167                              MAXLOGNAME - 1, user_from_uid(ab.ac_uid, 0),
168                              getdev(ab.ac_tty));
169                 
170                 
171                 /* user + system time */
172                 if (flags & AC_CTIME) {
173                         (void)printf(" %6.2f secs", 
174                                      (expand(ab.ac_utime) + 
175                                       expand(ab.ac_stime))/AC_HZ);
176                 }
177                 
178                 /* usr time */
179                 if (flags & AC_UTIME) {
180                         (void)printf(" %6.2f us", expand(ab.ac_utime)/AC_HZ);
181                 }
182                 
183                 /* system time */
184                 if (flags & AC_STIME) {
185                         (void)printf(" %6.2f sy", expand(ab.ac_stime)/AC_HZ);
186                 }
187                 
188                 /* elapsed time */
189                 if (flags & AC_ETIME) {
190                         (void)printf(" %8.2f es", expand(ab.ac_etime)/AC_HZ);
191                 }
192                 
193                 /* starting time */
194                 if (flags & AC_BTIME) {
195                         (void)printf(" %.16s", ctime(&ab.ac_btime));
196                 }
197                 
198                 /* exit time (starting time + elapsed time )*/
199                 if (flags & AC_FTIME) {
200                         t = ab.ac_btime;
201                         t += (time_t)(expand(ab.ac_etime)/AC_HZ);
202                         (void)printf(" %.16s", ctime(&t));
203                 }
204                 printf("\n");
205
206         } while (size > 0);
207         exit(0);
208 }
209
210 time_t
211 expand(u_int t)
212 {
213         time_t nt;
214
215         nt = t & 017777;
216         t >>= 13;
217         while (t) {
218                 t--;
219                 nt <<= 3;
220         }
221         return (nt);
222 }
223
224 char *
225 flagbits(int f)
226 {
227         static char flags[20] = "-";
228         char *p;
229
230 #define BIT(flag, ch)   if (f & flag) *p++ = ch
231
232         p = flags + 1;
233         BIT(ASU, 'S');
234         BIT(AFORK, 'F');
235         BIT(ACOMPAT, 'C');
236         BIT(ACORE, 'D');
237         BIT(AXSIG, 'X');
238         *p = '\0';
239         return (flags);
240 }
241
242 int
243 requested(char *argv[], struct acct *acp)
244 {
245         const char *p;
246
247         do {
248                 p = user_from_uid(acp->ac_uid, 0);
249                 if (!strcmp(p, *argv))
250                         return (1);
251                 if ((p = getdev(acp->ac_tty)) && !strcmp(p, *argv))
252                         return (1);
253                 if (!strncmp(acp->ac_comm, *argv, AC_COMM_LEN))
254                         return (1);
255         } while (*++argv);
256         return (0);
257 }
258
259 const char *
260 getdev(dev_t dev)
261 {
262         static dev_t lastdev = (dev_t)-1;
263         static const char *lastname;
264
265         if (dev == NODEV)                       /* Special case. */
266                 return ("__");
267         if (dev == lastdev)                     /* One-element cache. */
268                 return (lastname);
269         lastdev = dev;
270         lastname = devname(dev, S_IFCHR);
271         return (lastname);
272 }
273
274 static void
275 usage(void)
276 {
277         (void)fprintf(stderr,
278 "usage: lastcomm [-EScesu] [-f file] [command ...] [user ...] [terminal ...]\n");
279         exit(1);
280 }