Print this page
2989 Eliminate use of LOGNAME_MAX in ON
1166 useradd have warning with name more 8 chars
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/who/who.c
+++ new/usr/src/cmd/who/who.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 22 /* All Rights Reserved */
23 23
24 24
25 25 /*
26 + * Copyright (c) 2013 Gary Mills
27 + *
26 28 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 29 * Use is subject to license terms.
28 30 */
29 31
30 -#pragma ident "%Z%%M% %I% %E% SMI"
31 -
32 32 /*
33 33 * This program analyzes information found in /var/adm/utmpx
34 34 *
35 35 * Additionally information is gathered from /etc/inittab
36 36 * if requested.
37 37 *
38 38 *
39 39 * Syntax:
40 40 *
41 41 * who am i Displays info on yourself
42 42 *
43 43 * who -a Displays information about All
44 44 * entries in /var/adm/utmpx
45 45 *
46 46 * who -b Displays info on last boot
47 47 *
48 48 * who -d Displays info on DEAD PROCESSES
49 49 *
50 50 * who -H Displays HEADERS for output
51 51 *
52 52 * who -l Displays info on LOGIN entries
53 53 *
54 54 * who -m Same as who am i
55 55 *
56 56 * who -p Displays info on PROCESSES spawned by init
57 57 *
58 58 * who -q Displays short information on
59 59 * current users who LOGGED ON
60 60 *
61 61 * who -r Displays info of current run-level
62 62 *
63 63 * who -s Displays requested info in SHORT form
64 64 *
65 65 * who -t Displays info on TIME changes
66 66 *
67 67 * who -T Displays writeability of each user
68 68 * (+ writeable, - non-writeable, ? hung)
69 69 *
70 70 * who -u Displays LONG info on users
71 71 * who have LOGGED ON
72 72 */
73 73
74 74 #define DATE_FMT "%b %e %H:%M"
75 75
76 76 /*
77 77 * %b Abbreviated month name
78 78 * %e Day of month
79 79 * %H hour (24-hour clock)
80 80 * %M minute
81 81 */
82 82 #include <errno.h>
83 83 #include <fcntl.h>
84 84 #include <stdio.h>
85 85 #include <string.h>
86 86 #include <sys/types.h>
87 87 #include <unistd.h>
88 88 #include <stdlib.h>
89 89 #include <sys/stat.h>
90 90 #include <time.h>
91 91 #include <utmpx.h>
92 92 #include <locale.h>
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
93 93 #include <pwd.h>
94 94 #include <limits.h>
95 95
96 96 static void process(void);
97 97 static void ck_file(char *);
98 98 static void dump(void);
99 99
100 100 static struct utmpx *utmpp; /* pointer for getutxent() */
101 101
102 102 /*
103 - * utmpx defines wider fields for user and line. For compatibility of output,
104 - * we are limiting these to the old maximums in utmp. Define UTMPX_NAMELEN
105 - * to use the full lengths.
103 + * Use the full lengths from utmpx for user and line.
106 104 */
107 -#ifndef UTMPX_NAMELEN
108 -/* XXX - utmp - fix name length */
109 -#define NMAX (_POSIX_LOGIN_NAME_MAX - 1)
110 -#define LMAX 12
111 -#else /* UTMPX_NAMELEN */
112 105 #define NMAX (sizeof (utmpp->ut_user))
113 106 #define LMAX (sizeof (utmpp->ut_line))
114 -#endif
115 107
108 +/* Print minimum field widths. */
109 +#define LOGIN_WIDTH 8
110 +#define LINE_WIDTH 12
111 +
116 112 static char comment[BUFSIZ]; /* holds inittab comment */
117 113 static char errmsg[BUFSIZ]; /* used in snprintf for errors */
118 114 static int fildes; /* file descriptor for inittab */
119 115 static int Hopt = 0; /* 1 = who -H */
120 116 static char *inittab; /* ptr to inittab contents */
121 117 static char *iinit; /* index into inittab */
122 118 static int justme = 0; /* 1 = who am i */
123 119 static struct tm *lptr; /* holds user login time */
124 120 static char *myname; /* pointer to invoker's name */
125 121 static char *mytty; /* holds device user is on */
126 122 static char nameval[sizeof (utmpp->ut_user) + 1]; /* invoker's name */
127 123 static int number = 8; /* number of users per -q line */
128 124 static int optcnt = 0; /* keeps count of options */
129 125 static char outbuf[BUFSIZ]; /* buffer for output */
130 126 static char *program; /* holds name of this program */
131 127 #ifdef XPG4
132 128 static int aopt = 0; /* 1 = who -a */
133 129 static int dopt = 0; /* 1 = who -d */
134 130 #endif /* XPG4 */
135 131 static int qopt = 0; /* 1 = who -q */
136 132 static int sopt = 0; /* 1 = who -s */
137 133 static struct stat stbuf; /* area for stat buffer */
138 134 static struct stat *stbufp; /* ptr to structure */
139 135 static int terse = 1; /* 1 = print terse msgs */
140 136 static int Topt = 0; /* 1 = who -T */
141 137 static time_t timnow; /* holds current time */
142 138 static int totlusrs = 0; /* cntr for users on system */
143 139 static int uopt = 0; /* 1 = who -u */
144 140 static char user[sizeof (utmpp->ut_user) + 1]; /* holds user name */
145 141 static int validtype[UTMAXTYPE+1]; /* holds valid types */
146 142 static int wrap; /* flag to indicate wrap */
147 143 static char time_buf[128]; /* holds date and time string */
148 144 static char *end; /* used in strtol for end pointer */
149 145
150 146 int
151 147 main(int argc, char **argv)
152 148 {
153 149 int goerr = 0; /* non-zero indicates cmd error */
154 150 int i;
155 151 int optsw; /* switch for while of getopt() */
156 152
157 153 (void) setlocale(LC_ALL, "");
158 154
159 155 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
160 156 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
161 157 #endif
162 158 (void) textdomain(TEXT_DOMAIN);
163 159
164 160 validtype[USER_PROCESS] = 1;
165 161 validtype[EMPTY] = 0;
166 162 stbufp = &stbuf;
167 163
168 164 /*
169 165 * Strip off path name of this command
170 166 */
171 - for (i = strlen(argv[0]); i >= 0 && argv[0][i] != '/'; --i);
167 + for (i = strlen(argv[0]); i >= 0 && argv[0][i] != '/'; --i)
168 + ;
172 169 if (i >= 0)
173 170 argv[0] += i+1;
174 171 program = argv[0];
175 172
176 173 /*
177 174 * Buffer stdout for speed
178 175 */
179 176 setbuf(stdout, outbuf);
180 177
181 178 /*
182 179 * Retrieve options specified on command line
183 180 * XCU4 - add -m option
184 181 */
185 182 while ((optsw = getopt(argc, argv, "abdHlmn:pqrstTu")) != EOF) {
186 183 optcnt++;
187 184 switch (optsw) {
188 185
189 186 case 'a':
190 187 optcnt += 7;
191 188 validtype[BOOT_TIME] = 1;
192 189 validtype[DEAD_PROCESS] = 1;
193 190 validtype[LOGIN_PROCESS] = 1;
194 191 validtype[INIT_PROCESS] = 1;
195 192 validtype[RUN_LVL] = 1;
196 193 validtype[OLD_TIME] = 1;
197 194 validtype[NEW_TIME] = 1;
198 195 validtype[USER_PROCESS] = 1;
199 196 #ifdef XPG4
200 197 aopt = 1;
201 198 #endif /* XPG4 */
202 199 uopt = 1;
203 200 Topt = 1;
204 201 if (!sopt) terse = 0;
205 202 break;
206 203
207 204 case 'b':
208 205 validtype[BOOT_TIME] = 1;
209 206 if (!uopt) validtype[USER_PROCESS] = 0;
210 207 break;
211 208
212 209 case 'd':
213 210 validtype[DEAD_PROCESS] = 1;
214 211 if (!uopt) validtype[USER_PROCESS] = 0;
215 212 #ifdef XPG4
216 213 dopt = 1;
217 214 #endif /* XPG4 */
218 215 break;
219 216
220 217 case 'H':
221 218 optcnt--; /* Don't count Header */
222 219 Hopt = 1;
223 220 break;
224 221
225 222 case 'l':
226 223 validtype[LOGIN_PROCESS] = 1;
227 224 if (!uopt) validtype[USER_PROCESS] = 0;
228 225 terse = 0;
229 226 break;
230 227 case 'm': /* New XCU4 option */
231 228 justme = 1;
232 229 break;
233 230
234 231 case 'n':
235 232 errno = 0;
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
236 233 number = strtol(optarg, &end, 10);
237 234 if (errno != 0 || *end != '\0') {
238 235 (void) fprintf(stderr, gettext(
239 236 "%s: Invalid numeric argument\n"),
240 237 program);
241 238 exit(1);
242 239 }
243 240 if (number < 1) {
244 241 (void) fprintf(stderr, gettext(
245 242 "%s: Number of users per line must "
246 - "be at least 1\n"), program);
243 + "be at least 1\n"), program);
247 244 exit(1);
248 245 }
249 246 break;
250 247
251 248 case 'p':
252 249 validtype[INIT_PROCESS] = 1;
253 250 if (!uopt) validtype[USER_PROCESS] = 0;
254 251 break;
255 252
256 253 case 'q':
257 254 qopt = 1;
258 255 break;
259 256
260 257 case 'r':
261 258 validtype[RUN_LVL] = 1;
262 259 terse = 0;
263 260 if (!uopt) validtype[USER_PROCESS] = 0;
264 261 break;
265 262
266 263 case 's':
267 264 sopt = 1;
268 265 terse = 1;
269 266 break;
270 267
271 268 case 't':
272 269 validtype[OLD_TIME] = 1;
273 270 validtype[NEW_TIME] = 1;
274 271 if (!uopt) validtype[USER_PROCESS] = 0;
275 272 break;
276 273
277 274 case 'T':
278 275 Topt = 1;
279 276 #ifdef XPG4
280 277 terse = 1; /* XPG4 requires -T */
281 278 #else /* XPG4 */
282 279 terse = 0;
283 280 #endif /* XPG4 */
284 281 break;
285 282
286 283 case 'u':
287 284 uopt = 1;
288 285 validtype[USER_PROCESS] = 1;
289 286 if (!sopt) terse = 0;
290 287 break;
291 288
292 289 case '?':
293 290 goerr++;
294 291 break;
295 292 default:
296 293 break;
297 294 }
298 295 }
299 296 #ifdef XPG4
300 297 /*
301 298 * XCU4 changes - check for illegal sopt, Topt & aopt combination
302 299 */
303 300 if (sopt == 1) {
304 301 terse = 1;
305 302 if (Topt == 1 || aopt == 1)
306 303 goerr++;
307 304 }
308 305 #endif /* XPG4 */
309 306
310 307 if (goerr > 0) {
311 308 #ifdef XPG4
312 309 /*
313 310 * XCU4 - slightly different usage with -s -a & -T
314 311 */
315 312 (void) fprintf(stderr, gettext("\nUsage:\t%s"), program);
316 313 (void) fprintf(stderr,
317 314 gettext(" -s [-bdHlmpqrtu] [utmpx_like_file]\n"));
318 315
319 316 (void) fprintf(stderr, gettext(
320 317 "\t%s [-abdHlmpqrtTu] [utmpx_like_file]\n"), program);
321 318 #else /* XPG4 */
322 319 (void) fprintf(stderr, gettext(
323 320 "\nUsage:\t%s [-abdHlmpqrstTu] [utmpx_like_file]\n"),
324 321 program);
325 322 #endif /* XPG4 */
326 323 (void) fprintf(stderr,
327 324 gettext("\t%s -q [-n x] [utmpx_like_file]\n"), program);
328 325 (void) fprintf(stderr, gettext("\t%s [am i]\n"), program);
329 326 /*
330 327 * XCU4 changes - be explicit with "am i" options
331 328 */
332 329 (void) fprintf(stderr, gettext("\t%s [am I]\n"), program);
333 330 (void) fprintf(stderr, gettext(
334 331 "a\tall (bdlprtu options)\n"));
335 332 (void) fprintf(stderr, gettext("b\tboot time\n"));
336 333 (void) fprintf(stderr, gettext("d\tdead processes\n"));
337 334 (void) fprintf(stderr, gettext("H\tprint header\n"));
338 335 (void) fprintf(stderr, gettext("l\tlogin processes\n"));
339 336 (void) fprintf(stderr, gettext(
340 337 "n #\tspecify number of users per line for -q\n"));
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
341 338 (void) fprintf(stderr,
342 339 gettext("p\tprocesses other than getty or users\n"));
343 340 (void) fprintf(stderr, gettext("q\tquick %s\n"), program);
344 341 (void) fprintf(stderr, gettext("r\trun level\n"));
345 342 (void) fprintf(stderr, gettext(
346 343 "s\tshort form of %s (no time since last output or pid)\n"),
347 344 program);
348 345 (void) fprintf(stderr, gettext("t\ttime changes\n"));
349 346 (void) fprintf(stderr, gettext(
350 347 "T\tstatus of tty (+ writable, - not writable, "
351 - "? hung)\n"));
348 + "? hung)\n"));
352 349 (void) fprintf(stderr, gettext("u\tuseful information\n"));
353 350 (void) fprintf(stderr,
354 351 gettext("m\tinformation only about current terminal\n"));
355 352 (void) fprintf(stderr, gettext(
356 353 "am i\tinformation about current terminal "
357 - "(same as -m)\n"));
354 + "(same as -m)\n"));
358 355 (void) fprintf(stderr, gettext(
359 356 "am I\tinformation about current terminal "
360 - "(same as -m)\n"));
357 + "(same as -m)\n"));
361 358 exit(1);
362 359 }
363 360
364 361 /*
365 362 * XCU4: If -q option ignore all other options
366 363 */
367 364 if (qopt == 1) {
368 365 Hopt = 0;
369 366 sopt = 0;
370 367 Topt = 0;
371 368 uopt = 0;
372 369 justme = 0;
373 370 validtype[ACCOUNTING] = 0;
374 371 validtype[BOOT_TIME] = 0;
375 372 validtype[DEAD_PROCESS] = 0;
376 373 validtype[LOGIN_PROCESS] = 0;
377 374 validtype[INIT_PROCESS] = 0;
378 375 validtype[RUN_LVL] = 0;
379 376 validtype[OLD_TIME] = 0;
380 377 validtype[NEW_TIME] = 0;
381 378 validtype[USER_PROCESS] = 1;
382 379 }
383 380
384 381 if (argc == optind + 1) {
385 382 optcnt++;
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
386 383 ck_file(argv[optind]);
387 384 (void) utmpxname(argv[optind]);
388 385 }
389 386
390 387 /*
391 388 * Test for 'who am i' or 'who am I'
392 389 * XCU4 - check if justme was already set by -m option
393 390 */
394 391 if (justme == 1 || (argc == 3 && strcmp(argv[1], "am") == 0 &&
395 392 ((argv[2][0] == 'i' || argv[2][0] == 'I') &&
396 - argv[2][1] == '\0'))) {
393 + argv[2][1] == '\0'))) {
397 394 justme = 1;
398 395 myname = nameval;
399 396 (void) cuserid(myname);
400 397 if ((mytty = ttyname(fileno(stdin))) == NULL &&
401 398 (mytty = ttyname(fileno(stdout))) == NULL &&
402 399 (mytty = ttyname(fileno(stderr))) == NULL) {
403 400 (void) fprintf(stderr, gettext(
404 401 "Must be attached to terminal for 'am I' option\n"));
405 402 (void) fflush(stderr);
406 403 exit(1);
407 404 } else
408 405 mytty += 5; /* bump past "/dev/" */
409 406 }
410 407
411 408 if (!terse) {
412 409 if (Hopt)
413 410 (void) printf(gettext(
414 411 "NAME LINE TIME IDLE PID COMMENTS\n"));
415 412
416 413 timnow = time(0);
417 414
418 415 if ((fildes = open("/etc/inittab",
419 416 O_NONBLOCK|O_RDONLY)) == -1) {
420 417 (void) snprintf(errmsg, sizeof (errmsg),
421 418 gettext("%s: Cannot open /etc/inittab"), program);
422 419 perror(errmsg);
423 420 exit(errno);
424 421 }
425 422
426 423 if (fstat(fildes, stbufp) == -1) {
427 424 (void) snprintf(errmsg, sizeof (errmsg),
428 425 gettext("%s: Cannot stat /etc/inittab"), program);
429 426 perror(errmsg);
430 427 exit(errno);
431 428 }
432 429
433 430 if ((inittab = malloc(stbufp->st_size + 1)) == NULL) {
434 431 (void) snprintf(errmsg, sizeof (errmsg),
435 432 gettext("%s: Cannot allocate %ld bytes"),
436 433 program, stbufp->st_size);
437 434 perror(errmsg);
438 435 exit(errno);
439 436 }
440 437
441 438 if (read(fildes, inittab, stbufp->st_size)
442 439 != stbufp->st_size) {
443 440 (void) snprintf(errmsg, sizeof (errmsg),
444 441 gettext("%s: Error reading /etc/inittab"),
445 442 program);
446 443 perror(errmsg);
447 444 exit(errno);
448 445 }
449 446
450 447 inittab[stbufp->st_size] = '\0';
451 448 iinit = inittab;
452 449 } else {
453 450 if (Hopt) {
454 451 #ifdef XPG4
455 452 if (dopt) {
456 453 (void) printf(gettext(
457 454 "NAME LINE TIME COMMENTS\n"));
458 455 } else {
459 456 (void) printf(
460 457 gettext("NAME LINE TIME\n"));
461 458 }
462 459 #else /* XPG4 */
463 460 (void) printf(
464 461 gettext("NAME LINE TIME\n"));
465 462 #endif /* XPG4 */
466 463 }
467 464 }
468 465 process();
469 466
470 467 /*
471 468 * 'who -q' requires EOL upon exit,
472 469 * followed by total line
473 470 */
474 471 if (qopt)
475 472 (void) printf(gettext("\n# users=%d\n"), totlusrs);
476 473 return (0);
477 474 }
478 475
479 476 static void
480 477 dump()
481 478 {
482 479 char device[sizeof (utmpp->ut_line) + 1];
483 480 time_t hr;
484 481 time_t idle;
485 482 time_t min;
486 483 char path[sizeof (utmpp->ut_line) + 6];
487 484 int pexit;
488 485 int pterm;
489 486 int rc;
490 487 char w; /* writeability indicator */
491 488
492 489 /*
493 490 * Get and check user name
494 491 */
495 492 if (utmpp->ut_user[0] == '\0')
496 493 (void) strcpy(user, " .");
497 494 else {
498 495 (void) strncpy(user, utmpp->ut_user, sizeof (user));
499 496 user[sizeof (user) - 1] = '\0';
500 497 }
501 498 totlusrs++;
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
502 499
503 500 /*
504 501 * Do print in 'who -q' format
505 502 */
506 503 if (qopt) {
507 504 /*
508 505 * XCU4 - Use non user macro for correct user count
509 506 */
510 507 if (((totlusrs - 1) % number) == 0 && totlusrs > 1)
511 508 (void) printf("\n");
512 - (void) printf("%-*s ", NMAX, user);
509 + (void) printf("%-*.*s ", LOGIN_WIDTH, NMAX, user);
513 510 return;
514 511 }
515 512
516 513
517 514 pexit = (int)' ';
518 515 pterm = (int)' ';
519 516
520 517 /*
521 518 * Get exit info if applicable
522 519 */
523 520 if (utmpp->ut_type == RUN_LVL || utmpp->ut_type == DEAD_PROCESS) {
524 521 pterm = utmpp->ut_exit.e_termination;
525 522 pexit = utmpp->ut_exit.e_exit;
526 523 }
527 524
528 525 /*
529 526 * Massage ut_xtime field
530 527 */
531 528 lptr = localtime(&utmpp->ut_xtime);
532 529 (void) strftime(time_buf, sizeof (time_buf),
533 530 dcgettext(NULL, DATE_FMT, LC_TIME), lptr);
534 531
535 532 /*
536 533 * Get and massage device
537 534 */
538 535 if (utmpp->ut_line[0] == '\0')
539 536 (void) strcpy(device, " .");
540 537 else {
541 538 (void) strncpy(device, utmpp->ut_line,
542 539 sizeof (utmpp->ut_line));
543 540 device[sizeof (utmpp->ut_line)] = '\0';
544 541 }
545 542
546 543 /*
547 544 * Get writeability if requested
548 545 * XCU4 - only print + or - for user processes
549 546 */
550 547 if (Topt && (utmpp->ut_type == USER_PROCESS)) {
551 548 w = '-';
552 549 (void) strcpy(path, "/dev/");
553 550 (void) strncpy(path + 5, utmpp->ut_line,
554 551 sizeof (utmpp->ut_line));
555 552 path[5 + sizeof (utmpp->ut_line)] = '\0';
556 553
557 554 if ((rc = stat(path, stbufp)) == -1) w = '?';
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
558 555 else if ((stbufp->st_mode & S_IWOTH) ||
559 556 (stbufp->st_mode & S_IWGRP)) /* Check group & other */
560 557 w = '+';
561 558
562 559 } else
563 560 w = ' ';
564 561
565 562 /*
566 563 * Print the TERSE portion of the output
567 564 */
568 - (void) printf("%-*s %c %-12s %s", NMAX, user, w, device, time_buf);
565 + (void) printf("%-*.*s %c %-12s %s", LOGIN_WIDTH, NMAX, user,
566 + w, device, time_buf);
569 567
570 568 if (!terse) {
571 569 /*
572 570 * Stat device for idle time
573 571 * (Don't complain if you can't)
574 572 */
575 573 rc = -1;
576 574 if (utmpp->ut_type == USER_PROCESS) {
577 575 (void) strcpy(path, "/dev/");
578 576 (void) strncpy(path + 5, utmpp->ut_line,
579 577 sizeof (utmpp->ut_line));
580 578 path[5 + sizeof (utmpp->ut_line)] = '\0';
581 579 rc = stat(path, stbufp);
582 580 }
583 581 if (rc != -1) {
584 582 idle = timnow - stbufp->st_mtime;
585 583 hr = idle/3600;
586 584 min = (unsigned)(idle/60)%60;
587 585 if (hr == 0 && min == 0)
588 586 (void) printf(gettext(" . "));
589 587 else {
590 588 if (hr < 24)
591 589 (void) printf(" %2d:%2.2d", (int)hr,
592 590 (int)min);
593 591 else
594 592 (void) printf(gettext(" old "));
595 593 }
596 594 }
597 595
598 596 /*
599 597 * Add PID for verbose output
600 598 */
601 599 if (utmpp->ut_type != BOOT_TIME &&
602 600 utmpp->ut_type != RUN_LVL &&
603 601 utmpp->ut_type != ACCOUNTING)
604 602 (void) printf(" %5ld", utmpp->ut_pid);
605 603
606 604 /*
607 605 * Handle /etc/inittab comment
608 606 */
609 607 if (utmpp->ut_type == DEAD_PROCESS) {
610 608 (void) printf(gettext(" id=%4.4s "),
611 609 utmpp->ut_id);
612 610 (void) printf(gettext("term=%-3d "), pterm);
613 611 (void) printf(gettext("exit=%d "), pexit);
614 612 } else if (utmpp->ut_type != INIT_PROCESS) {
615 613 /*
616 614 * Search for each entry in inittab
617 615 * string. Keep our place from
618 616 * search to search to try and
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
619 617 * minimize the work. Wrap once if needed
620 618 * for each entry.
621 619 */
622 620 wrap = 0;
623 621 /*
624 622 * Look for a line beginning with
625 623 * utmpp->ut_id
626 624 */
627 625 while ((rc = strncmp(utmpp->ut_id, iinit,
628 626 strcspn(iinit, ":"))) != 0) {
629 - for (; *iinit != '\n'; iinit++);
627 + for (; *iinit != '\n'; iinit++)
628 + ;
630 629 iinit++;
631 630
632 631 /*
633 632 * Wrap once if necessary to
634 633 * find entry in inittab
635 634 */
636 635 if (*iinit == '\0') {
637 636 if (!wrap) {
638 637 iinit = inittab;
639 638 wrap = 1;
640 639 }
641 640 }
642 641 }
643 642
644 643 if (*iinit != '\0') {
645 644 /*
646 645 * We found our entry
647 646 */
648 647 for (iinit++; *iinit != '#' &&
649 - *iinit != '\n'; iinit++);
648 + *iinit != '\n'; iinit++)
649 + ;
650 650 if (*iinit == '#') {
651 651 for (iinit++; *iinit == ' ' ||
652 - *iinit == '\t'; iinit++);
652 + *iinit == '\t'; iinit++)
653 + ;
653 654 for (rc = 0; *iinit != '\n'; iinit++)
654 655 comment[rc++] = *iinit;
655 656 comment[rc] = '\0';
656 657 } else
657 658 (void) strcpy(comment, " ");
658 659
659 660 (void) printf(" %s", comment);
660 661 } else
661 662 iinit = inittab; /* Reset pointer */
662 663 }
663 664 if (utmpp->ut_type == INIT_PROCESS)
664 665 (void) printf(gettext(" id=%4.4s"), utmpp->ut_id);
665 666 }
666 667 #ifdef XPG4
667 668 else
668 669 if (dopt && utmpp->ut_type == DEAD_PROCESS) {
669 670 (void) printf(gettext("\tterm=%-3d "), pterm);
670 671 (void) printf(gettext("exit=%d "), pexit);
671 672 }
672 673 #endif /* XPG4 */
673 674
674 675
675 676 /*
676 677 * Handle RUN_LVL process - If no alt. file - Only one!
677 678 */
678 679 if (utmpp->ut_type == RUN_LVL) {
679 680 (void) printf(" %c %5ld %c", pterm, utmpp->ut_pid,
680 681 pexit);
681 682 if (optcnt == 1 && !validtype[USER_PROCESS]) {
682 683 (void) printf("\n");
683 684 exit(0);
684 685 }
685 686 }
686 687
687 688 /*
688 689 * Handle BOOT_TIME process - If no alt. file - Only one!
689 690 */
690 691 if (utmpp->ut_type == BOOT_TIME) {
691 692 if (optcnt == 1 && !validtype[USER_PROCESS]) {
692 693 (void) printf("\n");
693 694 exit(0);
694 695 }
695 696 }
696 697
697 698 /*
698 699 * Get remote host from utmpx structure
699 700 */
700 701 if (utmpp && utmpp->ut_host[0])
701 702 (void) printf("\t(%.*s)", sizeof (utmpp->ut_host),
702 703 utmpp->ut_host);
703 704
704 705 /*
705 706 * Now, put on the trailing EOL
706 707 */
707 708 (void) printf("\n");
708 709 }
709 710
710 711 static void
711 712 process()
712 713 {
713 714 struct passwd *pwp;
714 715 int i = 0;
715 716 char *ttname;
716 717
717 718 /*
718 719 * Loop over each entry in /var/adm/utmpx
719 720 */
720 721
721 722 setutxent();
722 723 while ((utmpp = getutxent()) != NULL) {
723 724 #ifdef DEBUG
724 725 (void) printf(
725 726 "ut_user '%s'\nut_id '%s'\nut_line '%s'\nut_type '%d'\n\n",
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
726 727 utmpp->ut_user, utmpp->ut_id, utmpp->ut_line, utmpp->ut_type);
727 728 #endif
728 729 if (utmpp->ut_type <= UTMAXTYPE) {
729 730 /*
730 731 * Handle "am i"
731 732 */
732 733 if (justme) {
733 734 if (strncmp(myname, utmpp->ut_user,
734 735 sizeof (utmpp->ut_user)) == 0 &&
735 736 strncmp(mytty, utmpp->ut_line,
736 - sizeof (utmpp->ut_line)) == 0 &&
737 + sizeof (utmpp->ut_line)) == 0 &&
737 738 utmpp->ut_type == USER_PROCESS) {
738 739 /*
739 740 * we have have found ourselves
740 741 * in the utmp file and the entry
741 742 * is a user process, this is not
742 743 * meaningful otherwise
743 744 *
744 745 */
745 746
746 747 dump();
747 748 exit(0);
748 749 }
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
749 750 continue;
750 751 }
751 752
752 753 /*
753 754 * Print the line if we want it
754 755 */
755 756 if (validtype[utmpp->ut_type]) {
756 757 #ifdef XPG4
757 758 if (utmpp->ut_type == LOGIN_PROCESS) {
758 759 if ((utmpp->ut_line[0] == '\0') ||
759 - (strcmp(utmpp->ut_user, "LOGIN") != 0))
760 + (strcmp(utmpp->ut_user,
761 + "LOGIN") != 0))
760 762 continue;
761 763 }
762 764 #endif /* XPG4 */
763 765 dump();
764 766 }
765 767 } else {
766 768 (void) fprintf(stderr,
767 769 gettext("%s: Error --- entry has ut_type "
768 - "of %d\n"), program, utmpp->ut_type);
770 + "of %d\n"), program, utmpp->ut_type);
769 771 (void) fprintf(stderr,
770 772 gettext(" when maximum is %d\n"), UTMAXTYPE);
771 773 }
772 774 }
773 775
774 776 /*
775 777 * If justme is set at this point than the utmp entry
776 778 * was not found.
777 779 */
778 780 if (justme) {
779 781 static struct utmpx utmpt;
780 782
781 783 pwp = getpwuid(geteuid());
782 784 if (pwp != NULL)
783 785 while (i < (int)sizeof (utmpt.ut_user) &&
784 786 *pwp->pw_name != 0)
785 787 utmpt.ut_user[i++] = *pwp->pw_name++;
786 788
787 789 ttname = ttyname(1);
788 790
789 791 i = 0;
790 792 if (ttname != NULL)
791 793 while (i < (int)sizeof (utmpt.ut_line) &&
792 794 *ttname != 0)
793 795 utmpt.ut_line[i++] = *ttname++;
794 796
795 797 utmpt.ut_id[0] = 0;
796 798 utmpt.ut_pid = getpid();
797 799 utmpt.ut_type = USER_PROCESS;
798 800 (void) time(&utmpt.ut_xtime);
799 801 utmpp = &utmpt;
800 802 dump();
801 803 exit(0);
802 804 }
803 805 }
804 806
805 807 /*
806 808 * This routine checks the following:
807 809 *
808 810 * 1. File exists
809 811 *
810 812 * 2. We have read permissions
811 813 *
812 814 * 3. It is a multiple of utmp entries in size
813 815 *
814 816 * Failing any of these conditions causes who(1) to
815 817 * abort processing.
816 818 *
817 819 * 4. If file is empty we exit right away as there
818 820 * is no info to report on.
819 821 *
820 822 * This routine does not check utmpx files.
821 823 */
822 824 static void
823 825 ck_file(char *name)
824 826 {
825 827 struct stat sbuf;
826 828 int rc;
827 829
828 830 /*
829 831 * Does file exist? Do stat to check, and save structure
830 832 * so that we can check on the file's size later on.
831 833 */
832 834 if ((rc = stat(name, &sbuf)) == -1) {
833 835 (void) snprintf(errmsg, sizeof (errmsg),
834 836 gettext("%s: Cannot stat file '%s'"), program, name);
835 837 perror(errmsg);
836 838 exit(1);
837 839 }
838 840
839 841 /*
840 842 * The only real way we can be sure we can access the
841 843 * file is to try. If we succeed then we close it.
842 844 */
843 845 if (access(name, R_OK) < 0) {
844 846 (void) snprintf(errmsg, sizeof (errmsg),
845 847 gettext("%s: Cannot open file '%s'"), program, name);
846 848 perror(errmsg);
847 849 exit(1);
848 850 }
849 851
850 852 /*
851 853 * If the file is empty, we are all done.
852 854 */
853 855 if (!sbuf.st_size)
854 856 exit(0);
855 857
856 858 /*
857 859 * Make sure the file is a utmp file.
858 860 * We can only check for size being a multiple of
859 861 * utmp structures in length.
860 862 */
861 863 rc = sbuf.st_size % (int)sizeof (struct utmpx);
862 864 if (rc) {
863 865 (void) fprintf(stderr, gettext("%s: File '%s' is not "
864 866 "a utmpx file\n"), program, name);
865 867 exit(1);
866 868 }
867 869 }
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX