Эмуляция командного процессора ОС UNIX в среде Windows 9x

Министерство образования Российской Федерации

ВОРОНЕЖСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

Естественно-гуманитарный факультет

Кафедра САПРИС

КУРСОВАЯ РАБОТА

по дисциплине Операционные системы

Тема “Эмуляция командного процессора ОС UNIX в среде Windows 9x”

Выполнил студент       ИС-012                                                     Тимофеев Д.А.      .

                                                               Группа                                             Подпись, дата                       инициалы, фамилия

Руководитель                                                                                  Королев Е.Н.        .

                                                                                                                        Подпись, дата                       инициалы, фамилия

Члены комиссии                                                                                                            .

                                                                                                                        Подпись, дата                       инициалы, фамилия

                                                                                                                                        .

                                                                                                                        Подпись, дата                       инициалы, фамилия

Нормоконтроллер                                                                                                         .

                                                                                                                        Подпись, дата                       инициалы, фамилия

Защищена                                                              Оценка                                  .

                                             Дата

2003

Воронежский государственный технический университет

Кафедра САПРИС

ЗАДАНИЕ

на курсовую работу

по дисциплине Операционные системы

Тема Эмуляция командного процессора ОС UNIX в среде Windows 9x

Студент группы           ИС-012                     Тимофеев Дмитрий Александрович   .

                                                                                                                                                     фамилия  имя  отчество

Перечень вопросов, подлежащих разработке                                                            .

                                                                                                                                        .

                                                                                                                                        .

                                                                                                                                        .

                                                                                                                                        .

Объем работы (графические работы, расчеты, прочее)                                            .

                                                                                                                                        .

                                                                                                                                        .

                                                                                                                                        .

Сроки выполнения этапов                                                                                           .

                                                                                                                                        .

Срок защиты курсовой работы                                                                                    .

Руководитель                                                                                  Королев Е.Н.        .

                                                                                                                        Подпись, дата                       инициалы, фамилия

Задание принял студент                                                                 Тимофеев Д.А.    .

                                                                                                                        Подпись, дата                       инициалы, фамилия

Замечания руководителя

Содержание

Задание на курсовую работу

Замечания руководителя

Введение

2

3

5

1.

2.

3.

Описание файловой системы операционной системы UNIX

Описание полученных для реализации команд и сравнение их с родственными командами Windows 9x

2.1 Описание команд UNIX

2.2 Описание команд Windows 9x

Программная реализация

3.1 Выбор языка программирования

3.2 Инструкция пользователю

3.3 Описание структуры программы

3.4 Используемые модули

3.5 Пример работы программы

6

12

12

14

18

18

18

19

19

20

Заключение

Список литературы

Приложение А Листинг программы

22

23

24

Введение

Давно ушли в прошлое времена компьютеров первых поколений, когда аппаратные средства были главным предметом вожделения специалистов. В те времена, 50-60-е годы, вопрос о программных средствах стоял так: если есть – хорошо, нет – сами напишем, только дайте ЭВМ. Сегодня, прежде всего в силу экономических обстоятельств, т.е. поменявшегося соотношения стоимости в диаде «аппаратные средства / программные средства», и высокой стоимости разработки удовлетворяющих современным требованиям, но отсутствующих по той или иной причине программных средств, при приобретении компьютера чаще обращают внимание на наличие на него доступного (по факту и по цене) программного обеспечения. Полный комплект программного обеспечения, необходимого для организации, например автоматизированного рабочего места (АРМ) инженера-проектировщика, научного работника (физика, химика, биолога и т.д.) по стоимости превосходит (порой в несколько раз) стоимость компьютера адекватного класса.

Особое место среди программных средств всех типов занимают операционные системы, являясь ядром программного обеспечения.

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

ОС UNIX - одна из старейших и наиболее простых операционных систем, изначально была рассчитана на разработку программ (для нее самой и не только) на мини-ЭВМ и позволяла без больших затрат труда программиста переносить программу из одной системы ЭВМ на другую. Неудивительно, что сейчас продается много различных вариантов мобильной операционной системы UNIX, таких как XENIX, UNIXWARE, SUN-OS, LINUX, BSD.

В данной работе будет разработан эмулятор команд ОС UNIX в среде MS-DOS, разработаны следующие команды: cat, comm, dircmp, rmdir, ls, mv, tr, а также команда man – справка.

1. Описание файловой системы операционной системы UNIX

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

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

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

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

В ряде файловых систем предусматривается использование более сложных логических структур, чем последовательная. Например, записи в файле могут образовывать древовидные структуры, может использоваться индексно-последовательная организация файлов (с упорядочением записей по значению некоторых полей) или так называемая, библиотечная структура файлов, использующая уровень учетной информации (каталога), облегчающей поиск и доступ к отдельным компонентам файлов. На физическом уровне блоки файла (обычно размером 256 или 512 байт) могут размещаться в памяти непрерывной областью или хранится несмежно. Первый способ хранения файлов, реализованный, например, в операционной системе РАФОС, приводит к затруднениям при изменении размеров файлов (т.е. к необходимости перезаписи файлов, если их длина увеличивается, или хранения «дыр», если длина уменьшается).

Наиболее развитый механизм несмежного распределения блоков файлов реализован в операционной системе UNIX, в которой размеры файлов могут динамически изменяться в пределах 1Гбайт. Каждый файл в системе имеет дескриптор, в составе которого хранится список, содержащий 13 номеров блоков на диске и используемый для адресации к тем блокам, которые входят в состав файла. Первые десять элементов списка непосредственно указывают на десять блоков, в которых размещаются данные файла. В одиннадцатом элементе списка указан номер блока, хранящий список из 128 номеров блоков данных, которые принадлежат файлу (это первый уровень косвенной адресации). Двенадцатый элемент ссылается на блок, который содержит список из 128 номеров блоков первого уровня косвенной адресации (это второй уровень косвенной адресации). С помощью тринадцатого элемента указывается ссылка на блок, содержащий список из 128 номеров блоков второго уровня косвенной адресации.

Роль учетного механизма, позволяющего обслуживать десятки и сотни файлов, в файловой системе очень важна. Общим приемом является сведение учетной информации о расположении файлов на магнитном диске в одно место – его каталог (директорий). Каталог представляет собой список элементов, каждый из которых описывает характеристики конкретного файла, используемые для организации доступа к этому файлу – имя файла, его тип, местоположение на диске и длину файла. В простых операционных системах (например, операционной системе РАФОС) местоположение единственного каталога на магнитном диске (дискете) и его размер фиксированы. В более сложных системах каталог может находиться в любом месте диска, но на него должна иметься ссылка в, так называемой, метке тома, находящейся в фиксированном месте и формируемой при инициализации диска. Более того, каталогов может быть большое число, и они могут быть логически связаны в какие-либо информационные структуры. Так, наиболее развитая многоуровневая файловая система UNIX поддерживает иерархическую (древовидную) систему каталогов (рис.1). Каждый пользователь может работать в составе этой структуры со своей системой каталогов (со своим поддеревом). Полное имя файла в данной структуре задает путь переходов между каталогами в логической структуре каталогов.

dev – специальные файлы

lib – библиотеки (подпрограммы)

bin – часто используемые программы

etc – команды администратора

tmp –временные файлы

users – каталоги пользователя

usr/lib – библиотеки

usr/games – игры

usr/bin – редко используемые команды

/

lib

etc

users

dev

bin

tmp

usr

games

bin

lib

peter

Рис. 1. Иерархическая система каталогов.

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

Известны десятки различных расширений, используемых при работе с различными программными системами.

В различных операционных системах существую определенные ограничения на длину имени и расширения файла имени файла. Так, в MS-DOS длина имени файла не должна превышать восьми символов, а расширение – трех. В операционной системе UNIX ограничения значительно менее жесткие.

Имена директориев, начиная от корневого, образующие путь к файлу, отделяемые при записи друг от друга косой чертой (\ в DOS, / в UNIX), также как и обозначение диска, относятся к идентификатору файла. Например, в MS-DOS

d:\lang\pascal\work\example.pas

есть файл с именем example и расширением pas, указывающим на то, что это текст программы на Паскале, полный путь к которому:

d: - диск d;

\lang\pascal\work – это структура вложенных директориев, в самом

                                 внутреннем из которых находится необходимый

                                 файл example.pas.

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

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

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

-        владельца (самого себя);

-        представителей той же группы пользователей, и что владелец (понятие группы полезно при совместной работе над какими-либо проектами);

-        всех остальных пользователей системы.

Каждый файл (каталог) имеет три вида разрешения на доступ:

-        чтение (r – read) – можно просматривать содержимое файла (каталога);

-        запись (w – write) – можно менять содержимое файла (создавать или удалять файлы в каталоге);

-        выполнение (x – execute) – можно использовать файл как команду UNIX.

Комбинация видов доступа к файлу записывается последовательностью 9 символов:

rwx rwx rwx

Владелец

Группа

Остальные

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

2. Описание полученных для реализации команд и сравнение их с

родственными командами Windows 9х

2.1 Описание команд операционной системы UNIX

CAT

сat параметры файла(ы)

Вывод содержимого файлов.

> - объединить несколько файлов в один,

>> - присоединить файл к существующему,

-s – запрет вывода пустых строк.

COMM

сomm параметры файл_1 параметры файл_2

Построчное сравнение содержимого 2-х текстовых файлов. Вывод производится в три столбца: строки, содержащиеся в первом файле; строки, содержащиеся во втором файле, строки, содержащиеся в обоих файлах.

-1 – запрет вывода 1-ого столбца,

-2 – запрет вывода 2-ого столбца,

-3 – запрет вывода 3-его столбца,

-12 – вывод только 3-его столбца,

-13 – вывод только 2-ого столбца,

-23 – вывод только 1-ого столбца.

DIRCMP

dircmp каталог_1 каталог_2

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

RMDIR

rmdir параметры каталог

Удаление каталога. Удаляемый каталог не должен содержать файлов или подкаталогов.

-р – удалить указанный каталог и его родительский каталог, если он окажется после этого пустым,

-s – запрет вывода сообщений об ошибках.

LS

ls параметры каталог

Вывод списка файлов в каталоге. Если каталог не указан, использовать текущий каталог.

-1 – вывод информации о каждом файле или каталоге с новой строки,

-a – вывод информации о всех файлах и каталогах,

-R – рекурсивный просмотр,

-l – расширенная информация о файлах,

-p –вывод наклонной черты в конце имени каталога.

MV

mv параметры исходный_файл конечный_файл

Переименование файла или перемещение одного или нескольких файлов в другой каталог.

-f – запрет запроса подтверждений при перезаписи уже существующих файлов,

-i – требование запроса подтверждения при перезаписи существующих файлов.

TR

tr строка_1 строка_2

Выполнение процедуры поиска и замены.

2.2 Описание команд MS-DOS

Общие команды MS-DOS распознаются и выполняются командным процессором command.com. Команды вводятся с клавиатуры, их ввод завершается нажатием клавиши <ENTER>.

Общие команды DOS делятся на три группы:

-         команды работы с дисками;

-         команды работы с файлами;

-         команды работы с каталогами;

-         команды управления системой;

Типовая структура команды выглядит следующим образом:

<имя_команды>[<список_параметров>][<список_ключей>]

Параметры (аргументы) указывают на те объекты, над которыми совершаются операции, ключи уточняют действие команды. Признак ключа (переключателя) – наличие косой линии ‘/’. Квадратные скобки указывают на возможность отсутствия фрагмента.

DIR

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

Полный синтаксис таков:

DIR  [диск:] [путь] [имя_файла] [/P] [/W] [/A[[:атрибуты]]]

         [/O[[:]порядок_сортировки]] […]

Параметры

[диск:][путь]

указываю дисковод и каталог, оглавление которого нужно просмотреть;

[имя_файла]

указывают файл или группу файлов, список которых необходимо получить.

В имени файла могут быть использованы символы заместители:

?

заменяет один произвольный символ в имени файла;

*

заменяет произвольное число произвольных символов.

Ключи:

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

/W

выводит информацию в сокращенном виде, только имена файлов и директориев (в 5 столбцов);

/A[[:]атрибуты]

выводит информацию тех директориев и файлов, атрибуты которых указаны.

Некоторые атрибуты:

H

скрытые файлы;

-H

все файла, кроме скрытых;

S

системные файлы;

-S

все файлы, кроме системных;

D

директории;

-D

только файлы;

R

файлы только для чтения.

Параметр

/Q[[:]порядок_сортировки]

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

DEL (ERASE)

Команда работы с файлами; удаляет файлы.

Синтаксис:

DEL[диск:][путь]<имя_файла>[/P]

Параметр

[диск:][путь]<имя_файла>

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

Ключ /Р вызывает запрос подтверждения для каждого удаляемого файла.

COPY

Команда работы с файлами; копирует один или более файлов в указанное место, а также может использоваться для слияния файлов.

Синтаксис:

COPY [/Y|/-Y] [/A|/B] <файл_источник> [/A|/B] [+ файл-источник [/A|/B] [+ …]] [файл_результат [/A|/B]] [/V]

Параметры состоят из обозначения дисковода, директория и имени файла.

<файл-источник>

указывает местоположение и имя файла, содержимое которого необходимо копировать;

<файл-результат>

указывает местоположение и имя файла, в который нужно поместить скопированную информацию.

Ключи:

/Y

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

/V

проверка того, что новые файлы записаны правильно.

Еще команда той же группы:

RENAME (REN) – переименование файла или группы файлов;

Примерами команд управления системой служат:

COMMAND – запуск командного процессора;

EXIT – выход из командного процессора.

3. Программная реализация

3.1 Выбор языка программирования

Для разработки эмуляции командного процессора ОС UNIX в среде Windows9x была разработана программа на языке Borland Pascal 7.0.

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

Среда Borland Pascal 7.0 обладает мощными и удобными средствами для написания и отладки кода программы. Также он поддерживает концепции объектно-ориентированного проектирования, хорошо структурирован и удобен в обращении.

3.2 Инструкция пользователю

Запуск программы в ОС Windows 95/98/Me/2000/XP:

Кнопка “Пуск” – “Выполнить” – “Обзор”, найти и выделить файл с именем Unix_com.exe, - нажать “OK”. После запуска на экране монитора появится следующее сообщение: ->Эмулятор команд ОС UNIX<-.

Символ $ - приглашение к вводу команд. При вводе команды exit происходит выход в систему. При неправильном вводе команды или при любой другой ошибке появляется сообщение: “Команда введена неправильно!”.

3.3 Описание структуры программы

Функции:

Unix_num – определение номера команды,

Error – ошибка при неверном формате команды,

Compare – сравнение двух строк.

Процедуры:

Reout – определение имени устройства при перенаправлении ввода-вывода,

Spaces – удаление лишних пробелов из строки,

Attr – атрибуты файлов,

Diff – сравнение файлов,

Scan – составление списка файлов указанного каталога,

Man – справка,

LS – вывод списка файлов в каталоге,

DIRCMP – сравнение содержимого двух каталогов,

TR – поиск и замена,

COMM – построчное сравнение содержимого двух текстовых файлов,

RMDIR – удаление каталога,

CAT – вывод содержимого файлов,

MV  - переименование  или перемещение.

3.4 Используемые модули

Модулю System отводится ведущая роль при организации программ на Pascal, так как формирование загрузочного выполнимого EXE-файла начинается именно с этого модуля. В силу своей исключительной важности подключение данного модуля в программу не требует отдельной строки вида Uses System. Интегрированная система включает модуль System в любую пользовательскую программу автоматически.

Процедуры и функции модуля Dos предназначены для обеспечения интерфейса с программами операционной системы. После загрузки DOS большинство пользовательских функций реализуется через прерывание с номером 21h, называемое прерыванием DOS.

3.5 Пример работы программы

-> Эмулятор команд ОС UNIX <-

$ man man

Описание команд ОС UNIX

man имя_команды

Список доступных команд:

ls, dircmp, tr, comm, rmdir, cat, mv

Выход – команда exit

$ ls

UNIX_COM.EXE     UNIX_COM.PAS

$ dircmp 1 2

Файлы из первого каталога

213.TXT

Файлы из второго каталога

321.TXT

Файлы общие для двух каталогов

123.TXT

$ comm. –23 5.TXT 7.TXT

matrix

matrix reload

$ rmdir 777

Каталог 777 удален.

$ cat 7.txt

matrix revolution

matrix reload

matrix

$ mv 7.txt 9.txt

Файл перенесен!

Заключение

В курсовой работе по дисциплине "Операционные системы" на тему "Эмуляция командного процессора ОС UNIX в среде Windows 9х" были рассмотрены вопросы касающиеся файловой системы операционных систем  UNIX и MS-DOS.

Разработана программа на языке Pascal. В данной программе были реализованы следующие команды ls, dircmp, tr, comm., rmdir, cat, mv и man. Работа по созданию программы позволила приобрести практические навыки системного программирования.

Программа достаточно не требовательна к аппаратному и программному обеспечению.

Список литературы

1. Паскаль для персональных компьютеров: Справ. пособие / Ю.С. Бородич, А.Н. Вальвачев, А.И. Кузьмич. – Мн.: Выш. шк.: БФ ГИТМП “НИКА”, 1991. – 365 с.: ил.

2. Информатика: Учеб. пособие для студ. вузов / А.В. Могилев, Н.И. Пак, Е.К. Хеннер; под ред. Е.К. Хеннера. – М.: Изд. центр «Академия», 2000. – 816 с.

3. UNIX:  Справочник / Рейчард К.,  Фостер - Джонсон Э. – Спб: Питер Ком, 1999. -384 с.

Приложение А

Листинг программы

Program unix_com;

Uses Dos;

Var comu:string;

    s_or_f:text;

    k:integer;

Function Unix_num (comu:string):integer;

const inp:array[1..9] of string[6] = (

          'ls', 'dircmp', 'tr', 'comm', 'rmdir', 'cat', 'mv', 'man', 'exit');

var f:boolean;

    i:integer;

Begin f:=False;

      for i:=1 to 9 do

         if (Copy(comu,1,Pos(' ',comu)-1)=inp[i]) or (comu=inp[i]) then

           begin

                 f:=True;

                 Break;

           end;

         if not f then i:=11;

         Unix_num:=i;

End;

Procedure Reout(var comu:string);

var Dev:string;

    Flag:boolean;

Begin

      Dev:='con';

      Flag:=False;

      if Pos ('>',comu) <> 0 then

        begin

              if Pos ('>>',comu) <> 0 then

                begin

                      Delete (comu,Pos('>',comu),1);

                      Flag:=True;

                end;

                Dev:=Copy(comu,Pos('>',comu)+1, Length(comu)-Pos('>',comu)+1);

                if Dev[1]='' then Delete(dev,1,1);

                Delete(comu,Pos('>',comu), Length(comu)-Pos('>',comu)+1);

        end;

      Assign (s_or_f,dev);

      if Flag then begin

                         {$I-} Append (s_or_f); {$I+}

                         if IOResult <> 0 then Rewrite (s_or_f);

                   end

        else Rewrite(s_or_f);

End;

Function Error (comu:string):boolean;

Begin

      Error:=False;

      if Pos(' ',comu)=0 then

        begin

              WriteLn('Команда введена неверно!');

              Error:=True;

        end;

end;

Procedure Spaces (var s:string);

Begin

      while Pos('  ',s)<>0 do Delete(s,Pos('  ',s),1);

      while Pos(' ',s)=1 do Delete(s,1,1);

      if s[Length(s)]=' ' then Delete (s,Length(s),1);

end;

Procedure Attr(at:byte);

const Ast:array[0..6] of string[5] = (

          '-','R','H','S','V','<DIR>','A');

      A16:array[0..6] of byte = (

          $00,$01,$02,$04,$08,$10,$20);

var i,i1,i2,i3,i4,i5:integer;

    at1:byte;

    ss:string[20];

Begin

  for i:=0 to 1 do

    for i:=1 to 2 do

      for i:=2 to 3 do

        for i:=3 to 4 do

          for i:=4 to 5 do

            for i:=5 to 6 do

              begin

                at1:=A16[i]+A16[i1]+A16[i2]+A16[i3]+A16[i4]+A16[i5];

                if at1=at then

                  begin

                    ss:=Ast[i]+Ast[i1]+Ast[i2]+Ast[i3]+Ast[i4]+Ast[i5]+'';

                    write(s_or_f,ss);

                    Exit;

                  end;

               end;

End;

Procedure Ls(comu: string);

var

  Info: SearchRec;

  dt: DateTime;

  atr: byte;

  keys, maska, cmd1: string;

  o1, p1, a1, p, l, r: boolean;

  nn, pos1: integer;

  c0: string[1];

begin

  atr := $3F;

  Spaces(comu);

  cmd1 := comu;

  Delete(comu, 1, 3);

  keys := '';

  if Pos('-', comu) <> 0 then

    begin

      if Pos(' ', comu) = 0 then

         pos1 := Length(comu)

      else

         pos1 := Pos(' ', comu);

      keys := Copy(comu, 1, pos1);

      Delete(comu, 1, pos1);

    end;

  if Pos('l', keys) <> 0 then

    l := True

  else

    l := False;

  if Pos('1', keys) <> 0 then

    o1 := True

  else

    o1 := False;

  if Pos('a', keys) <> 0 then

    a1 := True

  else

    a1 := False;

  if Pos('p', keys) <> 0 then

    p1 := True

  else

    p1 := False;

  if Pos('R', keys) <> 0 then

    r := True

  else

    r := False;

  if comu <> '' then

    begin

      if comu[Length(comu)] <> '\' then

         maska := comu + '\*.*'

      else

         maska := comu + '*.*'

    end

  else

    maska := '*.*';

  FindFirst(maska, atr, Info);

  if Info.Name = '.' then

    FindNext(Info);

  nn := 0;

  repeat

    if (DosError = 0) and a1 and (Info.Name ='..') then

      begin

         Write(s_or_f, Info.Name, ' ':(15 - Length(Info.Name)));

         Inc(nn);

      end;

    if (DosError = 0) and (Info.Name <> '..') then

      begin

         if (Info.Attr = $10) and p1 then

           Info.Name := Info.Name + '\';

         if (Info.Attr = $02) or (Info.Attr = $10) then

           begin

             if a1 then

               begin

               Write(s_or_f, Info.Name, ' ':(15 - Length(Info.Name)));

               Inc(nn);

               end;

           end

         else

           begin

           Write(s_or_f, Info.Name, ' ':(15 - Length(Info.Name)));

           Inc(nn);

           end;

         if l then

           begin

             Attr(Info.Attr);

             UnpackTime(Info.Time, DT);

             with DT do

               begin

                   c0 := '';

                   if Day < 10 then

                     c0 := '0';

                   Write(s_or_f, c0, Day, '-');

                   c0 := '';

                   if Month < 10 then

                     c0 := '0';

                   Write(s_or_f, c0, Month, '-', Year);

                   c0 := '';

                   if Hour < 10 then

                     c0 := '0';

                   Write(s_or_f, '  ', c0, Hour, ':');

                   c0 := '';

                   if Min < 10 then

                     c0 := '0';

                    if o1 then

                      begin

                        WriteLn(s_or_f, c0, Min, ' ');

                        Inc(k);

                      end

                    else

                      begin

                        if nn = 3 then

                          begin

                             WriteLn(s_or_f, c0, Min, ' ');

                             nn := 0;

                             Inc(k);

                          end

                        else

                          Write(s_or_f, c0, Min, ' ')

                      end;

               end;

           end

         else

           begin

             if o1 then

               begin

                   WriteLn(s_or_f);

                   Inc(k);

               end

             else

               if nn = 3 then

                   begin

                     WriteLn(s_or_f);

                     Inc(k);

                     nn := 0;

                   end;

           end;

         if (Info.Attr = $10) and r then

            begin

              WriteLn(s_or_f);

              WriteLn(s_or_f, 'Просмотр каталога ', Info.Name);

              Inc(k);

              keys := '';

              if p then

                keys := ' |more';

              if cmd1[Length(cmd1)] <> '\' then

                begin

                    comu := cmd1;

                    Delete(comu, 1, 3);

                    if Pos('-', comu) <> 0 then

                      begin

                        if Pos(' ', comu) = 0 then

                          pos1 := Length(comu)

                        else

                          pos1 := Pos(' ', comu);

                        Delete(comu, 1, pos1);

                      end;

                    if comu = '' then

                      Ls(cmd1 + ' ' + Info.Name + keys)

                    else

                      Ls(cmd1 + '\' + Info.Name + keys);

                end

              else

                Ls(cmd1 + Info.Name + keys);

            end;

      end;

    FindNext(Info);

  until DosError <> 0;

  WriteLn(s_or_f);

  Inc(k);

end;

Procedure Diff(comu: string);

var

  fname1, fname2, f: string[80];

  f1, f2: text;

  s1, s2: string;

  r, c: integer;

Function Compare(s1, s2: string): integer;

var

  i, k: integer;

Begin

  k := 0;

  for i := 1 to Length(s2) do

    begin

      if i > Length(s1) then

         Break;

      if s2[i] = s1[i] then

         k := k + 1;

    end;

  Compare := Round(100 * k / (Length(s2) +

              Abs(Length(s1) - Length(s2))));

End;

Begin

  Delete(comu, 1, 5);

  fname1 := Copy(comu, 1, Pos(' ', comu) - 1);

  Delete(comu, 1, Pos(' ', comu));

  fname2 := comu;

  Assign (f1, fname1); Reset (f1);

  Assign (f2, fname2); Reset (f2);

  r := 0;

  while True do

    begin

      s1 := #0;

      s2 := #0;

      if not EOF(f1) then

         ReadLn(f1, s1);

      if not EOF(f2) then

         ReadLn(f2, s2);

      r := r + 1;

      if s1 <> s2 then

         begin

           Write(r, ' ');

           c := Compare(s1, s2);

           if c > 80 then

             WriteLn('c')

           else

             WriteLn('d');

           WriteLn('<', s1);

           if c > 80 then

             WriteLn('----')

           else

             WriteLn(r, ' a');

           WriteLn('>', s2);

         end;

      if EOF(f1) and not EOF(f2) then

         begin

           WriteLn('Второй файл длинее первого!');

           Break;

         end;

      if EOF(f2) and not EOF(f1) then

         begin

           WriteLn('Первый файл длинее второго!');

           Break;

         end;

      if EOF(f1) and EOF(f2) then

         Break;

    end;

  Close(f1);

  Close(f2);

End;

Procedure Dircmp(cnp: string);

type

  FileList = array [1..500] of string[12];

var

  f1, f2: FileList;

  Flag, w, p, d, s: boolean;

  i, j, n1, n2, k, n, pos1, cod: integer;

  dir1, dir2, keys: DirStr;

  st: string;

Procedure Scan(dir: DirStr; var f: FileList; var n: integer);

var

  Info: SearchRec;

begin

  if dir[Length(dir)] = '\' then

    dir := dir + '*.*'

  else

    dir := dir + '\*.*';

  FindFirst(dir, $3F, Info);

  if DosError <> 0 then

    begin

      WriteLn('Ошибка при задании каталога ', dir);

      n := -1;

      Exit;

    end;

  n := 0;

  if Info.Name = '.' then

    FindNext(Info);

  repeat

    if (DosError = 0) and (Info.Name <> '..') then

      begin

         if Info.Attr <> $10 then

           begin

             Inc(n);

             f[n] := Info.Name;

           end;

      end;

    FindNext(Info);

  until DosError <> 0;

end;

begin

  if Pos(' ', cnp) = 0 then

    begin

      WriteLn('Необходимо задать параметры!');

      Exit;

    end;

  Delete(cnp, 1, 7);

  n := 72;

  keys := '';

  if Pos('-', cnp) <> 0 then

    begin

      if Pos(' ', cnp) = 0 then

         pos1 := Length(cnp)

      else

         pos1 := Pos(' ', cnp);

      keys := Copy(cnp, 1, pos1);

      Delete(keys, 1, 1);

      Delete(cnp, 1, pos1);

    end;

  if Pos('d', keys) <> 0 then

    begin

      d := True;

      Delete(keys, Pos('d', keys), 1);

    end

  else

    d := False;

  if Pos('s', keys) <> 0 then

    begin

      s := True;

      Delete(keys, Pos('s', keys), 1);

    end

  else

    s := False;

  if Pos('w', keys) <> 0 then

    begin

      w := True;

      Delete(keys, Pos('w', keys), 1);

      while Pos(' ', keys) <> 0 do

         Delete(keys, Pos(' ', keys), 1);

      Val(keys, n, cod);

      if cod <> 0 then

         begin

           WriteLn('Ошибка при задании длины строки!');

           Exit;

         end;

    end

  else

    w := False;

  dir1 := Copy(cnp, 1, Pos(' ', cnp) - 1);

  Delete(cnp, 1, Pos(' ', cnp));

  dir2 := cnp;

  Scan(dir1, f1, n1);

  if n1 = -1 then

    Exit;

  Scan(dir2, f2, n2);

  if n2 = -1 then

    Exit;

  k := 0;

  WriteLn(s_or_f, 'Файлы из первого каталога.');

  for i := 1 to n1 do

    begin

      cod := 0;

      for j := 1 to n2 do

         if f1[i] = f2[j] then

           cod := 1;

      if cod = 0 then

         begin

           Inc(k);

           WriteLn(s_or_f, f1[i]);

         end;

    end;

  WriteLn(s_or_f, 'Файлы из второго каталога.');

  for j := 1 to n2 do

    begin

      cod := 0;

      for i := 1 to n1 do

         if f2[j] = f1[i] then

           cod := 1;

      if cod = 0 then

         begin

           Inc(k);

           WriteLn(s_or_f, f2[j]);

         end;

    end;

  if s then

    Exit;

  WriteLn(s_or_f, 'Файлы общие для двух каталогов.');

  for j := 1 to n2 do

    begin

      cod := 0;

      for i := 1 to n1 do

         if f2[j] = f1[i] then

           cod := 1;

      if cod = 1 then

         begin

           Inc(k);

           WriteLn(s_or_f, f2[j]);

           if d then

             begin

               st := dir1;

               if st[Length(st)] = '\' then

                   st := st + f2[j]

               else

                   st := st + '\' + f2[j];

               st := st + ' ' + dir2;

               if st[Length(st)] = '\' then

                   st := st + f2[j]

               else

                   st := st + '\' + f2[j];

               Diff(st);

             end;

         end;

    end;

end;

Procedure Tr(comu: string);

var

  p1, p2, s, s1: string;

  k: integer;

begin

  if Error(comu) then exit;

  Delete(comu, 1, 3);

  if Pos(' ', comu) = 0 then

    begin

      WriteLn('Недостаточно параметров!');

      exit;

    end;

  p1 := Copy(comu, 1, Pos(' ', comu) - 1);

  Delete(comu, 1, Pos(' ', comu));

  p2 := comu; ReadLn(s);

  while Pos(p1, s) <> 0 do

    begin

      k := Pos(p1, s); Delete(s, k, length(p1));

      insert(p2, s, k);

    end;

  WriteLn(s_or_f, s);

end;

Procedure Comm(comu:string);

var

  fname1, fname2, f: string[80];

  f1, f2: text;

  s1, s2: string;

  par: string[10];

  r1, r2, i: integer;

  b, v1, v2, v3: boolean;

begin

  if Pos(' ', comu) = 0 then

    begin

      WriteLn('Не указаны параметры команды!');

      Exit;

    end;

  Delete(comu, 1, 5);

  if Pos(' ', comu) = 0 then

    begin

      WriteLn('Недостаточно параметров!');

      Exit;

    end;

  par := '';

  if Pos('-',  comu) <> 0 then

    begin

      par := Copy(comu, 2, Pos(' ', comu) - 2);

      Delete(comu, 1, Pos(' ', comu));

    end;

  fname1 := Copy(comu, 1, Pos(' ', comu) - 1);

  Delete(comu, 1, Pos(' ', comu));

  fname2 := comu;

  if fname1 = fname2 then

    begin

      WriteLn('Одинаковые имена файлов!');

      Exit;

    end;

  {$I-}

  Assign (f1, fname1); Reset (f1);

  if IOResult <> 0 then

    begin

      Writeln ('Файл ', fname1, ' не найден!');

      Exit;

    end;

  Assign (f2, fname2); Reset (f2);

  {$I+}

  if IOResult <> 0 then

    begin

      Writeln ('Файл ', fname2, ' не найден!');

      Exit;

    end;

  r1 := 0; r2 := 0;

  v1 := True;

  v2 := True;

  v3 := True;

  if par = '1' then

    v1 := False;

  if par = '2' then

    v2 := False;

  if par = '3' then

    v3 := False;

  if par = '12' then

    begin

      v1 := False;

      v2 := False;

    end;

  if par = '13' then

    begin

      v1 := False;

      v3 := False;

    end;

  if par = '23' then

    begin

      v2 := False;

      v3 := False;

    end;

  while True do

    begin

      Reset(f1);

      for i := 1 to r1 do

         ReadLn(f1, s1);

      Inc(r1);

      ReadLn(f1, s1);

      Reset(f2);

      b := False;

      while not EOF(f2) do

         begin

           ReadLn(f2, s2);

           if s1 = s2 then

             begin

               if v3 then

                   WriteLn(s_or_f, '            ', s1);

               b := True;

               Break;

             end;

         end;

      if not b and v1 then

         WriteLn(s_or_f, s1);

      Reset(f2);

      for i := 1 to r2 do

         ReadLn(f2, s2);

      Inc(r2);

      ReadLn(f2, s2);

      if EOF(f1) and EOF(f2) then

         r1 := -1;

      Reset(f1);

      b := False;

      while not EOF(f1) do

         begin

           ReadLn(f1, s1);

           if s1 = s2 then

             begin

               b := True;

               Break;

             end;

         end;

      if not b and v2 then

         WriteLn(s_or_f, '      ', s2);

      if (r1 = -1) then

         Break;

    end;

  Close(f1);

  Close(f2);

end;

Procedure Rmcat(comu:string);

var

  keys, f: string;

  p, s: boolean;

  n, i: integer;

BEGIN

  if Error(comu) then exit;

  Delete(comu, 1, 6);

  keys := '';

  if Pos('-', comu) <> 0 then

    begin

      keys := Copy(comu, 1, Pos(' ', comu));

      Delete(comu, 1, Pos(' ', comu));

    end;

  if Pos('p', keys) <> 0 then

    p := True

  else

    p := False;

  if Pos('s', keys) <> 0 then

    s := True

  else

    s := False;

  f := comu;

  {$I-} RmDir(f); {$I+}

  if IOResult <> 0 then

    begin

      if not s then

        WriteLn('Kаталог не существует или содержит файлы!');

      Exit;

    end;

  WriteLn('Каталог ', f, ' удален.');

  if p then

    begin

      if Pos('\', f) = 0 then

         begin

          GetDir(0, f);

           ChDir('..');

         end

      else

         begin

           for i := 1 to Length(f) do

             if f[i] = '\' then

               n := i;

           f[0] := Chr(n - 1);

         end;

      RmDir(f);

    end;

End;

Procedure Cat(comu: string);

var

  fname, fname2: string;

  b: string;

  f: text;

  p, Flag: boolean;

  k, f2: integer;

begin

  if Error(comu) then Exit;

  Delete(comu, 1, 4);

  f2 := 0;

  if Pos(' ', comu) = 0 then

    fname := comu

  else

    begin

      f2 := 1;

      fname := Copy(comu, 1, Pos(' ', comu) - 1);

      fname2 := Copy(comu, Pos(' ', comu) + 1, Length(comu) - Pos(' ', comu));

    end;

  if (fname = '-') or (fname = '') then

    fname := 'con';

  repeat

    if f2 = 2 then

      f2 := 0;

    {$I-} Assign(f, fname); Reset(f); {$I+}

    if IOResult <> 0 then

      begin

        WriteLn('Неверное имя файла!');

         Exit;

      end;

    k := 0;

    while not EOF(f) do

      begin

         ReadLn(f, b);

         k := k + 1;

         WriteLn(s_or_f, b);

      end;

    Close(f);

    if f2 = 1 then

      begin

         fname := fname2;

         f2 := 2;

      end;

  until f2 = 0;

end;

procedure Mv(comu:string);

{перенос файлов}

const rs = 512;

var

   keys, fname1, fname2, f: string;

   f1, f2: file;

   nr, nw: word;

   buf: array [1..rs] of char;

   i, r: boolean;

   yn: char;

Begin

     if error(comu) then exit;

     delete(comu, 1, 3);

     if error(comu) then exit;

     keys := '';

     if pos('-', comu) <> 0 then

       begin

            keys := copy(comu, 1, pos(' ', comu));

            delete(comu, 1, pos(' ', comu));

       end;

     if pos('i', keys) <> 0 then i := true

       else i := false;

     if pos('f', keys) <> 0 then r := true

       else r := false;

     fname1 := copy(comu, 1, pos(' ', comu) - 1);

     delete(comu, 1, pos(' ', comu));

     fname2 := comu;

     if fname2[length(fname2)] = '\' then

       begin

            f := fname1;

           while pos('\', f) <> 0 do

                 delete(f, 1, pos('\', f));

                 fname2 := fname2 + f;

       end;

     if fname1 = fname2 then

       begin

            writeln('Oдинаковые имена файла источника и приемника!');

            exit;

       end;

     {$i-}

     assign (f1, fname1);  reset (f1, 1);

     {$i+}

     if ioresult <> 0 then

       begin

            writeln ('Файл - источник не найден!');

            exit;

       end;

     assign (f2, fname2); {$i-} reset(f2); {$i+}

     if (ioresult = 0) and (i or (not r)) then

       begin

        repeat

          write('файл ', fname2, ' уже существует. перезаписать? (y/n) ');

          readln(yn);

        until upcase(yn) in ['y', 'n'];

     if upcase(yn) = 'y' then

       rewrite(f2, 1)

       else

       begin

           close(f1); close(f2);

           exit;

       end;

       end

       else

           rewrite(f2, 1);

           repeat

             blockread(f1, buf, rs, nr);

             blockwrite(f2, buf, nr, nw);

           until (nr = 0) or (nw <> nr);

           close(f1); close(f2); erase(f1);

           writeln ('Файл перенесен!');

End;

Procedure Man (comu:string);

Begin

      Delete(comu,1,4);

      case Unix_num (comu) of

          1:begin

                  WriteLn('Справка по: LS');

                  WriteLn('Выводит список файлов в каталоге.');

                  WriteLn('Если каталог не указан, то исп. текущий каталог.');

                  WriteLn('Вызов:');

                  WriteLn('ls -1lRap каталог');

                  WriteLn('-R - рекурсивный просмотр');

                  WriteLn('-1 - вывод информации о каждом файле или каталоге с новой строки');

                  WriteLn('-l - расширенная информация о файлах');

                  WriteLn('-a - вывод информации о всех файлах и каталогах');

                  WriteLn('-p - вывод наклонной черты в конце имени каталога');

            end;

          2:begin

                  WriteLn('Справка по: DIRCMP');

                  WriteLn('Сравнение содержимого двух каталогов и');

                  WriteLn('вывод информации об отличиях.');

                  WriteLn('Вызов:');

                  WriteLn('dircmp каталог_1 каталог_2');

            end;

          3:begin

                  WriteLn('Справка по: TR');

                  WriteLn('Выполнение процедуры поиска и замены.');

                  WriteLn('Вызов:');

                  WriteLn('tr строка_1 строка_2');

            end;

          4:begin

                  WriteLn('Справка по: COMM');

                  WriteLn('Построчное сравнение содержимого 2-х текстовых файлов.');

                  WriteLn('Вывод производится в три столбца:');

                  WriteLn('      строки, содержащиеся в первом файле,');

                  WriteLn('      строки, содержащиеся во втором файле,');

                  WriteLn('      строки, содержащиеся в обоих файлах.');

                  WriteLn('Вызов:');

                  WriteLn('comm -123 файл_1 файл_2');

                  WriteLn('-1 - запрет вывода 1-ого столбца');

                  WriteLn('-2 - запрет вывода 2-ого столбца');

                  WriteLn('-3 - запрет вывода 3-его столбца');

                  WriteLn('-12 - вывод только 3-его столбца');

                  WriteLn('-13 - вывод только 2-ого столбца');

                  WriteLn('-23 - вывод только 1-ого столбца');

            end;

          5:begin

                  WriteLn('Справка по: RMDIR');

                  WriteLn('Удаление каталога. Удаляемый каталог не должен');

                  WriteLn('содержать файлов или подкаталогов.');

                  WriteLn('Вызов:');

                  WriteLn('rmdir -ps каталог');

                  WriteLn('-p - удалить указанный каталог и его род. каталог');

                  WriteLn('-s - запрет вывода сообщений об ошибках');

            end;

          6:begin

                  WriteLn('Справка по: CAT');

                  WriteLn('Вывод содержимого файлов.');

                  WriteLn('Вызов:');

                  WriteLn('cat имя_файла');

                  WriteLn('> - объединить несколько файлов в один,');

                  WriteLn('>> - присоединить файл к существующему,');

                  WriteLn('-s - запрет вывода пустых строк.');

            end;

          7:begin

                  WriteLn('Справка по: MV');

                  WriteLn('Переименование файла или перемещение одного либо');

                  WriteLn('нескольких файлов в другой каталог.');

                  WriteLn('Вызов:');

                  WriteLn('mv -fi исходный_файл_1 конечный_файл_2');

                  WriteLn('-f - запрет запроса подтверждений,');

                  WriteLn('-i - требование запроса подтверждения.');

            end;

          8,10:begin

                     WriteLn('Описание команд ОС UNIX');

                     WriteLn('man имя_команды');

                     WriteLn('Список доступных команд: ');

                     WriteLn('ls, dircmp, tr, comm, rmdir, cat, mv');

                     WriteLn('Выход - команда exit');

               end;

          else WriteLn('Отсутствует описание этой команды.');

      end;

End;

BEGIN

      WriteLn('-> Эмулятор команд ОС UNIX <-');

      Repeat

             Write('$ ');

             ReadLn(comu);

             Spaces(comu);

             Reout(comu);

             case Unix_num (comu) of

                 1:Ls(comu);

                 2:Dircmp(comu);

                 3:Tr(comu);

                 4:Comm(comu);

                 5:Rmcat(comu);

                 6:Cat(comu);

                 7:Mv(comu);

                 8:Man(comu);

                 9:Break;

                   else WriteLn('Неизвестная команда!');

             end;

             Close(s_or_f);

      Until False;

END.