1 /* $NetBSD: who.c,v 1.10 2002/08/01 23:23:09 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Michael Fischbein. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 __COPYRIGHT( 42 "@(#) Copyright (c) 1989, 1993\n\ 43 The Regents of the University of California. All rights reserved.\n"); 44 #endif /* not lint */ 45 46 #ifndef lint 47 #if 0 48 static char sccsid[] = "@(#)who.c 8.1 (Berkeley) 6/6/93"; 49 #endif 50 __RCSID("$NetBSD: who.c,v 1.10 2002/08/01 23:23:09 christos Exp $"); 51 #endif /* not lint */ 52 53 #include <sys/types.h> 54 #include <sys/stat.h> 55 #include <err.h> 56 #include <locale.h> 57 #include <pwd.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <string.h> 61 #include <time.h> 62 #include <unistd.h> 63 #include "utmpentry.h" 64 65 static void output_labels(void); 66 static void who_am_i(const char *, int); 67 static void usage(void); 68 static void process(const char *, int); 69 static void print(const char *, const char *, time_t, const char *); 70 71 int main(int, char **); 72 73 static int show_term; /* show term state */ 74 static int show_idle; /* show idle time */ 75 76 static int maxname = 8, maxline = 8, maxhost = 16; 77 78 int 79 main(int argc, char **argv) 80 { 81 int c, only_current_term, show_labels; 82 83 setlocale(LC_ALL, ""); 84 85 only_current_term = show_term = show_idle = show_labels = 0; 86 while ((c = getopt(argc, argv, "mTuH")) != -1) { 87 switch (c) { 88 case 'm': 89 only_current_term = 1; 90 break; 91 case 'T': 92 show_term = 1; 93 break; 94 case 'u': 95 show_idle = 1; 96 break; 97 case 'H': 98 show_labels = 1; 99 break; 100 default: 101 usage(); 102 /* NOTREACHED */ 103 } 104 } 105 argc -= optind; 106 argv += optind; 107 108 if (chdir("/dev")) { 109 err(1, "cannot change directory to /dev"); 110 /* NOTREACHED */ 111 } 112 113 switch (argc) { 114 case 0: /* who */ 115 if (only_current_term) { 116 who_am_i(NULL, show_labels); 117 } else { 118 process(NULL, show_labels); 119 } 120 break; 121 case 1: /* who utmp_file */ 122 if (only_current_term) { 123 who_am_i(*argv, show_labels); 124 } else { 125 process(*argv, show_labels); 126 } 127 break; 128 case 2: /* who am i */ 129 who_am_i(NULL, show_labels); 130 break; 131 default: 132 usage(); 133 /* NOTREACHED */ 134 } 135 exit(0); 136 } 137 138 static void 139 who_am_i(const char *fname, int show_labels) 140 { 141 struct passwd *pw; 142 char *p; 143 char *t; 144 time_t now; 145 struct utmpentry *ehead, *ep; 146 147 /* search through the utmp and find an entry for this tty */ 148 if ((p = ttyname(STDIN_FILENO)) != NULL) { 149 150 /* strip any directory component */ 151 if ((t = strrchr(p, '/')) != NULL) 152 p = t + 1; 153 154 (void)getutentries(fname, &ehead); 155 for (ep = ehead; ep; ep = ep->next) 156 if (strcmp(ep->line, p) == 0) { 157 if (show_labels) 158 output_labels(); 159 print(ep->name, ep->line, (time_t)ep->tv.tv_sec, 160 ep->host); 161 return; 162 } 163 } else 164 p = "tty??"; 165 166 (void)time(&now); 167 pw = getpwuid(getuid()); 168 if (show_labels) 169 output_labels(); 170 print(pw ? pw->pw_name : "?", p, now, ""); 171 } 172 173 static void 174 process(const char *fname, int show_labels) 175 { 176 struct utmpentry *ehead, *ep; 177 (void)getutentries(fname, &ehead); 178 if (show_labels) 179 output_labels(); 180 for (ep = ehead; ep != NULL; ep = ep->next) 181 print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host); 182 } 183 184 static void 185 print(const char *name, const char *line, time_t t, const char *host) 186 { 187 struct stat sb; 188 char state; 189 static time_t now = 0; 190 time_t idle; 191 192 state = '?'; 193 idle = 0; 194 195 if (show_term || show_idle) { 196 if (now == 0) 197 time(&now); 198 199 if (stat(line, &sb) == 0) { 200 state = (sb.st_mode & 020) ? '+' : '-'; 201 idle = now - sb.st_atime; 202 } 203 204 } 205 206 (void)printf("%-*.*s ", maxname, maxname, name); 207 208 if (show_term) { 209 (void)printf("%c ", state); 210 } 211 212 (void)printf("%-*.*s ", maxline, maxline, line); 213 (void)printf("%.12s ", ctime(&t) + 4); 214 215 if (show_idle) { 216 if (idle < 60) 217 (void)printf(" . "); 218 else if (idle < (24 * 60 * 60)) 219 (void)printf("%02ld:%02ld ", 220 (long)(idle / (60 * 60)), 221 (long)(idle % (60 * 60)) / 60); 222 else 223 (void)printf(" old "); 224 } 225 226 if (*host) 227 printf("\t(%.*s)", maxhost, host); 228 (void)putchar('\n'); 229 } 230 231 static void 232 output_labels() 233 { 234 (void)printf("%-*.*s ", maxname, maxname, "USER"); 235 236 if (show_term) 237 (void)printf("S "); 238 239 (void)printf("%-*.*s ", maxline, maxline, "LINE"); 240 (void)printf("WHEN "); 241 242 if (show_idle) 243 (void)printf("IDLE "); 244 245 (void)printf("\t%.*s", maxhost, "FROM"); 246 247 (void)putchar('\n'); 248 } 249 250 static void 251 usage() 252 { 253 (void)fprintf(stderr, "Usage: %s [-mTuH] [ file ]\n %s am i\n", 254 getprogname(), getprogname()); 255 exit(1); 256 } 257