OS2021_Project1.Shell
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

894 lines
16 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <dirent.h>
  6. #include <signal.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <sys/wait.h>
  10. #include <sys/stat.h>
  11. #include <sys/ioc_tty.h>
  12. #include <sys/times.h>
  13. #include <sys/types.h>
  14. #include <sys/time.h>
  15. #include <sys/select.h>
  16. #include <curses.h>
  17. #include <timers.h>
  18. #include <limits.h>
  19. #include <termcap.h>
  20. #include <termios.h>
  21. #include <time.h>
  22. #include <assert.h>
  23. #include <minix/com.h>
  24. #include <minix/config.h>
  25. #include <minix/type.h>
  26. #include <minix/endpoint.h>
  27. #include <minix/const.h>
  28. #include <minix/u64.h>
  29. #include <paths.h>
  30. #include <minix/procfs.h>
  31. #include "yeeshell.h"
  32. /* record cmdline history */
  33. char *history[CMDLINE_HISTORY_MAX_QUANTITY];
  34. int cmdline_amount = 0;
  35. /* mytop CPU part */
  36. struct proc *proc = NULL, *prev_proc = NULL;
  37. int nr_total;
  38. unsigned int nr_procs, nr_tasks;
  39. /* name of cpu cycle types, in the order they appear in /psinfo. */
  40. const char *cputimenames[] = {"user", "ipc", "kernelcall"};
  41. int blockedverbose = 0;
  42. int main()
  43. {
  44. char *cmdline = NULL, *pwd = NULL;
  45. char *args[ARGS_MAX_QUANTITY];
  46. int status = 1;
  47. pwd = (char *)calloc(PATH_MAX_SIZE, sizeof(char));
  48. for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++)
  49. {
  50. history[i] = (char *)calloc(CMDLINE_MAX_SIZE, sizeof(char));
  51. }
  52. /* execute the shell's read, parse and execution loop */
  53. do
  54. {
  55. if (!getcwd(pwd, PATH_MAX_SIZE))
  56. {
  57. printf("yeeshell: The current path cannot be obtained!\n");
  58. exit(0);
  59. }
  60. printf("[root@yeeshell %s]# ", pwd);
  61. cmdline = readline();
  62. strcpy(history[cmdline_amount++], cmdline);
  63. status = execute(cmdline, args);
  64. free(cmdline);
  65. } while (status);
  66. for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++)
  67. {
  68. free(history[i]);
  69. }
  70. exit(EXIT_SUCCESS);
  71. }
  72. char *readline()
  73. {
  74. char *cmdline = NULL;
  75. ssize_t bufsize = 0;
  76. getline(&cmdline, &bufsize, stdin);
  77. return cmdline;
  78. }
  79. int parseline(char *cmdline, char **args)
  80. {
  81. static char array[CMDLINE_MAX_SIZE]; /* holds local copy of command line */
  82. char *buf = array; /* ptr that traverses command line */
  83. char *delim; /* points to first space delimiter */
  84. int argc; /* number of args */
  85. int bg; /* background job? */
  86. strcpy(buf, cmdline);
  87. buf[strlen(buf) - 1] = ' '; /* replace trailing '\n' with space */
  88. while (*buf && (*buf == ' ')) /* ignore leading spaces */
  89. {
  90. buf++;
  91. }
  92. /* Build the argv list */
  93. argc = 0;
  94. if (*buf == '\'')
  95. {
  96. buf++;
  97. delim = strchr(buf, '\'');
  98. }
  99. else
  100. {
  101. delim = strchr(buf, ' ');
  102. }
  103. while (delim)
  104. {
  105. args[argc++] = buf;
  106. *delim = '\0';
  107. buf = delim + 1;
  108. while (*buf && (*buf == ' ')) /* ignore spaces */
  109. {
  110. buf++;
  111. }
  112. if (*buf == '\'')
  113. {
  114. buf++;
  115. delim = strchr(buf, '\'');
  116. }
  117. else
  118. {
  119. delim = strchr(buf, ' ');
  120. }
  121. }
  122. args[argc] = NULL;
  123. if (argc == 0) /* ignore blank line */
  124. {
  125. return 1;
  126. }
  127. /* should the job run in the background? */
  128. if ((bg = (*args[argc - 1] == '&')) != 0)
  129. {
  130. args[--argc] = NULL;
  131. }
  132. return bg;
  133. }
  134. int check_redirect(char **args, char *redirect_filename, char **redirect_args)
  135. {
  136. int i = 0, j = 0, redirect_flag = REDIRECT_NO;
  137. while (args[i] != NULL)
  138. {
  139. if (!strcmp(args[i], ">"))
  140. {
  141. redirect_flag = REDIRECT_OUT;
  142. break;
  143. }
  144. else if (!strcmp(args[i], "<"))
  145. {
  146. redirect_flag = REDIRECT_IN;
  147. break;
  148. }
  149. i++;
  150. }
  151. if ((redirect_flag == 1) || (redirect_flag == 2))
  152. {
  153. strcpy(redirect_filename, args[i + 1]);
  154. for (j = 0; j < i; j++)
  155. {
  156. redirect_args[j] = args[j];
  157. }
  158. }
  159. return redirect_flag;
  160. }
  161. int do_redirect(int redirect_flag, char *redirect_filename, char **redirect_args)
  162. {
  163. pid_t pid;
  164. int fd = 1;
  165. if ((pid = fork()) == 0) /* Child process */
  166. {
  167. if (redirect_flag == 1) /* in or out? */
  168. {
  169. fd = open(redirect_filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR);
  170. close(1);
  171. dup(fd);
  172. }
  173. else if (redirect_flag == 2)
  174. {
  175. fd = open(redirect_filename, O_RDONLY, S_IRUSR);
  176. close(0);
  177. dup(fd);
  178. }
  179. if (execvp(redirect_args[0], redirect_args) <= 0)
  180. {
  181. printf("%s: Command not found\n", redirect_args[0]);
  182. exit(0);
  183. }
  184. close(fd);
  185. }
  186. else /* parent process */
  187. {
  188. waitpid(pid, NULL, 0);
  189. }
  190. return 1;
  191. }
  192. int check_pipe(char **args, char **pipe_arg_1, char **pipe_arg_2)
  193. {
  194. int pipe_flag = 0, i = 0, j = 0;
  195. while (args[i] != NULL)
  196. {
  197. if (!strcmp(args[i], "|"))
  198. {
  199. pipe_flag = 1;
  200. break;
  201. }
  202. pipe_arg_1[j++] = args[i++];
  203. }
  204. pipe_arg_1[j] = NULL;
  205. j = 0;
  206. i++;
  207. while (args[i] != NULL)
  208. {
  209. pipe_arg_2[j++] = args[i++];
  210. }
  211. pipe_arg_2[j] = NULL;
  212. return pipe_flag;
  213. }
  214. int do_pipe(char **pipe_arg_1, char **pipe_arg_2)
  215. {
  216. int fds[2];
  217. pipe(fds);
  218. pid_t prog_1, prog_2;
  219. if ((prog_1 = fork()) == 0) /* Child process 1 */
  220. {
  221. close(1);
  222. dup(fds[1]);
  223. close(fds[0]);
  224. close(fds[1]);
  225. if (execvp(pipe_arg_1[0], pipe_arg_1) <= 0)
  226. {
  227. printf("%s: Command not found\n", pipe_arg_1[0]);
  228. exit(0);
  229. }
  230. }
  231. if ((prog_2 = fork()) == 0) /* Child process 1 */
  232. {
  233. dup2(fds[0], 0);
  234. close(fds[0]);
  235. close(fds[1]);
  236. if (execvp(pipe_arg_2[0], pipe_arg_2) <= 0)
  237. {
  238. printf("%s: Command not found\n", pipe_arg_2[0]);
  239. exit(0);
  240. }
  241. }
  242. close(fds[0]);
  243. close(fds[1]);
  244. waitpid(prog_1, NULL, 0);
  245. waitpid(prog_2, NULL, 0);
  246. return 1;
  247. }
  248. int do_bg_fg(char **args, int bg)
  249. {
  250. pid_t pid;
  251. if ((pid = fork()) == 0)
  252. {
  253. if (execvp(args[0], args) <= 0)
  254. {
  255. printf("%s: Command not found\n", args[0]);
  256. exit(0);
  257. }
  258. }
  259. else
  260. {
  261. if (bg)
  262. {
  263. signal(SIGCHLD, SIG_IGN);
  264. }
  265. else
  266. {
  267. waitpid(pid, NULL, 0);
  268. }
  269. }
  270. return 1;
  271. }
  272. int execute(char *cmdline, char **args)
  273. {
  274. int bg = 0, i = 0, redirect_flag = 0, pipe_num = 0;
  275. pid_t pid;
  276. char *redirect_filename = NULL;
  277. char *redirect_args[ARGS_MAX_QUANTITY];
  278. char *pipe_arg_1[ARGS_MAX_QUANTITY];
  279. char *pipe_arg_2[ARGS_MAX_QUANTITY];
  280. redirect_filename = (char *)calloc(REDIRECT_FILENAME_MAX_SIZE, sizeof(char));
  281. memset(redirect_args, NULL, sizeof(redirect_args));
  282. bg = parseline(cmdline, args);
  283. redirect_flag = check_redirect(args, redirect_filename, redirect_args);
  284. pipe_num = check_pipe(args, pipe_arg_1, pipe_arg_2);
  285. if (args[0] == NULL)
  286. {
  287. return 1;
  288. }
  289. if (pipe_num == 0) /* no pipe */
  290. {
  291. if (!built_in(args)) /* built-in cmd? */
  292. {
  293. if (redirect_flag != 0) /* redirection? */
  294. {
  295. return do_redirect(redirect_flag, redirect_filename, redirect_args);
  296. }
  297. else
  298. {
  299. return do_bg_fg(args, bg);
  300. }
  301. }
  302. else
  303. {
  304. return 1;
  305. }
  306. }
  307. else
  308. {
  309. return do_pipe(pipe_arg_1, pipe_arg_2);
  310. }
  311. }
  312. int built_in(char **args)
  313. {
  314. if (!strcmp(args[0], "exit"))
  315. {
  316. exit(0);
  317. }
  318. else if (!strcmp(args[0], "cd"))
  319. {
  320. return builtin_cd(args);
  321. }
  322. else if (!strcmp(args[0], "history"))
  323. {
  324. return builtin_history(args);
  325. }
  326. else if (!strcmp(args[0], "mytop"))
  327. {
  328. int flag = builtin_mytop();
  329. if (flag == -1)
  330. {
  331. printf("yeeshell: unable to get memory info.\n");
  332. }
  333. else if (flag == -2)
  334. {
  335. printf("yeeshell: unable to get CPU info.\n");
  336. }
  337. return flag;
  338. }
  339. else
  340. {
  341. return 0;
  342. }
  343. }
  344. int builtin_cd(char **args)
  345. {
  346. if (args[1] == NULL)
  347. {
  348. return 1;
  349. }
  350. else
  351. {
  352. if (chdir(args[1]) != 0)
  353. {
  354. perror("yeeshell");
  355. }
  356. return 1;
  357. }
  358. }
  359. int builtin_history(char **args)
  360. {
  361. int n = 0;
  362. if (args[1] == NULL)
  363. {
  364. n = cmdline_amount;
  365. }
  366. else
  367. {
  368. n = atoi(args[1]) < cmdline_amount ? atoi(args[1]) : cmdline_amount;
  369. }
  370. printf("ID\tCommandline\n");
  371. for (int i = 0; i < n; i++)
  372. {
  373. printf("%d\t%s\n", i + 1, history[i]);
  374. }
  375. return 1;
  376. }
  377. int builtin_mytop()
  378. {
  379. int memory_flag = 0, CPU_flag = 0;
  380. memory_flag = mytop_memory();
  381. CPU_flag = mytop_CPU();
  382. if (!memory_flag)
  383. {
  384. return -1;
  385. }
  386. else if (!CPU_flag)
  387. {
  388. return -2;
  389. }
  390. else
  391. {
  392. return 1;
  393. }
  394. }
  395. int mytop_memory()
  396. {
  397. FILE *fp = NULL;
  398. int pagesize;
  399. long total = 0, free = 0, cached = 0;
  400. if ((fp = fopen("/proc/meminfo", "r")) == NULL)
  401. {
  402. return 0;
  403. }
  404. fscanf(fp, "%u %lu %lu %lu", &pagesize, &total, &free, &cached);
  405. fclose(fp);
  406. printf("memmory(KBytes):\t%ld total\t%ld free\t%ld cached\n", (pagesize * total) / 1024, (pagesize * free) / 1024, (pagesize * cached) / 1024);
  407. return 1;
  408. }
  409. int mytop_CPU()
  410. {
  411. pid_t pid;
  412. if ((pid = fork()) == 0)
  413. {
  414. printf("fork error\n");
  415. return;
  416. }
  417. if (pid == 0)
  418. {
  419. int cputimemode = 1;
  420. getkinfo();
  421. print_memory();
  422. get_procs();
  423. if (prev_proc == NULL)
  424. get_procs();
  425. print_procs(prev_proc, proc, cputimemode);
  426. exit(0);
  427. }
  428. return 1;
  429. }
  430. void getkinfo(void)
  431. {
  432. FILE *fp;
  433. if ((fp = fopen("kinfo", "r")) == NULL)
  434. {
  435. fprintf(stderr, "opening " _PATH_PROC "kinfo failed\n");
  436. exit(1);
  437. }
  438. if (fscanf(fp, "%u %u", &nr_procs, &nr_tasks) != 2)
  439. {
  440. fprintf(stderr, "reading from " _PATH_PROC "kinfo failed\n");
  441. exit(1);
  442. }
  443. fclose(fp);
  444. nr_total = (int)(nr_procs + nr_tasks);
  445. }
  446. void get_procs(void)
  447. {
  448. struct proc *p;
  449. int i;
  450. p = prev_proc;
  451. prev_proc = proc;
  452. proc = p;
  453. if (proc == NULL)
  454. {
  455. proc = malloc(nr_total * sizeof(proc[0]));
  456. if (proc == NULL)
  457. {
  458. fprintf(stderr, "Out of memory!\n");
  459. exit(1);
  460. }
  461. }
  462. for (i = 0; i < nr_total; i++)
  463. proc[i].p_flags = 0;
  464. parse_dir();
  465. }
  466. void parse_dir(void)
  467. {
  468. DIR *p_dir;
  469. struct dirent *p_ent;
  470. pid_t pid;
  471. char *end;
  472. if ((p_dir = opendir(".")) == NULL)
  473. {
  474. perror("opendir on " _PATH_PROC);
  475. exit(1);
  476. }
  477. for (p_ent = readdir(p_dir); p_ent != NULL; p_ent = readdir(p_dir))
  478. {
  479. pid = strtol(p_ent->d_name, &end, 10);
  480. if (!end[0] && pid != 0)
  481. parse_file(pid);
  482. }
  483. closedir(p_dir);
  484. }
  485. void parse_file(pid_t pid)
  486. {
  487. char path[PATH_MAX], name[256], type, state;
  488. int version, endpt, effuid;
  489. unsigned long cycles_hi, cycles_lo;
  490. FILE *fp;
  491. struct proc *p;
  492. int slot;
  493. int i;
  494. sprintf(path, "%d/psinfo", pid);
  495. if ((fp = fopen(path, "r")) == NULL)
  496. return;
  497. if (fscanf(fp, "%d", &version) != 1)
  498. {
  499. fclose(fp);
  500. return;
  501. }
  502. if (version != PSINFO_VERSION)
  503. {
  504. fputs("procfs version mismatch!\n", stderr);
  505. exit(1);
  506. }
  507. if (fscanf(fp, " %c %d", &type, &endpt) != 2)
  508. {
  509. fclose(fp);
  510. return;
  511. }
  512. slot = SLOT_NR(endpt);
  513. if (slot < 0 || slot >= nr_total)
  514. {
  515. fprintf(stderr, "top: unreasonable endpoint number %d\n", endpt);
  516. fclose(fp);
  517. return;
  518. }
  519. p = &proc[slot];
  520. if (type == TYPE_TASK)
  521. p->p_flags |= IS_TASK;
  522. else if (type == TYPE_SYSTEM)
  523. p->p_flags |= IS_SYSTEM;
  524. p->p_endpoint = endpt;
  525. p->p_pid = pid;
  526. if (fscanf(fp, " %255s %c %d %d %lu %*u %lu %lu",
  527. name, &state, &p->p_blocked, &p->p_priority,
  528. &p->p_user_time, &cycles_hi, &cycles_lo) != 7)
  529. {
  530. fclose(fp);
  531. return;
  532. }
  533. strncpy(p->p_name, name, sizeof(p->p_name) - 1);
  534. p->p_name[sizeof(p->p_name) - 1] = 0;
  535. if (state != STATE_RUN)
  536. p->p_flags |= BLOCKED;
  537. p->p_cpucycles[0] = make64(cycles_lo, cycles_hi);
  538. p->p_memory = 0L;
  539. if (!(p->p_flags & IS_TASK))
  540. {
  541. int j;
  542. if ((j = fscanf(fp, " %lu %*u %*u %*c %*d %*u %u %*u %d %*c %*d %*u",
  543. &p->p_memory, &effuid, &p->p_nice)) != 3)
  544. {
  545. fclose(fp);
  546. return;
  547. }
  548. p->p_effuid = effuid;
  549. }
  550. else
  551. p->p_effuid = 0;
  552. for (i = 1; i < CPUTIMENAMES; i++)
  553. {
  554. if (fscanf(fp, " %lu %lu",
  555. &cycles_hi, &cycles_lo) == 2)
  556. {
  557. p->p_cpucycles[i] = make64(cycles_lo, cycles_hi);
  558. }
  559. else
  560. {
  561. p->p_cpucycles[i] = 0;
  562. }
  563. }
  564. if ((p->p_flags & IS_TASK))
  565. {
  566. if (fscanf(fp, " %lu", &p->p_memory) != 1)
  567. {
  568. p->p_memory = 0;
  569. }
  570. }
  571. p->p_flags |= USED;
  572. fclose(fp);
  573. }
  574. void print_procs(int maxlines, struct proc *proc1, struct proc *proc2, int cputimemode)
  575. {
  576. int p, nprocs;
  577. u64_t idleticks = 0;
  578. u64_t kernelticks = 0;
  579. u64_t systemticks = 0;
  580. u64_t userticks = 0;
  581. u64_t total_ticks = 0;
  582. int blockedseen = 0;
  583. static struct tp *tick_procs = NULL;
  584. if (tick_procs == NULL)
  585. {
  586. tick_procs = malloc(nr_total * sizeof(tick_procs[0]));
  587. if (tick_procs == NULL)
  588. {
  589. fprintf(stderr, "Out of memory!\n");
  590. exit(1);
  591. }
  592. }
  593. for (p = nprocs = 0; p < nr_total; p++)
  594. {
  595. u64_t uticks;
  596. if (!(proc2[p].p_flags & USED))
  597. continue;
  598. tick_procs[nprocs].p = proc2 + p;
  599. tick_procs[nprocs].ticks = cputicks(&proc1[p], &proc2[p], cputimemode);
  600. uticks = cputicks(&proc1[p], &proc2[p], 1);
  601. total_ticks = total_ticks + uticks;
  602. if (p - NR_TASKS == IDLE)
  603. {
  604. idleticks = uticks;
  605. continue;
  606. }
  607. if (p - NR_TASKS == KERNEL)
  608. {
  609. kernelticks = uticks;
  610. }
  611. if (!(proc2[p].p_flags & IS_TASK))
  612. {
  613. if (proc2[p].p_flags & IS_SYSTEM)
  614. systemticks = systemticks + tick_procs[nprocs].ticks;
  615. else
  616. userticks = userticks + tick_procs[nprocs].ticks;
  617. }
  618. nprocs++;
  619. }
  620. if (total_ticks == 0)
  621. return;
  622. qsort(tick_procs, nprocs, sizeof(tick_procs[0]), cmp_procs);
  623. printf("CPU states: %6.2f%% user, ", 100.0 * userticks / total_ticks);
  624. printf("%6.2f%% system, ", 100.0 * systemticks / total_ticks);
  625. printf("%6.2f%% kernel, ", 100.0 * kernelticks / total_ticks);
  626. printf("%6.2f%% idle", 100.0 * idleticks / total_ticks);
  627. #define NEWLINE \
  628. do \
  629. { \
  630. printf("\n"); \
  631. if (--maxlines <= 0) \
  632. { \
  633. return; \
  634. } \
  635. } while (0)
  636. NEWLINE;
  637. printf("CPU time displayed ('%c' to cycle): %s; ",
  638. TIMECYCLEKEY, cputimemodename(cputimemode));
  639. printf(" sort order ('%c' to cycle): %s", ORDERKEY, ordername(order));
  640. NEWLINE;
  641. NEWLINE;
  642. printf(" PID USERNAME PRI NICE SIZE STATE TIME CPU COMMAND");
  643. NEWLINE;
  644. for (p = 0; p < nprocs; p++)
  645. {
  646. struct proc *pr;
  647. int level = 0;
  648. pr = tick_procs[p].p;
  649. if ((pr->p_flags & IS_TASK) && pr->p_pid != KERNEL)
  650. {
  651. /* skip old kernel tasks as they don't run anymore */
  652. continue;
  653. }
  654. /* If we're in blocked verbose mode, indicate start of
  655. * blocked processes.
  656. */
  657. if (blockedverbose && (pr->p_flags & BLOCKED) && !blockedseen)
  658. {
  659. NEWLINE;
  660. printf("Blocked processes:");
  661. NEWLINE;
  662. blockedseen = 1;
  663. }
  664. print_proc(&tick_procs[p], total_ticks);
  665. NEWLINE;
  666. if (!blockedverbose)
  667. continue;
  668. /* Traverse dependency chain if blocked. */
  669. while (pr->p_flags & BLOCKED)
  670. {
  671. endpoint_t dep = NONE;
  672. struct tp *tpdep;
  673. level += 5;
  674. if ((dep = pr->p_blocked) == NONE)
  675. {
  676. printf("not blocked on a process");
  677. NEWLINE;
  678. break;
  679. }
  680. if (dep == ANY)
  681. break;
  682. tpdep = lookup(dep, tick_procs, nprocs);
  683. pr = tpdep->p;
  684. printf("%*s> ", level, "");
  685. print_proc(tpdep, total_ticks);
  686. NEWLINE;
  687. }
  688. }
  689. }
  690. u64_t cputicks(struct proc *p1, struct proc *p2, int timemode)
  691. {
  692. int i;
  693. u64_t t = 0;
  694. for (i = 0; i < CPUTIMENAMES; i++)
  695. {
  696. if (!CPUTIME(timemode, i))
  697. continue;
  698. if (p1->p_endpoint == p2->p_endpoint)
  699. {
  700. t = t + p2->p_cpucycles[i] - p1->p_cpucycles[i];
  701. }
  702. else
  703. {
  704. t = t + p2->p_cpucycles[i];
  705. }
  706. }
  707. return t;
  708. }
  709. char *cputimemodename(int cputimemode)
  710. {
  711. static char name[100];
  712. int i;
  713. name[0] = '\0';
  714. for (i = 0; i < CPUTIMENAMES; i++)
  715. {
  716. if (CPUTIME(cputimemode, i))
  717. {
  718. assert(strlen(name) +
  719. strlen(cputimenames[i]) <
  720. sizeof(name));
  721. strcat(name, cputimenames[i]);
  722. strcat(name, " ");
  723. }
  724. }
  725. return name;
  726. }
  727. void print_proc(struct tp *tp, u64_t total_ticks)
  728. {
  729. int euid = 0;
  730. static struct passwd *who = NULL;
  731. static int last_who = -1;
  732. char *name = "";
  733. int ticks;
  734. struct proc *pr = tp->p;
  735. printf("%5d ", pr->p_pid);
  736. euid = pr->p_effuid;
  737. name = pr->p_name;
  738. if (last_who != euid || !who)
  739. {
  740. who = getpwuid(euid);
  741. last_who = euid;
  742. }
  743. if (who && who->pw_name)
  744. printf("%-8s ", who->pw_name);
  745. else if (!(pr->p_flags & IS_TASK))
  746. printf("%8d ", pr->p_effuid);
  747. else
  748. printf(" ");
  749. printf(" %2d ", pr->p_priority);
  750. if (!(pr->p_flags & IS_TASK))
  751. {
  752. printf(" %3d ", pr->p_nice);
  753. }
  754. else
  755. printf(" ");
  756. printf("%6ldK", (pr->p_memory + 512) / 1024);
  757. printf("%6s", (pr->p_flags & BLOCKED) ? "" : "RUN");
  758. ticks = pr->p_user_time;
  759. printf(" %3u:%02u ", (ticks / system_hz / 60), (ticks / system_hz) % 60);
  760. printf("%6.2f%% %s", 100.0 * tp->ticks / total_ticks, name);
  761. }
  762. struct tp *lookup(endpoint_t who, struct tp *tptab, int np)
  763. {
  764. int t;
  765. for (t = 0; t < np; t++)
  766. if (who == tptab[t].p->p_endpoint)
  767. return &tptab[t];
  768. fprintf(stderr, "lookup: tp %d (0x%x) not found.\n", who, who);
  769. abort();
  770. return NULL;
  771. }