низкой плотностью записи. Если должна быть выполнена команда монтиро-
вания, переменная DIR содержит каталог. Если выполняется размонтирова-
ние, значение переменной DIR равно нулю.


    ЗАМЕЧАНИЕ ПО ВОПРОСУ БЕЗОПАСНОСТИ



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

# chown root /etc/mount <- делает пользователя root владельцем
модуля /etc/mount
# chmod 4511 /etc/mount и дает возможность выполнять команду mount
всем пользователям

# chown root /etc/umount <- делает то же самое для команды
# chmod 4511 /etc/umount размонтирования

Эти команды облегчают всем пользователям работу с гибким диском,
но одновременно открывают огромную дыру в защите системы. Если кто-ли-
бо уже проложил тропинку прав доступа на гибкий диск (см. главу 9), то
монтирование файловой системы продолжит эту тропинку в главную систему
и позволит такому пользователю стать суперпользователем всей системы в
целом просто с гибкого диска!


--------------------------------------------------------------
ИМЯ: mntlook
--------------------------------------------------------------
mntlook Поиск файловых систем на устройствах


    НАЗНАЧЕНИЕ



Просмотр всех файлов дисковых устройств и обнаружение всех файло-
вых систем, включая немонтированные.


    ФОРМАТ ВЫЗОВА



mntlook


    ПРИМЕР ВЫЗОВА



mntlook /dev/hd*

Поиск файловых систем на всех жестких дисках


    ТЕКСТ ПРОГРАММЫ



1 static char id[] =
"@(#) mntlook v1.0 Look for mounts Author: Russ Sage";
Поиск файловых систем

3 #include
4 #include
5 #include
6 #include
7 #include

9 #define BSIZ 512

11 main(argc,argv)
12 int argc;
13 char *argv[];
14 {
15 struct filsys sb;
16 int d, dev;
17 char buf[BSIZ];

19 for (d = 1; d < argc; d++)
20 {
21 if (argv[d][0] == '-')
22 {
23 printf("mntlook: invalid argument %s\n", argv[d]);
24 printf("usage: mntlook device [device ...]\n");
25 continue;
26 }
27 if ((dev = open(argv[d],O_RDONLY)) < 0)
28 {
29 sprintf(buf, "cannot open %s",argv[d]);
невозможно открыть
30 perror(buf);
31 continue;
32 }

34 /* throw away first block */
обойти первый блок
35 if (read(dev, &sb, sizeof(sb)) == -1)
36 {
37 perror("cannot read block 0");
не читается блок 0
38 continue;
39 }

41 /* block 1 is the superblock */
блок 1 является суперблоком
42 if (read(dev, &sb, sizeof(sb)) == -1)
43 {
44 perror("cannot read block 1");
не читается блок 1
45 continue;
46 }

48 if (sb.s_magic == S_S3MAGIC)
49 {
50 printf("\nDEV: %s --> VALID file system\n",argv[d]);
51 printf("filsys: %s\n",sb.s_fname);
52 printf("pack : %s\n",sb.s_fpack);
53 printf("type : %s byte block\n",
54 (sb.s_type == S_B512) ? "512" : "1024");
55 printf("magic : %lx\n",sb.s_magic);
56 }

58 close(dev);
59 }
60 }


ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖНА ПРОГРАММА mntlook?

Файловые системы являются сердцевиной системы UNIX. Сама система
не существует вне файловой системы, а расширенные возможности системы
обеспечиваются файловой системой.

Даже несмотря на то, что файловые системы настолько важны, UNIX
не имеет никаких средств для обнаружения файловых систем как таковых.
Не имеется даже средств, которые могли бы сообщить нам, какая информа-
ция находится в суперблоках.

Нам необходимо универсальное средство для работы с файловыми
системами. Оно должно обнаруживать и идентифицировать суперблоки, на-
ходящиеся на устройствах. Заметим, что операция открытия устройства
обычно требует наличия привилегий суперпользователя.


ЧТО ДЕЛАЕТ mntlook?

Программа mntlook предназначена для просмотра содержимого файлов
устройств и поиска суперблока. (Мы вкратце рассматривали суперблоки
ранее). Когда суперблок обнаружен, из него извлекается и выводится на
экран имя файловой системы, имя дискового пакета, используемый размер
блока и идентификационный "магический номер".

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

Давайте рассмотрим, каким образом файловые системы связаны с фи-
зическим носителем. К каждой машине подсоединено фиксированное число
периферийных устройств. Для работы со сменными носителями в UNIX реа-
лизована концепция монтированного и немонтированного файлового прост-
ранства. Но первым шагом является установка пакета дисков (или гибкого
диска) в дисковое устройство. После этого можно выполнять операции
чтения и записи на физических носителях, указывая определенные имена
устройств.

Монтирование представляет собой логическое действие, которое чи-
тает суперблок с пакета дисков и записывает его в память, где ядро
системы поддерживает свою версию суперблока. Периодически выполняется
запись версии, находящейся в памяти, обратно на диск, чтобы эти две
версии были по возможности одинаковыми. В System V это делает програм-
ма update, которая работает в фоновом режиме с момента загрузки систе-
мы.

Для обращения непосредственно к физическому носителю используются
такие команды, как, например, команда "od -c /dev /rfd0", которая дам-
пирует неструктурированный гибкий диск. Одной из команд, которые не-
посредственно помещают данные на устройство, является команда "cp file
/dev/rfd0". Область данных начинается с самого первого байта на гибком
диске. Такие данные несовместимы с командами tar, cpio или файловой
системой.

Для обращения к файловой системе используется команда "mount
/dev/fd0 /mnt". Начиная с этого момента, все обращения к данному уст-
ройству выполняются через каталог /mnt. Важно то, что непосредственный
доступ к файлу устройства является операцией более низкого уровня, чем
операции файловой системы, что позволяет прочитать информацию о су-
перблоке непосредственно с устройства.

Входной информацией для программы mntlook являются имена файлов
устройств. В командной строке нельзя указывать никакие опции. Имена
устройств могут быть как блочными, так и символьными. Для операции
чтения это не имеет никакого значения, если только у вас имеются права
чтения. Затем программа читает второй блок и проверяет "магическое
число", определяющее суперблок. Суперблок - это просто структура языка
Си, которая предопределена системой и хранится в файле filsys.h, что
указано в нашей программе оператором #include. Магическое число
представляет собой длинное целое, имеющее заранее определенное значе-
ние. Если элемент структуры, которая прочитана с диска, содержит это
число, то считается, что остальная часть структуры является корректны-
ми данными. Для каждой файловой системы имеется только одна структура
суперблока.

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

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


    ПРИМЕРЫ



1. $ mntlook /dev/hd13

Поиск суперблока на устройстве с именем hd13. Это имя указывает
устройство 1, третий раздел. Для просмотра разделов в среде XENIX нуж-
но запустить программу fdisk. Для System V нужно воспользоваться ко-
мандой iv.

2. $ mntlook /dev/fd0*

Поиск файловых систем на гибких дисках с любой плотностью записи,
находящихся в устройстве 0. Это снова пример для системы XENIX.

3. $ for DEV in /dev/*[fh]d*
> do
> echo "checking device: $DEV"
> mntlook $DEV
> done

Данный цикл выполняется по всем именам устройств для гибих и
жестких дисков по очереди. Каждое имя выводится на экран. Затем прове-
ряется, содержит ли данное устройство файловую систему.


    ПОЯСНЕНИЯ



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

Строка 9 определяет размер используемого буфера. Этот буфер при-
меняется только для хранения сообщений об ошибках, поэтому он не дол-
жен быть очень большим.

Строка 15 определяет структуру суперблока. Он имеет тип filesys
(см. включаемый файл sys/types.h). На моей машине суперблок имеет раз-
мер 1024 байта. Если вы не знаете точно размер буфера у вас, то вы мо-
жете проверить его, вставив в программу следующий оператор:

printf ("the size is %d",sizeof(sb))

Строка 16 описывает рабочую переменную d и дескриптор файла dev.
Строка 17 объявляет буфер размером BSIZE.

Строки 19-59 - это один большой цикл for. Этот цикл представляет
собой всю остальную часть программы. Он выполняется столько раз,
сколько аргументов указано в командной строке. Счетчик цикла начина-
ется с 1, поскольку первым аргументом argv[0] является имя команды. В
качестве аргументов должны быть указаны имена файлов, поэтому данный
цикл использует каждое имя по очереди.

В строках 21-26 проверяется, не начинается ли текущий рассматри-
ваемый нами аргумент со знака '-'. Если да, то это опция, что
представляет собой ошибку, поэтому выводится сообщение об ошибке и
оператор continue вызывает выполнение следующей итерации цикла. Таким
образом, данная программа отвергает опции, но работает при обнаружении
имен файлов.

Считая, что имя файла было найдено, строки 27-32 открывают файл
устройства с этим именем только для чтения. Если данный вызов open не-
удачен, мы посылаем сообщение в буфер вместе с именем, указанным в ко-
мандной строке. Этот буфер передается программе обработки ошибок
(системной), которая использует наше сообщение как первую часть своего
сообщения об ошибке. Она выводит системное сообщение, которое опреде-
ляет данную ошибку. По оператору continue начинается выполнение следу-
ющей итерации цикла for.

Строки 35-39 читают первый блок файла. Для корневой файловой
системы первым блоком является загрузочная запись. Если при этом чте-
нии возникает ошибка, выводится сообщение об ошибке и выполнение цикла
продолжается.

Строки 42-46 читают второй блок, который должен находиться в том
месте, где размещается суперблок, если он имеется. По информации, про-
читанной и помещенной в структуру, мы можем получить доступ к каждому
элементу по его имени.

Строка 48 проверяет, равно ли магическое число в структуре маги-
ческому числу, определенному в файле заголовка. Если они совпадают,
программа mntlook выводит имя файла устройства и сообщение о том, что
файловая система корректна, имя файловой системы (если оно имеется),
имя пакета дисков, размер используемого блока и магическое число в
шестнадцатиричном виде.

В строках 53-54 мы имеем подобие кодированной структуры: оператор
printf использует структуру типа if-then-else для указания строки, ко-
торую нужно выводить. После того как выведена первая строка, выполня-
ется проверка и если она прошла успешно, то выводится значение 512.
Если в результате проверки получено значение "ложь", выводится значе-
ние 1024. Этот метод описан в книге B.W.Kernighan, D.M.Ritchie "The C
Programming Language" (Prentice-Hall, 1978).

Строка 58 закрывает устройство, и цикл возвращается в
начало для принятия следующего имени устройства.


    РАЗМЕРНЫЕ ПАРАМЕТРЫ



Теперь, когда мы рассмотрели взаимоотношения между устройствами и
файловыми системами и некоторые параметры, связанные с форматами
дисков, давайте обратимся к гайкам и болтикам этих устройств. Хотя
основная часть этой информации может показаться экзотичной, она может
оказаться важной при определенных обстоятельствах. Например, для уста-
новки системы UNIX на новую машину вам нужно разбить диск на сегменты
и понимать, каким образом UNIX фактически располагается на диске. Если
вы создаете программы, которые выполняют какую-либо операцию низкого
уровня с диском, вам, очевидно, необходимо понимать, что вы делаете.
Администраторам, поскольку они должны добавлять новые устройства в
систему, необходимо уметь определять количество файловых систем (т.е.
сколько можно создать разделов на диске), их размеры и знать, каким
образом установить файловые системы в эти разделы. Администраторы
должны также уметь писать или модифицировать драйверы устройств. Нако-
нец, при работе с дисками возникают проблемы, такие как плохие блоки,
которые необходимо изолировать и с которыми приходится иметь дело.


    РАЗМЕРЫ БЛОКОВ



System V является последним достижением ветви фирмы AT&T в фа-
мильном дереве UNIX. Это означает, что System V содержит последние
правки, внесенные в исходную систему UNIX. Эти правки предназначены
для того, чтобы сделать UNIX жизнеспособным и стойким коммерческим
продуктом. Для повышения устойчивости были внесены изменения, касающи-
еся работы с файлами и размеров их блоков.

Обычно обмен данными с дисками осуществляется блоками по 512 бай-
тов. Дисковая аппаратура имеет дело именно с таким размером. Для учета
этого факта UNIX первоначально использовал 512-байтные блоки внутри
файловой системы, что, возможно, облегчало написание программ и созда-
вало впечатление, что так и нужно. Однако нельзя отрицать, что при
этом UNIX может работать медленно!

Для ускорения работы внутренние программы в настоящее время
используют блоки размером 1024 байта. Сам диск должен выполнить два
обращения к 512-байтным блокам, но в системе две эти операции чтения
рассматриваются как одна операция чтения блока размером 1024 байта.
Единственная проблема заключается в том, что одни утилиты выдают ре-
зультаты в 512-байтных блоках, а другие - в 1024-байтных, в зависи-
мости от того, когда они были написаны. Когда сильно приближаются пре-
делы свободного пространства на диске, вам действительно нужно знать,
с каким размером вы имеете дело.

Для лучшего понимания проблемы размеров блоков, в табл. 7-3 пока-
зано, какие утилиты какой размер блока используют. Эта информация по-
лучена в основном из System V на машине VAX, из другого варианта
System V и из XENIX. Эти значения могут отличаться на разных машинах,
но идея сохраняется.

Вы видите, что большинство утилит выдают результат в блоках раз-
мером 512 байтов, но утилиты, относящиеся к файловой системе, выдают
результат в 1024-байтных блоках. Поскольку UNIX обращается к дисковому
пространству поблочно, важно уметь точно вычислять, сколько свободного
пространства в файловой системе. Весьма плоха ситуация, когда имеется
какой-то большой файл в редакторе vi (который использует файл /tmp для
промежуточного редактирования), а на диске недостаточно места для за-
писи временного файла редактора vi в реальный файл на диске. На самом
деле это может случиться на персональных машинах с ограниченным (ска-
жем, 20 Мбайт) объемом жесткого диска.


Таблица 7-3

Размеры блоков для различных команд системы UNIX
-------------------------------------------------------------
512 байтов/блок 1024 байта/блок
-------------------------------------------------------------
ls -s fdisk (размеры разделов)
sum mkfs
cpio fsck
df
du
-------------------------------------------------------------


    РАСЧЕТЫ, СВЯЗАННЫЕ С БЛОКАМИ



Еще одним важным вопросом, имеющим отношение к физическим уст-
ройствам и логическим файловым системам, является определение местона-
хождения определенного блока на жестком диске. Номер этого блока вы-
числяется по номерам цилиндра, дорожки и сектора.

Знание номеров блоков становится важным, когда на диске появля-
ется дефектное место. Это дефектное место отмечается номерами цилиндра
и головки. Вам необходимо вычислить, какие блоки попадают в дефектную
область и занести их номера в таблицу дефектных блоков.

Обратная задача также важна. Если программа fsck начинает сооб-
щать, что где-то появился дефектный блок, то каким образом мы можем
узнать номера цилиндра, головки, сектора и т.д. для данного дефектного
блока? Такое обратное вычисление сделать очень тяжело, если не невоз-
можно. Во-первых, номер блока представляет собой произведение четырех
чисел. Трудно узнать, какие именно эти числа. Кроме того, файловые
системы могут использовать информацию вида база/смещение, поэтому блок
номер 1 в файловой системе в действительности является блоком номер
1382 на диске. Определить, какого вида информация была использована в
данном случае, тоже тяжело.

Конкретные данные в следующем примере относятся к вполне опреде-
ленной машине, но на других машинах используются подобные зависимости.
Эти данные относятся к машине с жестким диском объемом 20 Мбайт с
системами XENIX/DOS.

Характеристики устройства:

1 диск = 615 цилиндров, или 615 цилиндров/диск
1 цилиндр = 4 головки (дорожки), или 4 головки/цилиндр

Промышленный стандарт:

1 дорожка = 17 секторов, или 17 секторов/дорожку
1 сектор = 512 байт, или 512 байт/сектор
1 Кбайт = 1024 байта = 2^10
1 Мбайт = 1024 килобайта = 2^20 = 1 048 576 байт

Характеристики устройства различны для разных устройств, но про-
мышленный стандарт для числа секторов на дорожку и байтов на сектор
остается одинаковым. В табл. 7-4 показаны примеры характеристик раз-
личных устройств.


Таблица 7-4

Размеры жестких дисков и их конфигурация
--------------------------------------------------------------
Число цилиндров Число головок Мегабайты
--------------------------------------------------------------

981 3 25

697 5 30

981 5 42

925 7 55

1024 8 71
---------------------------------------------------------------

Вы видите, что число цилиндров и число дорожек различны для уст-
ройств с разным объемом. Определить максимальный объем дисковой памяти
можно перемножением всех чисел. В следующем примере вычисляется общий
размер в байтах для предыдущих данных.

615 цил 4 дор 17 сек 512 байт
------- * ----- * ------ * -------- = 21 411 840 байт/диск
1 диск 1 цил 1 дор 1 сек

21411840 байт 1 мегабайт
------------- * ------------ = 20.4 мегабайта/диск
1 диск 1048576 байт

Отметим, что если вы верно указываете единицы измерения, то они
попарно сокращаются, за исключением одной снизу и одной сверху, и в
результате получаются нужные единицы измерения в ответе. Таким обра-
зом, в первой строке вычислений цилиндры, дорожки и секторы сокраща-
ются, и в качестве единиц измерения остаются байты/диск. Поскольку мы
имеем дело с таким большим количеством различных единиц измерения, вы-
числения такого рода (иногда называемые "размерный анализ") убеждают
нас, что мы понимаем, о чем идет речь.

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

Важным моментом, на который необходимо обратить внимание, явля-
ется использование разных терминов. Иногда применяется число головок
на цилиндр, а иногда число дорожек на цилиндр. При использовании каж-
дого из этих терминов соответствующим образом изменяются и другие тер-
мины. Существует такая взаимосвязь:

цилиндр, дорожка, сектор = физический сектор
цилиндр, головка, байт = блок

Эти две записи выражают в точности одно и то же. Когда вы исполь-
зуете запись вида цилиндр/дорожка/сектор, то в результате получаете
физический сектор. Используя запись вида цилиндр/головка/байт, вы по-
лучаете в результате номер блока. Следует помнить, что ГОЛОВКА - это
то же самое, что и ДОРОЖКА. Если вы это запомните, все остальное вста-
нет на свое место.

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

1. Сколько дорожек имеет диск?

615 цил 4 дор
Решение: ------- * ----- = 2460 дор/диск
1 диск 1 цил

2. Сколько байт в дорожке?

17 сек 512 байт
Решение: ------ * -------- = 8704 байт/дор
1 дор 1 сек

3. Сколько дорожек в одном мегабайте?

2460 дор 1 диск
Решение: -------- * ------ = 123 дор/Мб
1 диск 20 Мб

4. Сколько цилиндров в одном мегабайте?

1 цил 2460 дор
Решение: ----- * -------- = 30 цил/Мб,
4 дор 20 Мб

615 цил 1 диск 123 дор
или ------- * -------- * ------- = 30 цил/Мб
1 диск 2460 дор 1 Мб

5. Дан цилиндр 47, дорожка 2, сектор 4. Какой физический номер секто-
ра?

Решение:

Сначала мы обращаем внимание на то, что вопрос касается секторов.
В качестве единиц измерения даны цилиндр, дорожка и сектор. Как пере-
вести их в другие единицы? Мы знаем, что головки - это то же самое,
что и дорожки, поэтому в вычислениях нужно использовать 4 головки
вместо 4 дорожек:

4 дор 17 сек 17 сек
47 цил * ----- * ------ + 2 дор * ------ + 4 сек =
1 цил 1 дор 1 дор

= 3196 сек + 34 сек + 4 сек =

= сектор 3234



    РАЗМЕРЫ ФАЙЛОВ



В основном при работе в системе UNIX мы считаем, что ее ресурсы
безграничны. Например, мы не заботимся о том, что созданный файл полу-
чится "слишком большим", а это не так уж редко в персональных компь-
ютерах на гибких дисках. Если же мы занимаемся сопровождением и адми-
нистрированием системы UNIX, то мы должны быть готовы иметь дело с си-
туациями, когда превышаются различные предельные значения системы.
Всегда лучше исследовать эти вопросы заранее в некритичных ситуациях,
поэтому давайте рассмотрим пределы размеров файлов и их смысл.

Некоторые параметры "зашиты" в ядро системы при ее генерации. Од-
ним из таких значений является максимальный размер файла. Он определя-
ет наибольшее число блоков, которые может занимать файл. Этот параметр
тесно связан с принятым в UNIX методом использования индексных деск-
рипторов файла (inodes). Это наборы указателей, среди которых первые
десять указывают на блоки данных, следующий указывает на другую табли-
цу, следующий - на таблицу, указывающую на таблицу и т.д.

Имеется еще одно ограничение размера файла, которое определено
для каждого пользователя во время работы в системе - число ulimit
(user limit - пользовательский предел). Это значение устанавливается в
момент вашей регистрации в системе и представляет собой число блоков
по 512 байт, которые вы можете записать в любой заданный файл. В
shell'е имеется команда ulimit, которая при ее вызове без аргументов
выводит это число. Эта же команда позволяет вам уменьшить ваше значе-
ние ulimit. Только суперпользователь (root) может УВЕЛИЧИТЬ значения
ulimit.

Побочным эффектом уменьшения значения ulimit является то, что вы
не можете снова увеличить его до регистрационного значения. Значение
ulimit остается таким же на все время работы вашего shell, поэтому для
восстановления регистрационного значения вам необходимо выйти из
системы, а затем снова зарегистрироваться.

Еще одним интересным моментом является то, что если вы установите
ваше значение ulimit равным 0, вы не сможете создать никакие файлы!
Максимально допустимым размером файла в данном случае является нуле-
вой, поэтому никакой файл не может быть создан. Это представляется
достаточно резонным, однако существуют такие ситуации, когда файл ну-
левого размера МОЖЕТ существовать. Опять же, для восстановления вашего
обычного значения ulimit необходимо выйти из системы, а затем снова
зарегистрироваться.

Как отмечалось ранее, увеличить значение ulimit может только су-
перпользователь. Эта процедура довольно проста. Сначала нужно увели-
чить значение ulimit командой ulimit, а затем запустить shell. Этот
новый shell имеет новое значение ulimit. Если мы хотим, чтобы система
загружалась с shell, имеющим большее значение ulimit, мы можем устано-
вить программу в inittab (таблице инициализации системы), чтобы эта
операция выполнялась автоматически.

Ниже приводится пример программы, которая изменяет значение
ulimit и запускает shell с этим новым значением. Напомним, что эта
программа может быть запущена только суперпользователем.

1 #include
2 #include

4 main()
5 {
6 long v1, v2, v3, newlimit = 5120;

8 v1 = (long)ulimit(UL_GFILLIM, 0L);
9 v2 = (long)ulimit(UL_SFILLIM,newlimit);
10 v3 = (long)ulimit(UL_GFILLIM, 0L);

12 printf("v1: %ld v2: %ld ulim: %ld\n",v1,v2,v3);
13 setuid(getuid());
14 execl("/bin/sh","ulimit sh", 0);
15 }

Значение ulimit является возвращаемым значением системного вызова
ulimit. Первый вызов ulimit в строке 8 получает исходное значение по
умолчанию. Это значение сохраняется в переменной v1. Вызов в строке 9
устанавливает новое значение ulimit равным значению переменной
newlimit. Если этот вызов оканчивается неудачей, переменной v2 присва-
ивается возвращаемое значение -1, и мы видим это по распечатке, кото-
рую выдает строка 12. Если вызов был успешным, возвращаемым значением
является новое значение ulimit, и это мы тоже видим. Затем вызов в
строке 10 получает это значение ulimit. Это или новое значение, или
старое, в зависимости от того, была ли успешной попытка изменить
ulimit.

В строке 13 значение идентификатора текущего процесса устанавли-
вается равным значению идентификатора пользователя, запустившего дан-
ный процесс. Это сработает только в том случае, если пользователь, за-