70: ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π·Π°Π΄Π°Π½ΠΈΡ, Π°ΡΡΠΎΡΠΈΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ Ρ Π½Π΅ΠΉ) ΠΈΠ»ΠΈ NULL, Π΅ΡΠ»ΠΈ
71: Π±ΠΎΠ»ΡΡΠ΅ Π½Π΅Ρ ΠΊΠΎΠΌΠ°Π½Π΄.*/
72: int parseCommand(char **commandPtr, struct job *job, int *isBg) {
73: char *command;
74: char *returnCommand = NULL;
75: char *src, *buf;
76: int argc = 0;
77: int done = 0;
78: int argvAlloced;
79: char quote = '\0';
80: int count;
81: struct childProgram *prog;
82:
83: /* ΠΡΠΎΠΏΡΡΡΠΈΡΡ Π²Π΅Π΄ΡΡΠΈΠ΅ ΠΏΡΠΎΠ±Π΅Π»Ρ */
84: while(**commandPtr && isspace(**commandPtr)) (*commandPtr)++;
85:
86: /* Π·Π΄Π΅ΡΡ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΠΏΡΡΡΡΠ΅ ΡΡΡΠΎΠΊΠΈ ΠΈ Π²Π΅Π΄ΡΡΠΈΠ΅ ΡΠΈΠΌΠ²ΠΎΠ»Ρ '#' */
87: if (!**commandPtr || (**commandPtr=='#')) {
88: job->numProgs = 0;
89: *commandPtr = NULL;
90: return 0;
91: }
92:
93: *isBg = 0;
94: job->numProgs = 1;
95: job->progs = malloc(sizeof(*job->progs));
96:
97: /* ΠΡ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠ»Π΅ΠΌΠ΅Π½ΡΡ argv Π² ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π²Π½ΡΡΡΠΈ ΡΡΡΠΎΠΊΠΈ.
98: ΠΠ°ΠΌΡΡΡ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅ΡΡΡ freeJob().
99:
100: ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠΈΡΡΠΎΠΉ ΠΏΠ°ΠΌΡΡΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π΄Π°Π»Π΅Π΅ ΠΈΠΌΠ΅ΡΡ Π΄Π΅Π»ΠΎ Ρ
101: NULL-Π·Π°Π²Π΅ΡΡΠ°ΡΡΠΈΠΌΠΈΡΡ Π²Π΅ΡΠ°ΠΌΠΈ ΠΈ Π΄Π΅Π»Π°Π΅Ρ Π²ΡΠ΅ ΠΎΡΡΠ°Π»ΡΠ½ΠΎΠ΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ
102: ΡΡΠ½Π΅Π΅ (ΠΊ ΡΠΎΠΌΡ ΠΆΠ΅, ΡΡΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅Ρ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ) */
103: job->cmdBuf = command = calloc(1, strlen(*commandPtr) + 1);
104: job->text = NULL;
105:
106: prog = job->progs;
107:
108: argvAlloced = 5;
109: prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
110: prog->argv[0] = job->cmdBuf;
111:
112: buf = command;
113: src = *commandPtr;
114: while (*src && !done) {
115: if (quote==*src) {
116: quote='\0';
117: } else if (quote) {
118: if (*src == '\\') {
119: src++;
120: if (!*src) {
121: fprintf(stderr,
122: "ΠΎΠΆΠΈΠ΄Π°Π΅ΡΡΡ ΡΠΈΠΌΠ²ΠΎΠ» ΠΏΠΎΡΠ»Π΅\\\n");
123: freeJob(job);
124: return 1;
125: }
126:
127: /* Π² ΠΎΠ±ΠΎΠ»ΠΎΡΠΊΠ΅, "\'" Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΏΠΎΡΠΎΠ΄ΠΈΡΡ \' */
128: if (*src != quote) *buf++='\\';
129: }
130: *buf++ = *src;
131: } else if (isspace(*src)) {
132: if (*prog->argv[argc]) {
133: buf++, argc++;
134: /* +1 Π·Π΄Π΅ΡΡ ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΌΠ΅ΡΡΠΎ Π΄Π»Ρ NULL,
135: ΠΊΠΎΡΠΎΡΡΠΌ Π·Π°Π²Π΅ΡΡΠ°Π΅ΡΡΡ argv */
136: if ((argc+1) == argvAlloced) {
137: argvAlloced += 5;
138: prog->argv = realloc(prog->argv,
139: sizeof(*prog->argv)*argvAlloced);
140: }
141: prog->argv[argc]=buf;
142: }
143: } else switch(*src) {
144: case '"':
145: case '\'':
146: quote = *src;
147: break;
148:
149: case '#' : /* ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ */
150: done=1;
151: break;
152:
153: case '&': /* ΡΠΎΠ½ΠΎΠ²ΡΠΉ ΡΠ΅ΠΆΠΈΠΌ */
154: *isBg = 1;
155: case ';': /* ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ */
156: done=1;
157: return Command = *commandPtr + (src - *commandPtr) + 1;
158: break;
159:
160: case '\\' :
161: src++;
162: if (!*src) {
163: freeJob(job);
164: fprintf(stderr, "ΠΎΠΆΠΈΠ΄Π°Π΅ΡΡΡ ΡΠΈΠΌΠ²ΠΎΠ» ΠΏΠΎΡΠ»Π΅ \\\n");
165: return 1;
166: }
167: /* Π΄Π²ΠΈΠ³Π°ΡΡΡΡ Π΄Π°Π»ΡΡΠ΅ */
168: default:
169: *buf++=*src;
170: }
171:
172: src++;
173: }
174:
175: if (*prog->argv[argc]) {
176: argc++;
177: }
178: if (!argc) {
179: freeJob(job);
180: return 0;
181: }
182: prog->argv[argc]=NULL;
183:
184: if (!returnCommand) {
185: job->text = malloc(strlen(*commandPtr) + 1);
186: strcpy(job->text,*commandPtr);
187: } else {
188: /* ΠΡΠΎ ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ Ρ Π²ΠΎΡΡΠΎΠ²ΡΠ΅ ΠΏΡΠΎΠ±Π΅Π»Ρ, ΡΡΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΈΠ·Π»ΠΈΡΠ½Π΅ */
189:
190: count = returnCommand - *commandPtr;
191: job->text = malloc(count + 1);
192: strncpy(job->text,*commandPtr,count);
193: job->text[count] = '\0';
194: }
195:
196: *commandPtr = returnCommand;
197:
198: return 0;
199: }
200:
201: int runCommand(struct jobnewJob, struct jobSet *jobList,
202: intinBg) {
203: struct job *job;
204:
205: /* ΠΎΠ±Ρ ΠΎΠ΄Π½ΠΎΠΉ ΠΏΡΡΡ "Π²ΡΡΡΠ½ΡΡ" - ΠΌΡ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ fork(),
206: ΠΏΠΎΡΡΠΎΠΌΡ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π»Π΅Π³ΠΊΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΡΠΎΠ½ΠΎΠ²ΡΠΉ ΡΠ΅ΠΆΠΈΠΌ */
207: if (!strcmp(newJob.progs[0].argv[0], "exit")) {
208: /* ΡΡΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π²Π΅ΡΠ½ΡΡΡ ΡΠ΅Π°Π»ΡΠ½ΡΠΉ ΠΊΠΎΠ΄ Π²ΠΎΠ·Π²ΡΠ°ΡΠ° */
209: exit(0);
210: } else if(!strcmp(newJob.progs[0].argv[0], "jobs")) {
211: for (job = jobList->head; job; job = job->next)
212: printf(JOB_STATUS_FORMAT, job->jobId, "Π Π°Π±ΠΎΡΠ°Ρ",
213: job->text);
214: return 0;
215: }
216:
217: /* Ρ Π½Π°Ρ ΠΏΠΎΠΊΠ° ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π½Π° Π΄ΠΎΡΠ΅ΡΠ½Π΅Π΅ Π·Π°Π΄Π°Π½ΠΈΠ΅,
218: ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΠΏΡΠΎΡΡΠΎ */
219: if (!(newJob.progs[0].pid = fork())) {
220: execvp(newJob.progs[0].argv[0],newJob.progs[0].argv);
221: fprintf(stderr, "exec() Π΄Π»Ρ %s ΠΏΠΎΡΠ΅ΡΠΏΠ΅Π»Π° Π½Π΅ΡΠ΄Π°ΡΡ: %s\n",
222: newJob.progs[0].argv[0],
223: strerror(errno));
224: exit(1);
225: }
226:
227: /* ΠΏΠΎΠΌΠ΅ΡΡΠΈΡΡ Π΄ΠΎΡΠ΅ΡΠ½ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π² ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ Π³ΡΡΠΏΠΏΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ² */
228: setpgid(newJob.progs[0].pid,newJob.progs[0].pid);
229:
230: newJob.pgrp = newJob.progs[0].pid;
231:
232: /* Π½Π°ΠΉΡΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π΄Π»Ρ Π·Π°Π΄Π°Π½ΠΈΡ */
233: newJob.jobld = 1;
234: for (job = jobList->head; job; job = job->next)
235: if (job->jobId >= newJob.jobId)
236: newJob.jobId = job->jobId+1;
237:
238: /* Π·Π°Π΄Π°Π½ΠΈΠ΅ Π΄Π»Ρ ΡΠΏΠΈΡΠΊΠ° Π·Π°Π΄Π°Π½ΠΈΠΉ */
239: if (!jobList->head) {
240: job = jobList->head = malloc(sizeof(*job));
241: } else {
242: for (job = jobList->head; job->next; job = job->next);
243: job->next = malloc(sizeof(*job));
244: job = job->next;
245: }
246:
247: *job = newJob;
248: job->next = NULL;
249: job->runningProgs = job->numProgs;
250:
251: if (inBg) {
252: /* ΠΌΡ Π½Π΅ ΠΆΠ΄Π΅ΠΌ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ ΡΠΎΠ½ΠΎΠ²ΡΡ Π·Π°Π΄Π°Π½ΠΈΠΉ - Π΄ΠΎΠ±Π°Π²ΠΈΡΡ
253: Π² ΡΠΏΠΈΡΠΎΠΊ ΡΠΎΠ½ΠΎΠ²ΡΡ Π·Π°Π΄Π°Π½ΠΈΠΉ ΠΈ ΠΎΡΡΠ°Π²ΠΈΡΡ Π² ΠΏΠΎΠΊΠΎΠ΅ */
254:
255: printf("[%d]%d\n", job->jobId,
256: newJob.progs[newJob.numProgs-1].pid);
257: } else {
258: jobList->fg=job;
259:
260: /* ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΡΠΈΡΡ Π½ΠΎΠ²ΡΡ Π³ΡΡΠΏΠΏΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ² Π½Π° ΠΏΠ΅ΡΠ΅Π΄Π½ΠΈΠΉ ΠΏΠ»Π°Π½ */
261:
262: if (tcsetpgrp(0,newJob.pgrp))
263: perror("tcsetpgrp");
264: }
265:
266: return 0;
267: }
268:
269: void removeJob(struct jobSet *jobList, struct job *job) {
270: struct job *prevJob;
271:
272: freeJob(job);
273: if (job == jobList->head) {
274: jobList->head=job->next;
275: } else {
276: prevJob = jobList->head;
277: while (prevJob->next != job) prevJob = prevJob->next;
278: prevJob->next=job->next;
279: }
280:
281: free(job);
282: }
283:
284: /* ΠΡΠΎΠ²Π΅ΡΠΈΡΡ, Π·Π°Π²Π΅ΡΡΠΈΠ»ΡΡ Π»ΠΈ ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ ΠΈΠ· ΡΠΎΠ½ΠΎΠ²ΡΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ² -
285: Π΅ΡΠ»ΠΈ Π΄Π°, Π²ΡΡΡΠ½ΠΈΡΡ, ΠΏΠΎΡΠ΅ΠΌΡ ΠΈ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ, Π·Π°Π²Π΅ΡΡΠΈΠ»ΠΎΡΡ Π»ΠΈ Π·Π°Π΄Π°Π½ΠΈΠ΅ */
286: void checkJobs(struct jobSet *jobList) {
287: struct job *job;
288: pid_t childpid;
289: int status;
290: int progNum;
291:
292: while ((childpid = waitpid(-1, &status, WNOHANG))>0) {
293: for (job = jobList->head;job;job = job->next) {
294: progNum = 0;
295: while (progNum<job->numProgs &&
296: job->progs[progNum].pid != childpid)
297: progNum++;
298: if (progNum<job->numProgs) break;
299: }
300:
301: job->runningProgs--;
302: job->progs[progNum].pid = 0;
303:
304: if (!job->runningProgs) {
305: printf(JOB_STATUS_FORMAT,job->jobId,"ΠΠΎΡΠΎΠ²ΠΎ",
306: job->text);
307: removeJob(jobList, job);
308: }
309: }
310:
311: if (childpid == -1 && errno!= ECHILD)
312: perror("waitpid");
313: }
314:
315: int main(int argc, const char **argv) {
316: char command [MAX_COMMAND_LEN + 1];
317: char *nextCommand = NULL;
318: struct jobSetjobList = {NULL, NULL};
319: struct jobnewJob;
320: FILE *input = stdin;
321: int i;
322: int status;
323: int inBg;
324:
325: if (argc>2) {
326: fprintf(stderr,"ΠΠ΅ΠΏΡΠ΅Π΄Π²ΠΈΠ΄Π΅Π½Π½ΡΠ΅ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ; ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅: ladsh1 "
327: "<ΠΊΠΎΠΌΠ°Π½Π΄Ρ>\n");
328: exit(1);