...
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
читает из программного канала или файла, их входные потоки могут мешать друг другу:
$ cat /etc/passwd | p -1
root:3d.fHR5KoB.3s:0:l:S.User:/:!ed
Вызвать ed из p
?
ed читает /etc/passwd
!
… запутывается и завершается
Для решения этой проблемы необходимо знать, как управлять процессами в UNIX, о чем речь пойдет в разд. 7.4. Пока же примите к сведению, что использование стандартной библиотечной функции system
может создать неприятности, однако ttyin
работает правильно, если компилируется с версией system
, описанной в гл. 7.
Итак, мы написали две программы vis
и p
, которые можно считать вариантами cat
с некоторыми "украшениями". Может быть, им следует быть частью cat
, доступной с помощью флагов -v
и -р
? Вопрос о том, писать ли новую программу или добавлять какие-то средства к старой, возникает всегда, как только у людей появляются новые идеи. Мы не можем со всей определенностью ответить на данный вопрос, но приведем здесь некоторые принципы, которые, возможно, вам помогут.
Основной принцип состоит в том, что программе следует выполнять только свою основную работу. Если у нее появляется слишком много функций, она становится большой, медленной, ее трудно сопровождать и использовать. В самом деле, ряд свойств часто остается невостребованным, поскольку пользователи никак не могут запомнить флаги.
Поэтому cat
и vis
совмещать не рекомендуется. Если cat
просто копирует входной поток без изменений, то vis
его трансформирует. Соединение их дает программу с двумя разными функциями. Это очевидно также для cat
и p
: cat
предназначена для быстрого эффективного копирования страниц, p
для их "перелистывания". Кроме того, p
преобразует выходной поток. Каждый 22-й символ перевода строки пропускается. Три отдельные программы представляются в таком случае правильным решением.
Упражнение 6.6
Работает ли p нормально, если pagesize
не является положительным?
Упражнение 6.7
Что еще можно было бы сделать с p
? Оцените и реализуйте (если оно вам подходит) свойство вновь выводить части ранее введенного текста. (Это дополнительное средство нам очень нравится.) Добавьте возможность выводить неполное содержимое экрана после каждой паузы, а также просматривать текст вперед или назад по строкам, задаваемым номером или содержимым.
Упражнение 6.8
Используйте средства манипуляций файлами, встроенные в exec
shell
(см. справочное руководство по sh(1)
), чтобы фиксировать обращения к system
с терминала ttyin
.
Упражнение 6.9
Если вы забыли определить источник ввода для p
, то программа "молча" ожидает ввода с терминала. Стоит ли искать эту возможную ошибку? Если да, то как? Подсказка: isatty(3)
.
Версия pick
из гл. 5, несомненно, увеличивает возможности shell
. Версия на Си, приведенная ниже, в чем-то отличается от рассмотренной в гл. 5. Если эта версия имеет аргументы, то они обрабатываются так же, как и ранее, но если определен единственный аргумент '-'
, pick
обрабатывает свой стандартный входной поток.
Читать дальше
Конец ознакомительного отрывка
Купить книгу