OS2021_Project1.Shell
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

706 Zeilen
12 KiB

vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
vor 3 Jahren
  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 <termcap.h>
  10. #include <termios.h>
  11. #include <curses.h>
  12. #include <limits.h>
  13. #include <pwd.h>
  14. #include <assert.h>
  15. #include <sys/types.h>
  16. #include <sys/wait.h>
  17. #include <sys/stat.h>
  18. #include <sys/times.h>
  19. #include <sys/time.h>
  20. #include <sys/select.h>
  21. #include <minix/com.h>
  22. #include <minix/config.h>
  23. #include <minix/type.h>
  24. #include <minix/endpoint.h>
  25. #include <minix/const.h>
  26. #include <minix/u64.h>
  27. #include <minix/procfs.h>
  28. #include <paths.h>
  29. #include "yeeshell.h"
  30. /* record cmdline history */
  31. char *history[CMDLINE_HISTORY_MAX_QUANTITY];
  32. int cmdline_amount = 0;
  33. struct proc *proc = NULL, *prev_proc = NULL;
  34. int order = ORDER_CPU;
  35. int blockedverbose = 0;
  36. int nr_total = 0;
  37. int slot = 1;
  38. unsigned int nr_procs, nr_tasks;
  39. int main()
  40. {
  41. char *cmdline = NULL, *pwd = NULL;
  42. char *args[ARGS_MAX_QUANTITY];
  43. int status = 1;
  44. pwd = (char *)calloc(PATH_MAX_SIZE, sizeof(char));
  45. for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++)
  46. {
  47. history[i] = (char *)calloc(CMDLINE_MAX_SIZE, sizeof(char));
  48. }
  49. /* execute the shell's read, parse and execution loop */
  50. do
  51. {
  52. if (!getcwd(pwd, PATH_MAX_SIZE))
  53. {
  54. printf("yeeshell: The current path cannot be obtained!\n");
  55. exit(0);
  56. }
  57. printf("[root@yeeshell %s]# ", pwd);
  58. cmdline = readline();
  59. strcpy(history[cmdline_amount++], cmdline);
  60. status = execute(cmdline, args);
  61. free(cmdline);
  62. } while (status);
  63. for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++)
  64. {
  65. free(history[i]);
  66. }
  67. exit(EXIT_SUCCESS);
  68. }
  69. char *readline()
  70. {
  71. char *cmdline = NULL;
  72. ssize_t bufsize = 0;
  73. getline(&cmdline, &bufsize, stdin);
  74. return cmdline;
  75. }
  76. int parseline(char *cmdline, char **args)
  77. {
  78. static char array[CMDLINE_MAX_SIZE]; /* holds local copy of command line */
  79. char *buf = array; /* ptr that traverses command line */
  80. char *delim; /* points to first space delimiter */
  81. int argc; /* number of args */
  82. int bg; /* background job? */
  83. strcpy(buf, cmdline);
  84. buf[strlen(buf) - 1] = ' '; /* replace trailing '\n' with space */
  85. while (*buf && (*buf == ' ')) /* ignore leading spaces */
  86. {
  87. buf++;
  88. }
  89. /* Build the argv list */
  90. argc = 0;
  91. if (*buf == '\'')
  92. {
  93. buf++;
  94. delim = strchr(buf, '\'');
  95. }
  96. else
  97. {
  98. delim = strchr(buf, ' ');
  99. }
  100. while (delim)
  101. {
  102. args[argc++] = buf;
  103. *delim = '\0';
  104. buf = delim + 1;
  105. while (*buf && (*buf == ' ')) /* ignore spaces */
  106. {
  107. buf++;
  108. }
  109. if (*buf == '\'')
  110. {
  111. buf++;
  112. delim = strchr(buf, '\'');
  113. }
  114. else
  115. {
  116. delim = strchr(buf, ' ');
  117. }
  118. }
  119. args[argc] = NULL;
  120. if (argc == 0) /* ignore blank line */
  121. {
  122. return 1;
  123. }
  124. /* should the job run in the background? */
  125. if ((bg = (*args[argc - 1] == '&')) != 0)
  126. {
  127. args[--argc] = NULL;
  128. }
  129. return bg;
  130. }
  131. int check_redirect(char **args, char *redirect_filename, char **redirect_args)
  132. {
  133. int i = 0, j = 0, redirect_flag = REDIRECT_NO;
  134. while (args[i] != NULL)
  135. {
  136. if (!strcmp(args[i], ">"))
  137. {
  138. redirect_flag = REDIRECT_OUT;
  139. break;
  140. }
  141. else if (!strcmp(args[i], "<"))
  142. {
  143. redirect_flag = REDIRECT_IN;
  144. break;
  145. }
  146. i++;
  147. }
  148. if ((redirect_flag == 1) || (redirect_flag == 2))
  149. {
  150. strcpy(redirect_filename, args[i + 1]);
  151. for (j = 0; j < i; j++)
  152. {
  153. redirect_args[j] = args[j];
  154. }
  155. }
  156. return redirect_flag;
  157. }
  158. int do_redirect(int redirect_flag, char *redirect_filename, char **redirect_args)
  159. {
  160. pid_t pid;
  161. int fd = 1;
  162. if ((pid = fork()) == 0) /* Child process */
  163. {
  164. if (redirect_flag == 1) /* in or out? */
  165. {
  166. fd = open(redirect_filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR);
  167. close(1);
  168. dup(fd);
  169. }
  170. else if (redirect_flag == 2)
  171. {
  172. fd = open(redirect_filename, O_RDONLY, S_IRUSR);
  173. close(0);
  174. dup(fd);
  175. }
  176. if (execvp(redirect_args[0], redirect_args) <= 0)
  177. {
  178. printf("%s: Command not found\n", redirect_args[0]);
  179. exit(0);
  180. }
  181. close(fd);
  182. }
  183. else /* parent process */
  184. {
  185. waitpid(pid, NULL, 0);
  186. }
  187. return 1;
  188. }
  189. int check_pipe(char **args, char **pipe_arg_1, char **pipe_arg_2)
  190. {
  191. int pipe_flag = 0, i = 0, j = 0;
  192. while (args[i] != NULL)
  193. {
  194. if (!strcmp(args[i], "|"))
  195. {
  196. pipe_flag = 1;
  197. break;
  198. }
  199. pipe_arg_1[j++] = args[i++];
  200. }
  201. pipe_arg_1[j] = NULL;
  202. j = 0;
  203. i++;
  204. while (args[i] != NULL)
  205. {
  206. pipe_arg_2[j++] = args[i++];
  207. }
  208. pipe_arg_2[j] = NULL;
  209. return pipe_flag;
  210. }
  211. int do_pipe(char **pipe_arg_1, char **pipe_arg_2)
  212. {
  213. int fds[2];
  214. pipe(fds);
  215. pid_t prog_1, prog_2;
  216. if ((prog_1 = fork()) == 0) /* Child process 1 */
  217. {
  218. close(1);
  219. dup(fds[1]);
  220. close(fds[0]);
  221. close(fds[1]);
  222. if (execvp(pipe_arg_1[0], pipe_arg_1) <= 0)
  223. {
  224. printf("%s: Command not found\n", pipe_arg_1[0]);
  225. exit(0);
  226. }
  227. }
  228. if ((prog_2 = fork()) == 0) /* Child process 1 */
  229. {
  230. dup2(fds[0], 0);
  231. close(fds[0]);
  232. close(fds[1]);
  233. if (execvp(pipe_arg_2[0], pipe_arg_2) <= 0)
  234. {
  235. printf("%s: Command not found\n", pipe_arg_2[0]);
  236. exit(0);
  237. }
  238. }
  239. close(fds[0]);
  240. close(fds[1]);
  241. waitpid(prog_1, NULL, 0);
  242. waitpid(prog_2, NULL, 0);
  243. return 1;
  244. }
  245. int do_bg_fg(char **args, int bg)
  246. {
  247. pid_t pid;
  248. if ((pid = fork()) == 0)
  249. {
  250. if (execvp(args[0], args) <= 0)
  251. {
  252. printf("%s: Command not found\n", args[0]);
  253. exit(0);
  254. }
  255. }
  256. else
  257. {
  258. if (bg)
  259. {
  260. signal(SIGCHLD, SIG_IGN);
  261. }
  262. else
  263. {
  264. waitpid(pid, NULL, 0);
  265. }
  266. }
  267. return 1;
  268. }
  269. int execute(char *cmdline, char **args)
  270. {
  271. int bg = 0, i = 0, redirect_flag = 0, pipe_num = 0;
  272. pid_t pid;
  273. char *redirect_filename = NULL;
  274. char *redirect_args[ARGS_MAX_QUANTITY];
  275. char *pipe_arg_1[ARGS_MAX_QUANTITY];
  276. char *pipe_arg_2[ARGS_MAX_QUANTITY];
  277. redirect_filename = (char *)calloc(REDIRECT_FILENAME_MAX_SIZE, sizeof(char));
  278. memset(redirect_args, NULL, sizeof(redirect_args));
  279. bg = parseline(cmdline, args);
  280. redirect_flag = check_redirect(args, redirect_filename, redirect_args);
  281. pipe_num = check_pipe(args, pipe_arg_1, pipe_arg_2);
  282. if (args[0] == NULL)
  283. {
  284. return 1;
  285. }
  286. if (pipe_num == 0) /* no pipe */
  287. {
  288. if (!built_in(args)) /* built-in cmd? */
  289. {
  290. if (redirect_flag != 0) /* redirection? */
  291. {
  292. return do_redirect(redirect_flag, redirect_filename, redirect_args);
  293. }
  294. else
  295. {
  296. return do_bg_fg(args, bg);
  297. }
  298. }
  299. else
  300. {
  301. return 1;
  302. }
  303. }
  304. else
  305. {
  306. return do_pipe(pipe_arg_1, pipe_arg_2);
  307. }
  308. }
  309. int built_in(char **args)
  310. {
  311. if (!strcmp(args[0], "exit"))
  312. {
  313. exit(0);
  314. }
  315. else if (!strcmp(args[0], "cd"))
  316. {
  317. return builtin_cd(args);
  318. }
  319. else if (!strcmp(args[0], "history"))
  320. {
  321. return builtin_history(args);
  322. }
  323. else if (!strcmp(args[0], "mytop"))
  324. {
  325. return builtin_mytop();
  326. }
  327. else
  328. {
  329. return 0;
  330. }
  331. }
  332. int builtin_cd(char **args)
  333. {
  334. if (args[1] == NULL)
  335. {
  336. return 1;
  337. }
  338. else
  339. {
  340. if (chdir(args[1]) != 0)
  341. {
  342. perror("yeeshell");
  343. }
  344. return 1;
  345. }
  346. }
  347. int builtin_history(char **args)
  348. {
  349. int n = 0;
  350. if (args[1] == NULL)
  351. {
  352. n = cmdline_amount;
  353. }
  354. else
  355. {
  356. n = atoi(args[1]) < cmdline_amount ? atoi(args[1]) : cmdline_amount;
  357. }
  358. printf("ID\tCommandline\n");
  359. for (int i = 0; i < n; i++)
  360. {
  361. printf("%d\t%s\n", i + 1, history[i]);
  362. }
  363. return 1;
  364. }
  365. int builtin_mytop()
  366. {
  367. int cputimemode = 1;
  368. mytop_memory();
  369. getkinfo();
  370. get_procs();
  371. if (prev_proc == NULL)
  372. get_procs();
  373. print_procs(prev_proc, proc, cputimemode);
  374. return 1;
  375. }
  376. void mytop_memory()
  377. {
  378. FILE *fp = NULL;
  379. int pagesize;
  380. long total = 0, free = 0, cached = 0;
  381. if ((fp = fopen("/proc/meminfo", "r")) == NULL)
  382. {
  383. exit(0);
  384. }
  385. fscanf(fp, "%u %lu %lu %lu", &pagesize, &total, &free, &cached);
  386. fclose(fp);
  387. printf("memory(KBytes):\t%ld total\t%ld free\t%ld cached\n", (pagesize * total) / 1024, (pagesize * free) / 1024, (pagesize * cached) / 1024);
  388. return;
  389. }
  390. void get_procs()
  391. {
  392. struct proc *p;
  393. int i;
  394. p = prev_proc;
  395. prev_proc = proc;
  396. proc = p;
  397. if (proc == NULL)
  398. {
  399. proc = malloc(nr_total * sizeof(proc[0]));
  400. if (proc == NULL)
  401. {
  402. fprintf(stderr, "Out of memory!\n");
  403. exit(1);
  404. }
  405. }
  406. for (i = 0; i < nr_total; i++)
  407. {
  408. proc[i].p_flags = 0;
  409. }
  410. parse_dir();
  411. }
  412. void parse_dir()
  413. {
  414. DIR *p_dir;
  415. struct dirent *p_ent;
  416. pid_t pid;
  417. char *end;
  418. if ((p_dir = opendir("/proc")) == NULL)
  419. {
  420. perror("opendir on " _PATH_PROC);
  421. exit(1);
  422. }
  423. for (p_ent = readdir(p_dir); p_ent != NULL; p_ent = readdir(p_dir))
  424. {
  425. pid = strtol(p_ent->d_name, &end, 10);
  426. if (!end[0] && pid != 0)
  427. {
  428. parse_file(pid);
  429. }
  430. }
  431. closedir(p_dir);
  432. }
  433. void parse_file(pid_t pid)
  434. {
  435. char path[PATH_MAX], name[256], type, state;
  436. int version, endpt, effuid;
  437. unsigned long cycles_hi, cycles_lo;
  438. FILE *fp;
  439. struct proc *p;
  440. int i;
  441. sprintf(path, "/proc/%d/psinfo", pid);
  442. if ((fp = fopen(path, "r")) == NULL)
  443. {
  444. return;
  445. }
  446. if (fscanf(fp, "%d", &version) != 1)
  447. {
  448. fclose(fp);
  449. return;
  450. }
  451. if (version != PSINFO_VERSION)
  452. {
  453. fputs("procfs version mismatch!\n", stderr);
  454. exit(1);
  455. }
  456. if (fscanf(fp, " %c %d", &type, &endpt) != 2)
  457. {
  458. fclose(fp);
  459. return;
  460. }
  461. slot++;
  462. if (slot < 0 || slot >= nr_total)
  463. {
  464. fprintf(stderr, "top: unreasonable endpoint number %d\n", endpt);
  465. fclose(fp);
  466. return;
  467. }
  468. p = &proc[slot];
  469. if (type == TYPE_TASK)
  470. {
  471. p->p_flags |= IS_TASK;
  472. }
  473. else if (type == TYPE_SYSTEM)
  474. {
  475. p->p_flags |= IS_SYSTEM;
  476. }
  477. p->p_endpoint = endpt;
  478. p->p_pid = pid;
  479. if (fscanf(fp, " %255s %c %d %d %lu %*u %lu %lu",
  480. name, &state, &p->p_blocked, &p->p_priority,
  481. &p->p_user_time, &cycles_hi, &cycles_lo) != 7)
  482. {
  483. fclose(fp);
  484. return;
  485. }
  486. strncpy(p->p_name, name, sizeof(p->p_name) - 1);
  487. p->p_name[sizeof(p->p_name) - 1] = 0;
  488. if (state != STATE_RUN)
  489. {
  490. p->p_flags |= BLOCKED;
  491. }
  492. p->p_cpucycles[0] = make64(cycles_lo, cycles_hi);
  493. p->p_memory = 0L;
  494. if (!(p->p_flags & IS_TASK))
  495. {
  496. int j;
  497. if ((j = fscanf(fp, " %lu %*u %*u %*c %*d %*u %u %*u %d %*c %*d %*u",
  498. &p->p_memory, &effuid, &p->p_nice)) != 3)
  499. {
  500. fclose(fp);
  501. return;
  502. }
  503. p->p_effuid = effuid;
  504. }
  505. else
  506. p->p_effuid = 0;
  507. for (i = 1; i < CPUTIMENAMES; i++)
  508. {
  509. if (fscanf(fp, " %lu %lu",
  510. &cycles_hi, &cycles_lo) == 2)
  511. {
  512. p->p_cpucycles[i] = make64(cycles_lo, cycles_hi);
  513. }
  514. else
  515. {
  516. p->p_cpucycles[i] = 0;
  517. }
  518. }
  519. if ((p->p_flags & IS_TASK))
  520. {
  521. if (fscanf(fp, " %lu", &p->p_memory) != 1)
  522. {
  523. p->p_memory = 0;
  524. }
  525. }
  526. p->p_flags |= USED;
  527. fclose(fp);
  528. }
  529. void getkinfo()
  530. {
  531. FILE *fp;
  532. if ((fp = fopen("/proc/kinfo", "r")) == NULL)
  533. {
  534. fprintf(stderr, "opening " _PATH_PROC "kinfo failed\n");
  535. exit(1);
  536. }
  537. if (fscanf(fp, "%u %u", &nr_procs, &nr_tasks) != 2)
  538. {
  539. fprintf(stderr, "reading from " _PATH_PROC "kinfo failed\n");
  540. exit(1);
  541. }
  542. fclose(fp);
  543. nr_total = (int)(nr_procs + nr_tasks);
  544. }
  545. void print_procs(struct proc *proc1, struct proc *proc2, int cputimemode)
  546. {
  547. int p, nprocs;
  548. u64_t systemticks = 0;
  549. u64_t userticks = 0;
  550. u64_t total_ticks = 0;
  551. int blockedseen = 0;
  552. static struct tp *tick_procs = NULL;
  553. if (tick_procs == NULL)
  554. {
  555. tick_procs = malloc(nr_total * sizeof(tick_procs[0]));
  556. if (tick_procs == NULL)
  557. {
  558. fprintf(stderr, "Out of memory!\n");
  559. exit(1);
  560. }
  561. }
  562. for (p = nprocs = 0; p < nr_total; p++)
  563. {
  564. u64_t uticks;
  565. if (!(proc2[p].p_flags & USED))
  566. {
  567. continue;
  568. }
  569. tick_procs[nprocs].p = proc2 + p;
  570. tick_procs[nprocs].ticks = cputicks(&proc1[p], &proc2[p], cputimemode);
  571. uticks = cputicks(&proc1[p], &proc2[p], 1);
  572. total_ticks = total_ticks + uticks;
  573. if (!(proc2[p].p_flags & IS_TASK))
  574. {
  575. if (proc2[p].p_flags & IS_SYSTEM)
  576. {
  577. systemticks = systemticks + tick_procs[nprocs].ticks;
  578. }
  579. else
  580. {
  581. userticks = userticks + tick_procs[nprocs].ticks;
  582. }
  583. }
  584. nprocs++;
  585. }
  586. if (total_ticks == 0)
  587. {
  588. return;
  589. }
  590. printf("CPU states: %6.2f%% user\t", 100.0 * userticks / total_ticks);
  591. printf("%6.2f%% syst\t", 100.0 * systemticks / total_ticks);
  592. printf("%6.2f%% in total\n", 100.0 * (systemticks + userticks) / total_ticks);
  593. }
  594. u64_t cputicks(struct proc *p1, struct proc *p2, int timemode)
  595. {
  596. int i;
  597. u64_t t = 0;
  598. for (i = 0; i < CPUTIMENAMES; i++)
  599. {
  600. if (!CPUTIME(timemode, i))
  601. {
  602. continue;
  603. }
  604. if (p1->p_endpoint == p2->p_endpoint)
  605. {
  606. t = t + p2->p_cpucycles[i] - p1->p_cpucycles[i];
  607. }
  608. else
  609. {
  610. t = t + p2->p_cpucycles[i];
  611. }
  612. }
  613. return t;
  614. }