3: #define _GNU_SOURCE
4:
5: #include <ctype.h>
6: #include <errno.h>
7: #include <fcntl.h>
8: #include <glob.h>
9: #include <signal.h>
10: #include <stdio.h>
11: #include <stdlib.h>
12: #include <string.h>
13: #include <sys/ioctl.h>
14: #include <sys/wait.h>
15: #include <unistd.h>
16:
17: #define MAX_COMMAND_LEN 250 /* максимальная длина одной
18: командной строки */
19: #define JOB_STATUS_FORMAT '[%d] %-22s %.40s
'
20:
21: struct jobSet {
22: struct job * head; /* заголовок списка выполняющихся заданий */
23: struct job * fg; /* текущее высокоприоритетное задание */
24: };
25:
26: enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
27: REDIRECT_APPEND };
28:
29: struct redirectionSpecifier {
30: enum redirectionType type; /* тип переадресации */
31: int fd; /* переадресация fd */
32: char * filename; /* файл, в который будет переадресовано fd */
33: };
34:
35: struct childProgram {
36: pid_t pid; /* 0 в случае выхода */
37: char ** argv; /* имя программы и аргументы */
38: int numRedirections; /* элементы в массиве переадресации */
39: struct redirectionSpecifier* redirections; /* переадресации ввода-вывода */
40: glob_t globResult; /* результат универсализации параметра */
41: int freeGlob; /* нужно ли освобождать globResult? */
42: int isStopped; /* выполняется ли в данный момент программа? */
43: };
44:
45: struct job {
46: int jobId; /* номер задания */
47: int numProgs; /* количество программ в задании */
48: int runningProgs; /* количество выполняющихся программ */
49: char * text; /* имя задания */
50: char * cmdBuf; /* буфер, на который ссылаются различные массивы argv */
51: pid_t pgrp; /* идентификатор группы процесса для задания */
52: struct childProgram* progs; /* массив программ в задании */
53: struct job* next; /* для отслеживания фоновых команд */
54: int stoppedProgs; /* количество активных, но приостановленных программ */
55: };
56:
57: void freeJob (struct job * cmd) {
58: int i;
59:
60: for (i = 0; i <cmd->numProgs; i++) {
61: free(cmd->progs[i].argv);
62: if (cmd->progs[i].redirections)
63: free(cmd->progs[i].redirections);
64: if (cmd->progs[i].freeGlob)
65: globfree(&cmd->progs[i].globResult);
66: }
67: free(cmd->progs);
68: if (cmd->text) free(cmd->text);
69: free(cmd->cmdBuf);
70: }
71:
72: int getCommand(FILE * source, char * command) {
73: if (source == stdin) {
74: printf('# ');
75: fflush(stdout);
76: }
77:
78: if (!fgets(command, MAX_COMMAND_LEN, source)) {
79: if (source == stdin) printf('
');
80: return 1;
81: }
82:
83: /* удаление хвостового символа новой строки */
84: command[strlen(command) - 1] = ' ';
85:
86: return 0;
87: }
88:
89: void globLastArgument(struct childProgram * prog, int * argcPtr,
90: int * argcAllocedPtr) {
91: int argc = *argcPtr;
92: int argcAlloced = *argcAllocedPtr;
93: int rc;
94: int flags;
95: int i;
96: char * src, * dst;
98: if (argc>1) { /* cmd->globResult уже инициализирован */