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

Роббинс Арнольд

Шрифт:

Как

read
, так и
write
могут переместить меньше байтов, чем запрошено. Код приложения (т.е. ваш код) всегда должен учитывать это.

4.4.4. Пример: Unix

cat

Как и было обещано, вот версия cat V7 [47] . Она начинается с проверки опций,

cat
V7 принимает единственную опцию,
– u
, для осуществления небуферированного вывода.

Общая структура сходна с той, которую мы видели ранее; программа перечисляет файлы, указанные в аргументах командной строки и читает каждый файл, по одному символу за раз, посылая этот символ в стандартный вывод. В отличие от нашей версии, она использует возможности

<stdio.h>
. Во многих случаях код, использующий стандартную библиотеку ввода/вывода, проще читать и писать, поскольку все проблемы с буферами скрыты библиотекой.

47

См.

/usr/src/cmd/cat.c
в дистрибутиве V7. Программа без изменений компилируется для GNU/Linux. — Примеч. автора.

1 /*

2 * Объединение файлов.

3 */

4

5 #include <stdio.h>

6 #include <sys/types.h>

7 #include <sys/stat.h>

8

9 char stdbuf[BUFSIZ];

10

11 main(argc, argv) /* int main(int argc, char **argv) */

12 char **argv;

13 {

14 int fflg = 0;

15 register FILE *fi;

16 register c;

17 int dev, ino = -1;

18 struct stat statb;

19

20 setbuf(stdout, stdbuf);

21 for( ; argc>1 && argv[1][0] == '-'; argc--, argv++) {

22 switch(argv[1][1]) { /* Обработка опций */

23 case 0:

24 break;

25 case 'u':

26 setbuf(stdout, (char*)NULL);

27 continue;

28 }

29 break;

30 }

31 fstat(fileno(stdout), &statb); /* Строки 31-36 объясняются в главе 5 */

32 statb.st_mode &= S_IFMT;

33 if (statb.st_mode != S_IFCHR && statb.st_mode != S_IPBLK) {

34 dev = statb.st_dev;

35 ino = statb.st_ino;

36 }

37 if (argc < 2) {

38 argc = 2;

39 fflg++;

40 }

41 while (--argc > 0) { // Loop over files

42 if (fflg || (*++argv)[0] == '-' && (*argv)[1] == '\0')

43 fi = stdin;

44 else {

45 if ((fi = fopen(*argv, "r")) == NULL) {

46 fprintf(stderr, "cat: can't open %s\n", *argv);

47 continue;

48 }

49 }

50 fstat(fileno(fi), &statb); /* Строки 50-56 объясняются в главе 5 */

51 if (statb.st_dev == dev && statb.st_ino == ino) {

52 fprintf(stderr, "cat: input %s is output\n",

53 fflg ? "-" : *argv);

54 fclose(fi);

55 continue;

56 }

57 while ((c=getc(fi)) != EOF) /* Копировать содержимое в stdout */

58 putchar(с);

59 if (fi != stdin)

60 fclose(fi);

61 }

62 return(0);

63 }

Следует заметить, что программа всегда завершается успешно (строка 62); можно было написать ее так, чтобы отмечать ошибки и указывать их в возвращаемом значении

main
. (Механизм завершения процесса и значение различных кодов завершения обсуждаются в разделе 9.1.5.1 «Определение статуса завершения процесса».)

Код, работающий с

struct stat
и функцией
fstat
(строки 31–36 и 50–56), без сомнения, непрозрачен, поскольку мы еще не рассматривали эти функции и не будем рассматривать до следующей главы (Но обратите внимание на использование
fileno
в строке 50 для получения нижележащего дескриптора файла, связанного с переменными
FILE*
.) Идея в основе этого кода заключается в том, чтобы убедиться, что входной и выходной файлы не совпадают. Это предназначено для предотвращения бесконечного роста файла, в случае подобной команды:

  • Читать дальше
  • 1
  • ...
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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