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.

940 lines
18 KiB

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