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