Print this page
2849 uptime should use locale settings for current time
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/w/w.c
+++ new/usr/src/cmd/w/w.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
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 /*
22 22 * Copyright (c) 2013 Gary Mills
23 23 *
24 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 25 * Use is subject to license terms.
26 26 */
27 27
28 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 29 /* All Rights Reserved */
30 30
31 31 /*
32 32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 33 * The Regents of the University of California
34 34 * All Rights Reserved
35 35 *
36 36 * University Acknowledgment- Portions of this document are derived from
37 37 * software developed by the University of California, Berkeley, and its
38 38 * contributors.
39 39 */
40 40
41 41 /*
42 42 * This is the new w command which takes advantage of
43 43 * the /proc interface to gain access to the information
44 44 * of all the processes currently on the system.
45 45 *
46 46 * This program also implements 'uptime'.
47 47 *
48 48 * Maintenance note:
49 49 *
50 50 * Much of this code is replicated in whodo.c. If you're
51 51 * fixing bugs here, then you should probably fix 'em there too.
52 52 */
53 53
54 54 #include <stdio.h>
55 55 #include <string.h>
56 56 #include <stdarg.h>
57 57 #include <stdlib.h>
58 58 #include <ctype.h>
59 59 #include <fcntl.h>
60 60 #include <time.h>
61 61 #include <errno.h>
62 62 #include <sys/types.h>
63 63 #include <utmpx.h>
64 64 #include <sys/stat.h>
65 65 #include <dirent.h>
66 66 #include <procfs.h> /* /proc header file */
67 67 #include <locale.h>
68 68 #include <unistd.h>
69 69 #include <sys/loadavg.h>
70 70 #include <limits.h>
71 71 #include <priv_utils.h>
72 72
73 73 /*
74 74 * Use the full lengths from utmpx for user and line.
75 75 */
76 76 static struct utmpx dummy;
77 77 #define NMAX (sizeof (dummy.ut_user))
78 78 #define LMAX (sizeof (dummy.ut_line))
79 79
80 80 /* Print minimum field widths. */
81 81 #define LOGIN_WIDTH 8
82 82 #define LINE_WIDTH 12
83 83
84 84 #define DIV60(t) ((t+30)/60) /* x/60 rounded */
85 85
86 86 #ifdef ERR
87 87 #undef ERR
88 88 #endif
89 89 #define ERR (-1)
90 90
91 91 #define HSIZE 256 /* size of process hash table */
92 92 #define PROCDIR "/proc"
93 93 #define INITPROCESS (pid_t)1 /* init process pid */
94 94 #define NONE 'n' /* no state */
95 95 #define RUNNING 'r' /* runnable process */
96 96 #define ZOMBIE 'z' /* zombie process */
97 97 #define VISITED 'v' /* marked node as visited */
98 98 #define PRINTF(a) if (printf a < 0) { \
99 99 perror((gettext("%s: printf failed"), prog)); \
100 100 exit(1); }
101 101
102 102 struct uproc {
103 103 pid_t p_upid; /* process id */
104 104 char p_state; /* numeric value of process state */
105 105 dev_t p_ttyd; /* controlling tty of process */
106 106 time_t p_time; /* seconds of user & system time */
107 107 time_t p_ctime; /* seconds of child user & sys time */
108 108 int p_igintr; /* 1 = ignores SIGQUIT and SIGINT */
109 109 char p_comm[PRARGSZ+1]; /* command */
110 110 char p_args[PRARGSZ+1]; /* command line arguments */
111 111 struct uproc *p_child, /* first child pointer */
112 112 *p_sibling, /* sibling pointer */
113 113 *p_pgrpl, /* pgrp link */
114 114 *p_link; /* hash table chain pointer */
115 115 };
116 116
117 117 /*
118 118 * define hash table for struct uproc
119 119 * Hash function uses process id
120 120 * and the size of the hash table(HSIZE)
121 121 * to determine process index into the table.
↓ open down ↓ |
121 lines elided |
↑ open up ↑ |
122 122 */
123 123 static struct uproc pr_htbl[HSIZE];
124 124
125 125 static struct uproc *findhash(pid_t);
126 126 static time_t findidle(char *);
127 127 static void clnarglist(char *);
128 128 static void showtotals(struct uproc *);
129 129 static void calctotals(struct uproc *);
130 130 static void prttime(time_t, char *);
131 131 static void prtat(time_t *time);
132 -static void checkampm(char *str);
133 132
134 133 static char *prog; /* pointer to invocation name */
135 134 static int header = 1; /* true if -h flag: don't print heading */
136 135 static int lflag = 1; /* set if -l flag; 0 for -s flag: short form */
137 136 static char *sel_user; /* login of particular user selected */
138 137 static char firstchar; /* first char of name of prog invoked as */
139 138 static int login; /* true if invoked as login shell */
140 139 static time_t now; /* current time of day */
141 140 static time_t uptime; /* time of last reboot & elapsed time since */
142 141 static int nusers; /* number of users logged in now */
143 142 static time_t idle; /* number of minutes user is idle */
144 143 static time_t jobtime; /* total cpu time visible */
145 144 static char doing[520]; /* process attached to terminal */
146 145 static time_t proctime; /* cpu time of process in doing */
147 146 static pid_t curpid, empty;
148 147 static int add_times; /* boolean: add the cpu times or not */
149 148
150 149 #if SIGQUIT > SIGINT
151 150 #define ACTSIZE SIGQUIT
152 151 #else
153 152 #define ACTSIZE SIGINT
154 153 #endif
155 154
156 155 int
157 156 main(int argc, char *argv[])
158 157 {
159 158 struct utmpx *ut;
160 159 struct utmpx *utmpbegin;
161 160 struct utmpx *utmpend;
162 161 struct utmpx *utp;
163 162 struct uproc *up, *parent, *pgrp;
164 163 struct psinfo info;
165 164 struct sigaction actinfo[ACTSIZE];
166 165 struct pstatus statinfo;
167 166 size_t size;
168 167 struct stat sbuf;
169 168 DIR *dirp;
170 169 struct dirent *dp;
171 170 char pname[64];
172 171 char *fname;
173 172 int procfd;
174 173 char *cp;
175 174 int i;
176 175 int days, hrs, mins;
177 176 int entries;
178 177 double loadavg[3];
179 178
180 179 /*
181 180 * This program needs the proc_owner privilege
182 181 */
183 182 (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER,
184 183 (char *)NULL);
185 184
186 185 (void) setlocale(LC_ALL, "");
187 186 #if !defined(TEXT_DOMAIN)
188 187 #define TEXT_DOMAIN "SYS_TEST"
189 188 #endif
190 189 (void) textdomain(TEXT_DOMAIN);
191 190
192 191 login = (argv[0][0] == '-');
193 192 cp = strrchr(argv[0], '/');
194 193 firstchar = login ? argv[0][1] : (cp == 0) ? argv[0][0] : cp[1];
195 194 prog = argv[0];
196 195
197 196 while (argc > 1) {
198 197 if (argv[1][0] == '-') {
199 198 for (i = 1; argv[1][i]; i++) {
200 199 switch (argv[1][i]) {
201 200
202 201 case 'h':
203 202 header = 0;
204 203 break;
205 204
206 205 case 'l':
207 206 lflag++;
208 207 break;
209 208 case 's':
210 209 lflag = 0;
211 210 break;
212 211
213 212 case 'u':
214 213 case 'w':
215 214 firstchar = argv[1][i];
216 215 break;
217 216
218 217 default:
219 218 (void) fprintf(stderr, gettext(
220 219 "%s: bad flag %s\n"),
221 220 prog, argv[1]);
222 221 exit(1);
223 222 }
224 223 }
225 224 } else {
226 225 if (!isalnum(argv[1][0]) || argc > 2) {
227 226 (void) fprintf(stderr, gettext(
228 227 "usage: %s [ -hlsuw ] [ user ]\n"), prog);
229 228 exit(1);
230 229 } else
231 230 sel_user = argv[1];
232 231 }
233 232 argc--; argv++;
234 233 }
235 234
236 235 /*
237 236 * read the UTMP_FILE (contains information about each logged in user)
238 237 */
239 238 if (stat(UTMPX_FILE, &sbuf) == ERR) {
240 239 (void) fprintf(stderr, gettext("%s: stat error of %s: %s\n"),
241 240 prog, UTMPX_FILE, strerror(errno));
242 241 exit(1);
243 242 }
244 243 entries = sbuf.st_size / sizeof (struct futmpx);
245 244 size = sizeof (struct utmpx) * entries;
246 245 if ((ut = malloc(size)) == NULL) {
247 246 (void) fprintf(stderr, gettext("%s: malloc error of %s: %s\n"),
248 247 prog, UTMPX_FILE, strerror(errno));
249 248 exit(1);
250 249 }
251 250
252 251 (void) utmpxname(UTMPX_FILE);
253 252
254 253 utmpbegin = ut;
255 254 utmpend = (struct utmpx *)((char *)utmpbegin + size);
256 255
257 256 setutxent();
258 257 while ((ut < utmpend) && ((utp = getutxent()) != NULL))
259 258 (void) memcpy(ut++, utp, sizeof (*ut));
260 259 endutxent();
261 260
262 261 (void) time(&now); /* get current time */
263 262
264 263 if (header) { /* print a header */
265 264 prtat(&now);
266 265 for (ut = utmpbegin; ut < utmpend; ut++) {
267 266 if (ut->ut_type == USER_PROCESS) {
268 267 if (!nonuser(*ut))
269 268 nusers++;
270 269 } else if (ut->ut_type == BOOT_TIME) {
271 270 uptime = now - ut->ut_xtime;
272 271 uptime += 30;
273 272 days = uptime / (60*60*24);
274 273 uptime %= (60*60*24);
275 274 hrs = uptime / (60*60);
276 275 uptime %= (60*60);
277 276 mins = uptime / 60;
278 277
279 278 PRINTF((gettext(" up")));
280 279 if (days > 0)
281 280 PRINTF((gettext(
282 281 " %d day(s),"), days));
283 282 if (hrs > 0 && mins > 0) {
284 283 PRINTF((" %2d:%02d,", hrs, mins));
285 284 } else {
286 285 if (hrs > 0)
287 286 PRINTF((gettext(
288 287 " %d hr(s),"), hrs));
289 288 if (mins > 0)
290 289 PRINTF((gettext(
291 290 " %d min(s),"), mins));
292 291 }
293 292 }
294 293 }
295 294
296 295 ut = utmpbegin; /* rewind utmp data */
297 296 PRINTF((((nusers == 1) ?
298 297 gettext(" %d user") : gettext(" %d users")), nusers));
299 298 /*
300 299 * Print 1, 5, and 15 minute load averages.
301 300 */
302 301 (void) getloadavg(loadavg, 3);
303 302 PRINTF((gettext(", load average: %.2f, %.2f, %.2f\n"),
304 303 loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
305 304 loadavg[LOADAVG_15MIN]));
306 305
307 306 if (firstchar == 'u') /* uptime command */
308 307 exit(0);
309 308
310 309 if (lflag) {
311 310 PRINTF((dcgettext(NULL, "User tty "
312 311 "login@ idle JCPU PCPU what\n", LC_TIME)));
313 312 } else {
314 313 PRINTF((dcgettext(NULL,
315 314 "User tty idle what\n", LC_TIME)));
316 315 }
317 316
318 317 if (fflush(stdout) == EOF) {
319 318 perror((gettext("%s: fflush failed\n"), prog));
320 319 exit(1);
321 320 }
322 321 }
323 322
324 323 /*
325 324 * loop through /proc, reading info about each process
326 325 * and build the parent/child tree
327 326 */
328 327 if (!(dirp = opendir(PROCDIR))) {
329 328 (void) fprintf(stderr, gettext("%s: could not open %s: %s\n"),
330 329 prog, PROCDIR, strerror(errno));
331 330 exit(1);
332 331 }
333 332
334 333 while ((dp = readdir(dirp)) != NULL) {
335 334 if (dp->d_name[0] == '.')
336 335 continue;
337 336 retry:
338 337 (void) sprintf(pname, "%s/%s/", PROCDIR, dp->d_name);
339 338 fname = pname + strlen(pname);
340 339 (void) strcpy(fname, "psinfo");
341 340 if ((procfd = open(pname, O_RDONLY)) < 0)
342 341 continue;
343 342 if (read(procfd, &info, sizeof (info)) != sizeof (info)) {
344 343 int err = errno;
345 344 (void) close(procfd);
346 345 if (err == EAGAIN)
347 346 goto retry;
348 347 if (err != ENOENT)
349 348 (void) fprintf(stderr, gettext(
350 349 "%s: read() failed on %s: %s \n"),
351 350 prog, pname, strerror(err));
352 351 continue;
353 352 }
354 353 (void) close(procfd);
355 354
356 355 up = findhash(info.pr_pid);
357 356 up->p_ttyd = info.pr_ttydev;
358 357 up->p_state = (info.pr_nlwp == 0? ZOMBIE : RUNNING);
359 358 up->p_time = 0;
360 359 up->p_ctime = 0;
361 360 up->p_igintr = 0;
362 361 (void) strncpy(up->p_comm, info.pr_fname,
363 362 sizeof (info.pr_fname));
364 363 up->p_args[0] = 0;
365 364
366 365 if (up->p_state != NONE && up->p_state != ZOMBIE) {
367 366 (void) strcpy(fname, "status");
368 367
369 368 /* now we need the proc_owner privilege */
370 369 (void) __priv_bracket(PRIV_ON);
371 370
372 371 procfd = open(pname, O_RDONLY);
373 372
374 373 /* drop proc_owner privilege after open */
375 374 (void) __priv_bracket(PRIV_OFF);
376 375
377 376 if (procfd < 0)
378 377 continue;
379 378
380 379 if (read(procfd, &statinfo, sizeof (statinfo))
381 380 != sizeof (statinfo)) {
382 381 int err = errno;
383 382 (void) close(procfd);
384 383 if (err == EAGAIN)
385 384 goto retry;
386 385 if (err != ENOENT)
387 386 (void) fprintf(stderr, gettext(
388 387 "%s: read() failed on %s: %s \n"),
389 388 prog, pname, strerror(err));
390 389 continue;
391 390 }
392 391 (void) close(procfd);
393 392
394 393 up->p_time = statinfo.pr_utime.tv_sec +
395 394 statinfo.pr_stime.tv_sec; /* seconds */
396 395 up->p_ctime = statinfo.pr_cutime.tv_sec +
397 396 statinfo.pr_cstime.tv_sec;
398 397
399 398 (void) strcpy(fname, "sigact");
400 399
401 400 /* now we need the proc_owner privilege */
402 401 (void) __priv_bracket(PRIV_ON);
403 402
404 403 procfd = open(pname, O_RDONLY);
405 404
406 405 /* drop proc_owner privilege after open */
407 406 (void) __priv_bracket(PRIV_OFF);
408 407
409 408 if (procfd < 0)
410 409 continue;
411 410
412 411 if (read(procfd, actinfo, sizeof (actinfo))
413 412 != sizeof (actinfo)) {
414 413 int err = errno;
415 414 (void) close(procfd);
416 415 if (err == EAGAIN)
417 416 goto retry;
418 417 if (err != ENOENT)
419 418 (void) fprintf(stderr, gettext(
420 419 "%s: read() failed on %s: %s \n"),
421 420 prog, pname, strerror(err));
422 421 continue;
423 422 }
424 423 (void) close(procfd);
425 424
426 425 up->p_igintr =
427 426 actinfo[SIGINT-1].sa_handler == SIG_IGN &&
428 427 actinfo[SIGQUIT-1].sa_handler == SIG_IGN;
429 428
430 429 /*
431 430 * Process args.
432 431 */
433 432 up->p_args[0] = 0;
434 433 clnarglist(info.pr_psargs);
435 434 (void) strcat(up->p_args, info.pr_psargs);
436 435 if (up->p_args[0] == 0 ||
437 436 up->p_args[0] == '-' && up->p_args[1] <= ' ' ||
438 437 up->p_args[0] == '?') {
439 438 (void) strcat(up->p_args, " (");
440 439 (void) strcat(up->p_args, up->p_comm);
441 440 (void) strcat(up->p_args, ")");
442 441 }
443 442 }
444 443
445 444 /*
446 445 * link pgrp together in case parents go away
447 446 * Pgrp chain is a single linked list originating
448 447 * from the pgrp leader to its group member.
449 448 */
450 449 if (info.pr_pgid != info.pr_pid) { /* not pgrp leader */
451 450 pgrp = findhash(info.pr_pgid);
452 451 up->p_pgrpl = pgrp->p_pgrpl;
453 452 pgrp->p_pgrpl = up;
454 453 }
455 454 parent = findhash(info.pr_ppid);
456 455
457 456 /* if this is the new member, link it in */
458 457 if (parent->p_upid != INITPROCESS) {
459 458 if (parent->p_child) {
460 459 up->p_sibling = parent->p_child;
461 460 up->p_child = 0;
462 461 }
463 462 parent->p_child = up;
464 463 }
465 464 }
466 465
467 466 /* revert to non-privileged user after opening */
468 467 (void) __priv_relinquish();
469 468
470 469 (void) closedir(dirp);
471 470 (void) time(&now); /* get current time */
472 471
473 472 /*
474 473 * loop through utmpx file, printing process info
475 474 * about each logged in user
476 475 */
477 476 for (ut = utmpbegin; ut < utmpend; ut++) {
478 477 if (ut->ut_type != USER_PROCESS)
479 478 continue;
480 479 if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0)
481 480 continue; /* we're looking for somebody else */
482 481
483 482 /* print login name of the user */
484 483 PRINTF(("%-*.*s ", LOGIN_WIDTH, NMAX, ut->ut_name));
485 484
486 485 /* print tty user is on */
487 486 if (lflag) {
488 487 PRINTF(("%-*.*s", LINE_WIDTH, LMAX, ut->ut_line));
489 488 } else {
490 489 if (ut->ut_line[0] == 'p' && ut->ut_line[1] == 't' &&
491 490 ut->ut_line[2] == 's' && ut->ut_line[3] == '/') {
492 491 PRINTF(("%-*.3s", LMAX, &ut->ut_line[4]));
493 492 } else {
494 493 PRINTF(("%-*.*s", LINE_WIDTH, LMAX,
495 494 ut->ut_line));
496 495 }
497 496 }
498 497
499 498 /* print when the user logged in */
500 499 if (lflag) {
501 500 time_t tim = ut->ut_xtime;
502 501 prtat(&tim);
503 502 }
504 503
505 504 /* print idle time */
506 505 idle = findidle(ut->ut_line);
507 506 if (idle >= 36 * 60) {
508 507 PRINTF((dcgettext(NULL, "%2ddays ", LC_TIME),
509 508 (idle + 12 * 60) / (24 * 60)));
510 509 } else
511 510 prttime(idle, " ");
512 511 showtotals(findhash(ut->ut_pid));
513 512 }
514 513 if (fclose(stdout) == EOF) {
515 514 perror((gettext("%s: fclose failed"), prog));
516 515 exit(1);
517 516 }
518 517 return (0);
519 518 }
520 519
521 520 /*
522 521 * Prints the CPU time for all processes & children,
523 522 * and the cpu time for interesting process,
524 523 * and what the user is doing.
525 524 */
526 525 static void
527 526 showtotals(struct uproc *up)
528 527 {
529 528 jobtime = 0;
530 529 proctime = 0;
531 530 empty = 1;
532 531 curpid = -1;
533 532 add_times = 1;
534 533
535 534 calctotals(up);
536 535
537 536 if (lflag) {
538 537 /* print CPU time for all processes & children */
539 538 /* and need to convert clock ticks to seconds first */
540 539 prttime((time_t)jobtime, " ");
541 540
542 541 /* print cpu time for interesting process */
543 542 /* and need to convert clock ticks to seconds first */
544 543 prttime((time_t)proctime, " ");
545 544 }
546 545 /* what user is doing, current process */
547 546 PRINTF((" %-.32s\n", doing));
548 547 }
549 548
550 549 /*
551 550 * This recursive routine descends the process
552 551 * tree starting from the given process pointer(up).
553 552 * It used depth-first search strategy and also marked
554 553 * each node as visited as it traversed down the tree.
555 554 * It calculates the process time for all processes &
556 555 * children. It also finds the interesting process
557 556 * and determines its cpu time and command.
558 557 */
559 558 static void
560 559 calctotals(struct uproc *up)
561 560 {
562 561 struct uproc *zp;
563 562
564 563 /*
565 564 * Once a node has been visited, stop adding cpu times
566 565 * for its children so they don't get totalled twice.
567 566 * Still look for the interesting job for this utmp
568 567 * entry, however.
569 568 */
570 569 if (up->p_state == VISITED)
571 570 add_times = 0;
572 571 up->p_state = VISITED;
573 572 if (up->p_state == NONE || up->p_state == ZOMBIE)
574 573 return;
575 574
576 575 if (empty && !up->p_igintr) {
577 576 empty = 0;
578 577 curpid = -1;
579 578 }
580 579
581 580 if (up->p_upid > curpid && (!up->p_igintr || empty)) {
582 581 curpid = up->p_upid;
583 582 if (lflag)
584 583 (void) strcpy(doing, up->p_args);
585 584 else
586 585 (void) strcpy(doing, up->p_comm);
587 586 }
588 587
589 588 if (add_times == 1) {
590 589 jobtime += up->p_time + up->p_ctime;
591 590 proctime += up->p_time;
592 591 }
593 592
594 593 /* descend for its children */
595 594 if (up->p_child) {
596 595 calctotals(up->p_child);
597 596 for (zp = up->p_child->p_sibling; zp; zp = zp->p_sibling)
598 597 calctotals(zp);
599 598 }
600 599 }
601 600
602 601 /*
603 602 * Findhash finds the appropriate entry in the process
604 603 * hash table (pr_htbl) for the given pid in case that
605 604 * pid exists on the hash chain. It returns back a pointer
606 605 * to that uproc structure. If this is a new pid, it allocates
607 606 * a new node, initializes it, links it into the chain (after
608 607 * head) and returns a structure pointer.
609 608 */
610 609 static struct uproc *
611 610 findhash(pid_t pid)
612 611 {
613 612 struct uproc *up, *tp;
614 613
615 614 tp = up = &pr_htbl[pid % HSIZE];
616 615 if (up->p_upid == 0) { /* empty slot */
617 616 up->p_upid = pid;
618 617 up->p_state = NONE;
619 618 up->p_child = up->p_sibling = up->p_pgrpl = up->p_link = 0;
620 619 return (up);
621 620 }
622 621 if (up->p_upid == pid) { /* found in hash table */
623 622 return (up);
624 623 }
625 624 for (tp = up->p_link; tp; tp = tp->p_link) { /* follow chain */
626 625 if (tp->p_upid == pid)
627 626 return (tp);
628 627 }
629 628 tp = malloc(sizeof (*tp)); /* add new node */
630 629 if (!tp) {
631 630 (void) fprintf(stderr, gettext("%s: out of memory!: %s\n"),
632 631 prog, strerror(errno));
633 632 exit(1);
634 633 }
635 634 (void) memset(tp, 0, sizeof (*tp));
636 635 tp->p_upid = pid;
637 636 tp->p_state = NONE;
638 637 tp->p_child = tp->p_sibling = tp->p_pgrpl = 0;
639 638 tp->p_link = up->p_link; /* insert after head */
640 639 up->p_link = tp;
641 640 return (tp);
642 641 }
643 642
644 643 #define HR (60 * 60)
645 644 #define DAY (24 * HR)
646 645 #define MON (30 * DAY)
647 646
648 647 /*
649 648 * prttime prints a time in hours and minutes or minutes and seconds.
650 649 * The character string tail is printed at the end, obvious
651 650 * strings to pass are "", " ", or "am".
652 651 */
653 652 static void
654 653 prttime(time_t tim, char *tail)
655 654 {
656 655 if (tim >= 60) {
657 656 PRINTF((dcgettext(NULL, "%3d:%02d", LC_TIME),
658 657 (int)tim/60, (int)tim%60));
659 658 } else if (tim > 0) {
660 659 PRINTF((dcgettext(NULL, " %2d", LC_TIME), (int)tim));
661 660 } else {
662 661 PRINTF((" "));
663 662 }
664 663 PRINTF(("%s", tail));
665 664 }
666 665
667 666 /*
668 667 * prints a 12 hour time given a pointer to a time of day
↓ open down ↓ |
526 lines elided |
↑ open up ↑ |
669 668 */
670 669 static void
671 670 prtat(time_t *time)
672 671 {
673 672 struct tm *p;
674 673
675 674 p = localtime(time);
676 675 if (now - *time <= 18 * HR) {
677 676 char timestr[50];
678 677 (void) strftime(timestr, sizeof (timestr),
679 - dcgettext(NULL, "%l:%M""%p", LC_TIME), p);
680 - checkampm(timestr);
678 + " %R ", p);
681 679 PRINTF((" %s", timestr));
682 680 } else if (now - *time <= 7 * DAY) {
683 681 char weekdaytime[20];
684 682
685 683 (void) strftime(weekdaytime, sizeof (weekdaytime),
686 - dcgettext(NULL, "%a%l%p", LC_TIME), p);
687 - checkampm(weekdaytime);
684 + "%a%H ", p);
688 685 PRINTF((" %s", weekdaytime));
689 686 } else {
690 687 char monthtime[20];
691 688
692 689 (void) strftime(monthtime, sizeof (monthtime),
693 - dcgettext(NULL, "%e%b%y", LC_TIME), p);
690 + "%e%b%y", p);
694 691 PRINTF((" %s", monthtime));
695 692 }
696 693 }
697 694
698 695 /*
699 696 * find & return number of minutes current tty has been idle
700 697 */
701 698 static time_t
702 699 findidle(char *devname)
703 700 {
704 701 struct stat stbuf;
705 702 time_t lastaction, diff;
706 703 char ttyname[64];
707 704
708 705 (void) strcpy(ttyname, "/dev/");
709 706 (void) strcat(ttyname, devname);
710 707 if (stat(ttyname, &stbuf) != -1) {
711 708 lastaction = stbuf.st_atime;
712 709 diff = now - lastaction;
713 710 diff = DIV60(diff);
714 711 if (diff < 0)
715 712 diff = 0;
716 713 } else
717 714 diff = 0;
718 715 return (diff);
719 716 }
720 717
721 718 /*
722 719 * given a pointer to the argument string get rid of unsavory characters.
723 720 */
724 721 static void
725 722 clnarglist(char *arglist)
726 723 {
727 724 char *c;
728 725 int err = 0;
729 726
730 727 /* get rid of unsavory characters */
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
731 728 for (c = arglist; *c != NULL; c++) {
732 729 if ((*c < ' ') || (*c > 0176)) {
733 730 if (err++ > 5) {
734 731 *arglist = NULL;
735 732 break;
736 733 }
737 734 *c = '?';
738 735 }
739 736 }
740 737 }
741 -
742 -/* replaces all occurences of AM/PM with am/pm */
743 -static void
744 -checkampm(char *str)
745 -{
746 - char *ampm;
747 - while ((ampm = strstr(str, "AM")) != NULL ||
748 - (ampm = strstr(str, "PM")) != NULL) {
749 - *ampm = tolower(*ampm);
750 - *(ampm+1) = tolower(*(ampm+1));
751 - }
752 -}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX