Вход/Регистрация
UNIX — универсальная среда программирования
вернуться

Керниган Брайан Уилсон

Шрифт:

else {

buf[strlen(buf)-1] = '\0';

fputs(buf, stdout);

fflush(stdout);

ttyin;

lines = 0;

}

}

Мы использовали здесь

BUFSIZ
, который определен в
<stdio.h>
как размер буфера входного потока. Функция
fgets(buf, size, fp)
выбирает следующую строку входного потока из
fp
до символа перевода строки (включая его) в буфер и добавляет завершающий символ
\0
. Копируется на более
size - 1
символов. По достижении конца файла возвращается
NULL
. (Конструкция
fgets
оставляет желать лучшего: она возвращает
buf
вместо счетчика символов и, кроме того, выдает предупреждение о том, что входная строка была слишком длинной. Символы не потеряны, но вы должны взглянуть на
buf
, чтобы понять, что в самом деле случилось.)

Функция

strlen
возвращает длину строки, поэтому мы можем отбросить завершающий символ перевода строки последней входной строки. После вызова
fputs(buf, fp)
строка
buf
записана в файл
fp
. При вызове
fflush
в конце страницы происходит вывод буферизованного выходного текста.

Считывание ответа пользователя в конце каждой страницы возложено на функцию

ttyin
. Функция
ttyin
не может читать стандартный входной поток, тогда как
p
должна выполняться, даже если входной поток поступает из файла или конвейера. Чтобы справиться с этим, программа открывает файл
/dev/tty
, которому поставлен в соответствие пользовательский терминал при любом переключении стандартного входного потока. Приведенная ниже функция
ttyin
возвращает первую букву ответа, но здесь это свойство не используется.

ttyin /* process response from /dev/tty (version 1) */

{

 char buf[BUFSIZ];

 FILE *efopen;

 static FILE *tty = NULL;

 if (tty == NULL)

tty = efopen("/dev/tty", "r");

 if (fgets(buf, BUFSIZ, tty) == NULL || buf[0] == 'q')

exit(0);

 else /* ordinary line */

return buf[0];

}

Указатель на файл

devtty
описан как статический, так что его значение сохраняется от одного вызова
ttyin
до другого; файл
/dev/tty
открывается только при первом вызове.

Очевидно, есть дополнительные средства, которые без особых усилий можно ввести в

p
, однако наша первая версия этой программы только печатает 22 строки и ждет следующей порции. Прошло немало времени, прежде чем в нее были добавлены другие средства, но в настоящее время ими мало кто пользуется. В частности, весьма простое дополнение ввод переменной
pagesize
для хранения числа строк на странице. Значение переменной можно установить из командной строки

$ p -n...

Она печатает порции по

n
строк. Для этого требуется лишь добавить несколько знакомых вам операторов в начале
main
:

/* p: print input in chunks (version 2) */

...

int i, pagesize = PAGESIZE;

progname = argv[0];

if (argc > 1 && argv[1][0] == '-') {

 pagesize = atoi(&argv[1][1]);

 argc--;

 argv++;

}

Функция

atoi
превращает строку символов в целое число (см. справочное руководство по
atoi(3)
).

Еще одно средство временно остановить вывод на экран в конце каждой страницы, чтобы выполнить какую-либо иную команду. По аналогии с

ed
и многими другими программами, если пользователь печатает строку, начинающуюся восклицательным знаком, остальная часть строки воспринимается как команда и передается
shell
для выполнения. Данное средство также тривиально, поскольку для этой цели предусмотрена функция
system(3)
, речь о которой пойдет ниже. Модифицированная версия
ttyin
такова:

ttyin /* process response from /dev/tty (version 2) */

{

 char buf[BUFSIZ];

 FILE *efopen;

 static FILE *tty = NULL;

 if (tty == NULL)

tty = efopen("/dev/tty", "r");

 for (;;) {

if (fgets(buf,BUFSIZ,tty) == NULL || buf[0] == 'q')

exit(0);

else if (buf[0] == '!') {

system(buf+1); /* BUG here */

printf("!\n");

else /* ordinary line */

return buf[0];

 }

}

К сожалению, эта версия

ttyin
имеет серьезный недостаток. Команда, запущенная с помощью
system
, получает стандартный входной поток от
p
, так что если
p
читает из программного канала или файла, их входные потоки могут мешать друг другу:

  • Читать дальше
  • 1
  • ...
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: