470: if (sscanf(newJob.progs[0].argv[l], "%%%d", &jobNum) != 1)
471: fprintf(stderr, "%s: ошибочный аргумент '%s'\n",
472: newJob.progs[0].argv[0],
473: newJob.progs[0].argv[1]);
474: return 1;
475: }
476:
477: for (job = jobList->head; job; job = job->next)
478: if (job->jobId == jobNum) break;
479:
480: if (!job) {
481: fprintf(stderr, "%s: неизвестное задание %d\n",
482: newJob.progs[0].argv[0], jobNum);
483: return 1;
484: }
485:
486: if (* new Job.progs[0].argv [0] == 'f') {
487: /* Перевести это задание на передний план */
488:
489: if (tcsetpgrp(0, job->pgrp))
490: perror("tcsetpgrp");
491: jobList->fg = job;
492: }
493:
494: /* Перезапустить процессы в задании */
495: for (i = 0; i < job->numProgs; i++)
496: job->progs[i].isStopped = 0;
497:
498: kill (-job->pgrp, SIGCONT);
499:
500: job->stoppedProgs = 0;
501:
502: return 0;
503: }
Управление заданиями — последняя возможность примера ladsh
, необходимая для нормального функционирования. В нем до сих пор не хватает многих свойств, присущих регулярным оболочкам, например, переменные оболочки и окружения, однако он иллюстрирует все низкоуровневые задания, выполняемые оболочками. Полный исходный код окончательной версии ladsh
доступен в приложении Б.
Глава 16
Терминалы и псевдотерминалы
Устройства, предназначенные для интерактивного использования[107], обладают сходным интерфейсом, который был выведен десятилетия назад для последовательных терминалов TeleType и получил название tty. Интерфейс tty используется для доступа к последовательным терминалам, консолям, терминалам xterm, сетевым регистрационным именам и тому подобному.
Интерфейс tty прост концептуально, но сложен в реализации. Будучи гибким и мощным, он может записывать приложения, не знающие, сколько входных и выходных данных они получают, а также работать в сети, на локальном экране либо через модем. Приложения можно даже запускать без их ведома под управлением другой программы.
К сожалению, разработчикам Unix пришлось предпринять несколько попыток совершенствования интерфейса. Они оставили пользователям три разных интерфейса для соединения с устройствами tty. Интерфейсы sgtty (BSD) и termio (System V) теперь вытеснены интерфейсом termios (POSIX), который представляет собой супермножество команд интерфейса termio. Так как все существующие системы поддерживают интерфейс termios, и поскольку это самый мощный интерфейс, мы документируем только termios, а не ранние интерфейсы. (Ради поддержки унаследованного исходного кода Linux поддерживает termio, а также termios. Ранее он также ограниченно поддерживал интерфейс sgtty, но эта поддержка впоследствии была изъята, поскольку этот интерфейс никогда не был идеален, и в нем уже не было существенной потребности.)
Интерфейс termios должен поддерживать не только интерактивное использование программ, но и другие виды трафика. Последовательный канал, по которому осуществляется вход в сеть через модем, можно также использовать для дозвона через модем и связи с последовательным принтером либо другим специализированным элементом оборудования.
Устройство tty имеет два конца. Если рассуждать упрощенно, один конец присоединяется к программе, а второй — к аппаратному устройству. Это верно для последовательного порта; в данном случае драйвер последовательного устройства присоединяет последовательный порт (и, таким образом, терминал или модем) к оболочке, редактору или другой программе. Это также верно для консоли; драйвер консоли соединяет клавиатуру и экран с такими же типами программ. Но в некоторых случаях на каждом конце находится по программе; при этом один из концов занимает место оборудования.
Например, при сетевом подключении один конец устройства tty соединяется с программой, предоставляющей сетевое подключение, а второй — с оболочкой, редактором или другой потенциально интерактивной программой. Если программы находятся на каждом конце, вы должны ясно понимать, на каком конце эмулируется оборудование; при сетевом подключении к сети подключается аппаратная сторона.