Троан Эрик В.
Шрифт:
10.7. Введение в
ladsh
Чтобы помочь проиллюстрировать идеи, обсуждаемые в нашей книге, на протяжении последующих разделов книги мы разработаем подмножество командной оболочки Unix. В конечном итоге наша оболочка будет поддерживать следующее.
• Простые встроенные команды.
• Запуск внешних команд.
• Перенаправление ввода-вывода (
>
, |
и так далее). • Управление заданиями.
Полный исходный текст окончательной версии этой оболочки,
ladsh4.с
, представлен в приложении Б. По мере добавления в ladsh
новых средств, изменения исходного текста описываются в тексте книги. Чтобы уменьшить количество изменений, которые мы вносим между версиями, некоторые ранние версии несколько более сложны, чем было бы нужно. Эти небольшие усложнения, однако, далее в книге упрощают разработку оболочки, поэтому будьте терпеливы. Просто пока поверьте, что эти фрагменты кода необходимы; все они будут объяснены позднее. 10.7.1. Запуск внешних программ с помощью ladsh
Вот первая (и самая простая) версия
ladsh
, называемая ladsh1
. 1: /*ladsh1.c*/
2:
3: #include <ctype.h>
4: #include <errno.h>
5: #include <fcntl.h>
6: #include <signal.h>
7: #include <stdio.h>
8: #include <stdlib.h>
9: #include <string.h>
10: #include <sys/ioctl.h>
11: #include <sys/wait.h>
12: #include <unistd.h>
13:
14: #define MAX_COMMAND_LEN 250 /* максимальная длина отдельной
15: командной строки */
16: #define JOB_STATUS_FORMAT "[%d]%-22s%.40s\n"
17:
18: struct jobSet {
19: struct job *head; /* заголовок списка запущенных заданий */
20: struct job *fg; /* текущее задание переднего плана */
21: };
22:
23: struct childProgram {
24: pid_t Pid; /* 0 на выходе */
25: char **argv; /* имя программы с аргументами */
26: };
27:
28: struct job {
29: int job Id; /* номер задания */
30: int numProgs; /* общее кол-во программ в задании */
31: int runningProgs; /* кол-во работающих программ */
32: char *text; /* имя задания */
33: char *cmdBuf; /* буфер различных argv */
34: pid_t pgrp; /* идентификатор группы процессов задания */
35: struct childProgram *progs; /* массив программ в задании */
36: struct job *next; /* для слежения за фоновыми программами */
37: };
38:
39: void freeJob(struct job *cmd) {
40: int i;
41:
42: for (i=0; i<cmd->numProgs; i++) {
43: free (cmd->progs[i].argv);
44: }
45: free(cmd->progs);
46: if (cmd->text) free(cmd->text);
47: free(cmd->cmdBuf);
48: }
49:
50: int getCommand(FILE *source, char *command) {
51: if (source == stdin) {
52: printf("#");
53: fflush(stdout);
54: }
55:
56: if (!fgets(command, MAX_COMMAND_LEN, source)) {
57: if (source==stdin) printf("\n");
58: return 1;
59: }
60:
61: /* удалить завершающий перевод строки */
62: command[strlen(command) - 1] = '\0';
63:
64: return 0;
65: }
66:
67: /* Возвратить cmd->numProgs как 0, если нет никаких команд (то есть пустая
68: строка). Если найдена правильная команда, commandPtr устанавливается в
69: указатель на начало следующей команды (если исходная команда имеет более