Міністерство освіти і науки України
Вінницький технічний коледж
Спеціальність: 5.091504
Програма емуляції роботи командного
процесора операційної системи
Пояснювальна записка
до курсового проекту
з дисципліни: „Системне програмування ”
Виконав: студент групи 4ОК2
Гладкий А.В.
Прийняв:
Кисюк Д.В.
Вінниця 2010
ВСТУП
Мова С була винайдена і реалізована Деннісом Рітчі (Dennis Ritchie) для комп'ютера DEC PDP-11 в операційній системі Unix. Ця мова була розроблена на основі "старішої" мови BCPL, створеної свого часу Мартіном Річардсом (Martin Richards). BCPL зробив певний вплив на мову В, розроблену Кеном Томпсоном (Ken Thompson). У свою чергу розвиток мови В привів до створення в 1970 році мови С.
Впродовж багатьох років стандартом С була фактично версія, що поставляється разом з операційною системою Unix. Ця версія вперше була описана Браяном Керніганом (Brian Kernighan) і Деннісом Рітчі в книзі The С Programming Language (Englewood Cliffs, N.J.: Prentice-Hall, 1978). Влітку 1983 року був утворений комітет із створення для мови С стандарту ANSI (American National Standards Institute — Національний інститут стандартизації США). Треба відзначити, що процес стандартизації зайняв вельми чималий термін — шість років.
Стандарт ANSI був остаточно прийнятий в грудні 1989 року і вперше опублікований на початку 1990 року. Цей стандарт був також прийнятий організацією ISO (International Standards Organization — Міжнародна організація по стандартизації), тому він називається стандартом ANSI/ISO мови С++. У 1995 році була прийнята 1-а поправка до стандарту С++, згідно якої, серед іншого, було додано декілька бібліотечних функцій. У 1989 році стандарт С разом з 1-ю поправкою став базовим документом стандарту C++, що визначає С як підмножина C++. Версію С, визначену стандартом 1989 року, звичайно називають С89.
Впродовж 90-х років увага програмістів була прикована головним чином до розвитку стандарту C++. Тим часом розробка С також продовжувалася, привівши в 1999 році до появи стандарту С, який прийнято називати С99. В цілому С99 зберіг всі основні риси С89, тобто,
можна сказати, що мова С залишилась сама собою! Комісія стандартизації С99 надала основну увагу двом напрямам: додаванню декількох чисельних бібліотек і розвитку нових вузькоспеціальних засобів, таких як масиви змінної довжини і модифікатор покажчика restrict. Завдяки цим нововведенням мова С++ знову виявилась на вістрі розвитку мов програмування.
Версія С стандарту 1989 року в даний час найпоширеніша версія, вона використовується всіма компіляторами С, вона ж є основою для C++.
Мову С++ часто називають мовою програмування середнього рівня. Але це не значить, що С++ менш могутня, менш розвинена або важча у використанні, ніж мови високого рівня, такі як Basic або Pascal. Це також не значить, що С++ така ж громіздка і незручна, як асемблер. Мовою середнього рівня її називають швидше тому, що вона об'єднує в собі кращі риси мов високого рівня з можливостями асемблера.
Як мова середнього рівня С++ дозволяє маніпулювати бітами, байтами і адресами, тобто тими базовими елементами даних, з якими працює комп'ютер. Не дивлячись на це програма, написана на С++, володіє високою переносимістю. Переносимість — це властивість програмного забезпечення, створеного для одного типу комп'ютера або операційної системи, яке дозволяє легко переробити його для іншого типу, тобто перенести в інше обчислювальне середовище. Наприклад, якщо програму, що працює під управлінням DOS, легко переробити так, щоб вона працювала під управлінням Windows 2000, то така програма називається переносимою.
Всі мови високого рівня дотримуються концепції типів даних. Тип даних є набором значень, що зберігаються в змінних, а також набір операцій, виконання яких допускається над цими значеннями. Звичні типи даних — це цілі числа, символи і числа з плаваючою крапкою. Мова С++ має декілька вбудованих типів даних, проте вона не є мовою, що сильно типізується, як Pascal або Ada. У мові С++ допускаються майже всі перетворення типів. Наприклад, у виразах можна вільно змішувати змінні символьного і цілого типів.
На відміну від більшості мов високого рівня, в С++ майже відсутній контроль помилок в процесі виконання програми. Наприклад, не перевіряється порушення меж масивів. Відповідальність за подібні помилки повністю покладається на програміста.
Аналогічно цьому С++ не вимагає строгої сумісності параметрів і аргументів функцій. У мовах програмування високого рівня звичайно необхідно, щоб тип аргументу більш менш відповідав типу параметра. Для С++ це не характерно, тут аргумент може мати майже будь-який тип, якщо його можна розумно перетворити в тип параметра. Більш того, компілятор С++ автоматично здійснює всі види необхідних перетворень.
Відмітною особливістю мови С++ є можливість маніпулювання безпосередньо бітами, байтами, словами і покажчиками. Тому С++ добре пристосована для системного програмування.
Інша важлива особливість С++ — це мала кількість ключових слів, складаючих команди мови. У С89 визначено 32 ключові слова, причому в С99 додано лише 5 слів. Мови високого рівня звичайно мають значно більше ключових слів, наприклад, в більшості версій мови Basic їх кількість перевищує сотню! Із за того, що в мові відсутні засоби введення/виведення й т.п., при програмуванні на ній істотну роль грає бібліотека стандартних програм, що здійснюють взаємодію із системою. У всіх системах, сумісних з ОС UNIX, існує сумісний набір програм для введення/виведення, керування пам'яттю, перетворення даних і виконуючи інші функції, використання яких забезпечує можливість переносу програм на інші ЕОМ. Командний процесор COMMAND.COM розташовується на системному диску як звичайний файл. При завантаженні на згадку частина зазначеного файлу, називається резидентною (оскільки вона постійно розміщається в ОЗП), розташовується за BIO.COM і DOS.COM, інша частина - транзитна, розташовується, починаючи зі старших адрес пам'яті процесора. Резидентна частина разом із двома файлами (DOS.COM і BIO.COM) становлять ядро ОС, що постійно перебуває в оперативній пам'яті. Основними функціями командного процесора є: прийом і розбір команд, отриманих із клавіатури або з командного файлу; виконання вбудованих команд DOS, що перебувають усередині файлу COMMAND.COM; завантаження й виконання зовнішніх програм DOS і прикладних програм (це файли типу COM і EXE); обробку файлу автозапуску (AUTOEXEC.BAT) при завантаженні системи; стандартну обробку переривань.
1. Аналіз технічного завдання
Будь-який процесор повинен сприймати та виконувати команди, які вводить користувач. Нескінченний інтерактивний цикл призначений для того щоб користувач міг вводити команди за допомогою клавіатури. Вихід з даного циклу супроводжується за допомогою появи команди “exit”, яка дає змогу вийти з даного циклу. Якщо в даному циклі не буде передбачений вихід за допомогою команди “exit”, то з нього буде можливо вийти лише аварійно.
Дана програма має такі модулі команд: edit, split, join, ar. Після вибірки команди, яку ввів користувач, за допомогою номеру команди визначається сама команда, яку користувач ввів на виконання після чого визивається модуль команди, який починає виконувати операції. Команда edit виконує функцію створення файлу, після того як користувач ввів команду. Для цього перевірялось правильність введення команди, назви файлу який потрібно створити, потім відкривається цей файл для подальшої роботи з ним. Команда join виконує з’єднання двох текстових файлів в один. В результуючому файлі після склеювання буде міститися інформація двох інших. Команда ar виконує архівування або розархівування вказаних файлів за допомогою зовнішнього архіватора. Команда split повинна розрізати текстовий файл на частини.
Крім вищезазначених команд дана програма повинна містити ще дві команди, а саме help та exit. За допомогою цих команд можна отримати довідку про саму програму або за допомогою команди exit правильно вийти з програми. Дані команди повинні вводитися правильно і в певній послідовності. Для отримання довідки про правильність введення команди можна отримати за допомогою введення параметру /?. Це дозволяє користувачу, який вперше користується даною програмою взнати про правильність користування командами.
2 Теоретична частина
2.1 Операційна система
Операційна система - це програма, яка завантажується при включенні комп'ютера. Вона веде діалог з користувачем, здійснює управління комп'ютером, його ресурсами (оперативною пам'яттю, місцем на дисках і т. д.), запускає інші (прикладні) програми на виконання. Операційна система забезпечує користувачу і прикладним програмам зручний спосіб спілкування (інтерфейс) з пристроями комп'ютера.
Основна причина необхідності операційної системи полягає в тому, що елементарні операції для роботи з пристроями комп'ютера і управління ресурсами комп'ютера - це операції дуже низького рівня, тому дії, які необхідні користувачу і прикладним програмам, складаються з декількох сотень або тисяч таких елементарних операцій.
Операційна система приховує від користувача ці складні і непотрібні подробиці і надає йому зручний інтерфейс для роботи. Вона виконує також різні допоміжні дії, наприклад, копіювання або друк файлів. Операційна система здійснює завантаження в оперативну пам'ять всіх програм, передає їм управління на початку їх роботи, виконує різні дії по запиту виконуваних програм і звільняє займану програмами оперативну пам'ять при їх завершенні.
Командний процесор обробляє команди, що вводяться користувачем. Основні функції командного процесора полягають в організації діалогу з оператором, виконанні команд, що подаються з клавіатури, і інтерпретації командних файлів.
Механізм роботи текст-орієнтованого інтерфейсу краще розглянути на прикладі командного процесора MSDOS, який до речі входить до складу операційної системи Windows.
Вона складається з наступних компонентів:
1.) базова система вводу-виводу (BIOS);
2.) блок початкового завантаження (BOOT RECORD);
3.) модуль обробки переривань (DOS.COM);
4.) утиліти (FORMAT.COM, DISKCOPY.COM);
5.) модуль розширення базової системи вводу-виводу (BIO.COM);
6.) командний процесор (COMMAND.COM).
Командний процесор COMMAND.COM розташовується на системному диску як звичайний файл. При завантаженні на згадку частина зазначеного файлу, називається резидентною (оскільки вона постійно розміщається в ОЗП), розташовується за BIO.COM і DOS.COM, інша частина - транзитна, розташовується, починаючи зі старших адрес пам'яті процесора. Резидентна частина разом із двома файлами (DOS.COM і BIO.COM) становлять ядро ОС, що постійно перебуває в оперативній пам'яті. Основними функціями командного процесора є: прийом і розбір команд, отриманих із клавіатури або з командного файлу; виконання вбудованих команд DOS, що перебувають усередині файлу COMMAND.COM; завантаження й виконання зовнішніх програм DOS і прикладних програм (це файли типу COM і EXE); обробку файлу автозапуску (AUTOEXEC.BAT) при завантаженні системи; стандартну обробку переривань. Комп’ютер, на якому буде працювати командний процесор повинен мати такі параметри: оперативної пам’яті 1Mb або більше; мінімум процесор 286DX/66MHz; ОС MS-DOS не нижче версії 5.0. Ще одним важливим елементом є файлова система жорсткого диску. Так як MS-DOS не працює з файловою системою NTFS, тоді дана програма не зможе працювати з даною файловою системою через іншу будову пам’яті. Тому дана програма буде працювати з файловою системою FAT16 чи FAT32.
2.2 Передача параметрів у мові С++
У мові C++ передача параметрів функціям відбувається через стек. Спочатку С++ заносить передаючі функції і їх параметри в стек, починаючи з найправішого і закінчуючи лівим, після чого відбувається виклик функції.
При поверненні з функції занесені в стек параметри все ще знаходяться там, але вони більше не використовуються. Тому після кожного виклику функції C++ налаштовує вказівник стека назад у відповідності із значенням, яке він мав перед занесенням в стек параметрів.
Організація передачі параметрів функції через стек і використання його для динамічних локальних змінних – це стандартний прийом в мові С++. Неважливо скільки параметрів має програма на мові С++, «най лівіший» параметр завжди зберігається в стеку за адресою, безпосередньо наступною за збереженою в стеку адресою повернення, наступний параметр, що повертається, зберігається безпосередньо після «най лівішого» параметра і т.д. Оскільки порядок і тип передаючих параметрів відомі, їх завжди можна знайти в стеку.
У випадку з мовою програмування Асемблера функції можуть звертатися до параметрів, передаючих в стеку, за допомогою звертання до регістру BP.
2.3 Системні ресурси та опис принципів роботи
Важливим пунктом необхідної системної конфігурації є файлова система жорсткого диску. Цей параметр має значення, так як операційна система MS-DOS не працює з файловою системою NTFS, тому наш командний процесор не матиме доступу до файлів та каталогів розміщених на даному жорсткому диску.
конецформыначалоформыКомп’ютер, який необхідний для запуску програми(мінімальна конфігурація):
- процесор 286DX/66MHz або кращий;
- ОС MS-DOS;
- Оперативної пам’яті 1Mb або більше.
Програма повинна містити:
1.Точку входу в програму;
2.Головну суперпетлю (частина інтерактивної програми, яка містить нескінченний цикл чекання дії користувача);
3. Модуль аналізу команди користувача;
4. Модулі, які відповідають командам, реалізованим в даному варіанті.
Крім того, програма обов’язково повинна реагувати на команди exit (або аналогічну), за якою програма повинна коректно завершувати свою роботу, та help (або аналогічну), за якою видається коротка довідка про написану програму. Кожна з команд повинна мати такий параметр (наприклад, “/?”), за яким користувачу повинна надаватись довідка по використанню даної команди.
3. Практична частина
3.1 Розробка алгоритму програми
В даному пункті описується алгоритм по якому буде написана програма емуляції роботи командного процесора ОС. Дані в програму будуть передаватись за допомогою командної стрічки. В тимчасову змінну будуть потрапляти дані введені у командній стрічці. Командна стрічка буде розбиватись на команду і відповідні аргументи, після чого буде проводитись аналіз командної стрічки наступним чином:
Алгоритм основної програми
1. Створюємо масив command_line довжиною 100 символів та встановлюємо command_number=6 – максимальна кількість команд.
2. Зчитуємо command_line, поки він не перестане бути порожнім.
3. Ріжемо стрічку по пробілам до кінця. Перше слово – команда, яку необхідно виконати, іші – аргументи функції.
4. У структурі CommandLIST шукаємо номер введеної команди і присвоюємо його змінній cmd.
5. Відповідно до номера команди виконуємо функції. Якщо 0 то виводимо повідомлення, що введена невідома команда, 1 – завершуємо виконання програми, 2 – виводимо допоміжну інформацію по програмі, 3-6 виконуємо відповідні функуції згідно структури CommandLIST.
3.2 Опис системних функцій
Join
Для реалізації команди join потрібно відкрити перший файл скопіювати його вміст в буфер, створивши новий файл копіюємо в нього вміст буфера. Після цього відкриваємо другий файл копіюємо його вміст в буфер, після чого копіюємо вміст буфера в створений файл, при цьому продовжуючи інформацію від першого файлу. Для реалізації даної команди використані такі функції як: fopen, fclose, fread, fwrite, fflush.
Ar
В даній команді реалізовано наступний підхід: ми використовуємо функцію мови С++ spawnl або system, які дозволяють запускати на виконання зовнішні програми з нашої. Потім, передаємо архіватору необхідні команди і виконуємо вказану дію, інформуючи користувача.
Edit
Дана команда виконує функцію створення файлу. Для цього їй потрібно відкрити файл із заданою назвою, зчитати його зміст, а якщо він не існує то створити його. Після чого відбувається емуляція текстового редактора і обробляються команди користувача. При натисненні клавіші Tab користувачем, файл зберігається, включаючи зміни. Для реалізації даної команди використані такі функції як: fopen (відкриває потік і зв’язує з цим потоком визначений файл), fseek ( функція яка виконує операції прямого доступу до файлу), fclose ( закриває потік, відкритий функцією fopen), ftell (повертає поточне значення показника поточній позиції ф файлі), putc (записує символ в файл), getc ( функція зчитує символ з файлу).
Split
Формат команди за технічним завданням повинен мати наступний вигляд:
Після аналізу команд, дана підпрограма проводить аналіз існування вхідного файлу. У випадку, якщо даний файл існує, він відкривається для читання, і виконується подальший алгоритм його обробки. Інакше, якщо файл не існує, виводиться інформація про не існування даного файлу, і підпрограма припиняє своє виконання.
У випадку, якщо файл знайдено і відкрито, відкриваються два вихідних файл для запису. У випадку, якщо файли не існували, вони будуть створені програмою, однак якщо вони вже були створені, то необхідно бути обережним, оскільки вони будуть цілком перезаписаними програмою, і всі попередні дані будуть втраченими.
Опис функцій які використовувались при написанні програми.
Функція fopen
Функція fopen ( ) відкриває потік і пов'язує з цим потоком певний файл. Потім вона повертає покажчик цього файлу. Найчастіше під файлом мається на увазі дисковий файл. Прототип функції fopen () такий:
FILE *fopen(const char *імя_файла, const char *режим)
де ім’я файла — це покажчик на рядок символів, що є допустимим ім'ям файлу, в яке також може входити специфікація шляху до цього файлу. Рядок, на яку вказує режим, визначає, яким чином файл буде відкритий.
Функція fopen () повертає покажчик файлу.
Функція fclose
Функція fclose () закриває потік, який був відкритий за допомогою виклику fopen (). Функція fclose () записує у файл всі дані, які ще залишалися в дисковому буфері, і проводить офіційне закриття файлу на рівні операційної системи. Відмова при закритті потоку несе всілякі неприємності, включаючи втрату даних, зіпсовані файли і можливі періодичні помилки в програмі. Функція fcloseO також звільняє блок управління файлом, пов'язаний з цим потоком, даючи можливість використовувати цей блок знову. Оскільки кількість одночасно відкритих файлів обмежена, то, можливо, доведеться закривати один файл, перш ніж відкривати інший. Прототип функції f close () такий:
int fclose(FILE *пф);
пф — покажчик файлу, повернений в результаті виклику fopen (). Повернення нуля означає успішну операцію закриття. У разі ж помилки повертається EOF.
Щоб точно взнати, в чому причина цієї помилки, можна використовувати стандартну функцію ferror (). Звично відмова при виконанні fclose () відбувається тільки тоді, коли диск був передчасно видалений (стертий) з дисковода або на диску не залишилося вільного місця.
Функція putc ()
У системі введення/виведення мови С++ визначаються дві еквівалентні функції, призначені для виведення символів: putc () і fputc (). (Насправді putc () зазвичай реалізується у вигляді макросу).
Функція putc () записує символи у файл, який за допомогою fopen () вже відкритий в режимі запису. Прототип цієї функції наступний:
int putc(int ch, FILE *пф);
Де пф — це покажчик файлу, повернений функцією fopen (), а ch — що виводиться символ. Покажчик файлу повідомляє putc (), в якій саме файл слід записувати символ. Хоча ch і визначається як int, проте записується тільки молодший байт. Якщо функція putc () виконалася успішно, то повертається записаний символ. У протилежному випадку повертається EOF.
Функція getc ()
Для введення символу також є дві еквівалентні функції: getc() і fgetc (). Обидві визначаються для збереження сумісності із старими версіями С++.
Функція getc () записує символи у файл, який за допомогою fopen() вже відкритий в режимі для читання. Прототип цієї функції наступний:
int getc(FILE *пф);
пф— це покажчик файлу, що має тип FILE і повернений функцією fopen(). Функція getc () повертає ціле значення, але символ знаходиться в молодшому байті. Якщо не відбулася помилка, то старший байт (байти) буде обнулений.
Якщо досягнутий кінець файлу, то функція getc () повертає EOF.
Функція fseek
Повторно поміщає вказівник файлу потоку. Тобто встановлює
вказівник файлу, зв’язаний з потоком в нове положення. Fseek використовується з введенням-виведенням потоку. Якщо вказівник переміщений успішно fseek повертає 0, а при помилці fseek повертає якесь інше відмінне від 0. fseek повертає значення помилки лише в тих випадках коли не відкривається файл. Замість FILE *stream вказується ім’я файлу, long offset – , int whence – зазначається місце куди потрібно відправити вказівник.
fseek(FILE *stream, long offset, int whence);
Функція ftell.
Повертає поточний вказівник файлу. Точніше кажучи повертає вказівник файлу для потоку. Функція ftell, яка повертає вказівник може використовуватись в наступному запиті до функції fseek. При успішній роботі функція повертає поточне положення вказівника файлу. При помилці повертає –1. FILE *stream – вказується назва файлу, тобто файл якому потрібно повернути вказівник.
ftell(FILE *stream);
ВИСНОВКИ
В результаті виконання курсового проекту було створено програму-емулятор командного процесора, яка в свою чергу виконує наступні команди: створення текстових файлів, з'єднання текстових файлів в один (зміст з'єднуваних файлів подається одним суцільним текстом в результуючому файлі), архівація файлів та розріз файлів на частини. В процесі виконання даної роботи було досліджено принципи функціонування командного процесора та розроблено програму на мовах програмування C++ та Асемблера. При написанні програми було використано принципи функціонування командного процесора.
Програма має головну довідку, яка містить перелік виконуваних команд, довідки по кожній команді з правильним синтаксисом, що значно спростить використання її користувачем
У курсовому проекті було використано функції мови програмування С++ та мови низького рівня програмування – Асемблера. Використання різних методів та ресурсів програмування дозволило створити невелику за об’ємом та швидкодіючу програму емуляції роботи командного процесора ОС.
ЛІТЕРАТУРА
1. Баженова І. Ю. Visual C++ 6.0 Уроки програмування. – Київ: Фоліо, 1997
2. Б. Керниган, Д. Ричи. Язык программирования «С». – Москва: Видавництво 1996
3. Белецкий Я. И. Turbo C++. М. : Видавництво Машиностроение 1994.
4. Прокофьев Б. П. Turbo C и Turbo C++. - Москва: СП «Ланит», 1992
5. Бъерн Страуструп. Язык программирования «С». – Москва: Видавництво 1998
6. Джес Либерти. Освой самостоятельно С++ за 21 день. – Москва:
Вільямс, 2001
7. Тед Фейсон Borland C. Обьектно ориентированое прорамирование. – Москва: SAMS, 1996
8. Зубков С. В. Assembler для DOS, Windows и Unix ., Москва: ДМК, 2005
9. С. Бочков. Д. Субботин. Язык программирования Си для персонального компьютера. М: Радио и связь, 1990
10. Стенли Б. Язык программирования С++. - Москва: SAMS, 2000
11. Страуструп Б.В. Язык программирования С++. - М. : Радио и связь, 1991.
ДОДАТОК А
Лістинг головної програми та команд мовою С++
#pragma option -ms
#include<stdio.h>
#include<string.h>
#include<process.h>
#include<dos.h>
#include<io.h>
#define maxarg 10
extern "C" void joinhelp(void);
extern "C" void joinexec(unsigned,char **);
typedef void(* exec)(unsigned ,char **);
typedef void(* help)(void);
struct CLIST{
char* cmdname;
exec execu;
help hlp;
};
unsigned argc;
char* args[maxarg];
unsigned cmdnum,cmd;
void Help(unsigned, char**){
printf("\n\nGladkyj A.V. - 4ok2\nVar. 14\nCom: Ar, Split, Edit, Join\n\n");
}
void arexec(unsigned ,char **argv){
int res;
if(argv[1][0]=='a'){
res=spawnl(P_WAIT,"rar.exe","","a",argv[2],argv[3],NULL);
if(res!=-1) printf("Done archive creation\n");
}
if(argv[1][0]=='e'){
res=spawnl(P_WAIT,"rar.exe","","e",argv[2],NULL);
if(res!=-1) printf("Done archive unpacking\n");
}
if(res==-1){
printf("Error executing application\n");
}
}
void arhelp(void){
printf("Usage:\n"
"\tar a arc file - Create an archive\n"
"\tar e arc - Unpack archive\n");
}
#define min(a,b) ((a)<(b))?(a):(b)
#define bufsz 512
void splitexec(unsigned argc,char** args){
FILE *fi,*fo;
char buf[bufsz];
if(argc!=4){
printf("Illegal parameter count\nType \"split /?\" for help\n");
return;
}
fi=fopen(args[1],"rb");
if(!fi){
printf("Fatal error: cannot open source file\n");
return;
}
fseek(fi,0,SEEK_END);
fpos_t fsize=ftell(fi);
if(fsize==0){
printf("Cannot split empty file\n");
fclose(fi);
return;
}
fpos_t sz1=fsize/2, sz2=fsize-sz1;
fseek(fi,0,SEEK_SET);
fo=fopen(args[2],"wb");
if(!fo){
printf("Fatal error: cannot open destantion file\n");
fclose(fi);
return;
}
while(sz1){
fpos_t i;
fpos_t toread;
toread=min(bufsz,sz1);
i=fread(buf,1,toread,fi);
if((i==0)&&(sz1!=0)){
printf("Error reading source file\n");
fclose(fi);
fclose(fo);
return;
}
sz1-=i;
if(fwrite(buf,1,i,fo)!=i){
printf("Error writing destantion file\n");
fclose(fi);
fclose(fo);
return;
}
}
fflush(fo);
fclose(fo);
fo=fopen(args[3],"wb");
if(!fo){
printf("Fatal error: cannot open destantion file\n");
fclose(fi);
return;
}
while(sz2){
fpos_t i;
fpos_t toread;
toread=min(bufsz,sz2);
i=fread(buf,1,toread,fi);
if((i==0)&&(sz2!=0)){
printf("Error reading source file\n");
fclose(fi);
fclose(fo);
return;
}
sz2-=i;
if(fwrite(buf,1,i,fo)!=i){
printf("Error writing destantion file\n");
fclose(fi);
fclose(fo);
}
}
fflush(fo);
fclose(fo);
printf("File %s is splited to files %s and %s.\n", args[1],args[2],args[3]);
}
void splithelp(void){
printf("Usage: split source dest1 dest2\n"
"\tsource Name of source file\n"
"\tdest1, dest2 Names of files to split in\n");
}
void editexec(unsigned argc,char **argv){
if(argc!=2){
printf("Invalid artgument count\n");
return;
}
if(_creat(argv[1],FA_NORMAL)==-1){
printf("Error creating file\n");
}
}
void edithelp(void){
printf("Usage: edit <filename>\nCreate file\n");
}
CLIST clist[]={{"",NULL,NULL}, {"exit",NULL,NULL}, {"help",Help,NULL},
{"split",splitexec,splithelp}, {"ar",arexec,arhelp},
{"edit",editexec,edithelp}, {"join",joinexec,joinhelp}};
void main(void){
char cmdline[100];
cmdnum=6;
while(1){
printf("***KOM*** > ");
gets(cmdline);
if(!strlen(cmdline)) continue;
args[0]=strtok(cmdline," ");
argc=1;
while(args[argc]=strtok(NULL," ")) argc++;
cmd=0;
for(int i=1;i<=cmdnum;i++)
if(!strcmpi(args[0],clist[i].cmdname)){
cmd=i;
break;
}
if(cmd==0){
printf("Unknown command\n");
continue;
}
if(cmd==1) return;
if(cmd==2){
clist[2].execu(0,NULL);
continue;
}
if(!strcmp(args[1],"/?")){
clist[cmd].hlp();
continue;
}
clist[cmd].execu(argc,args);
}
}
ДОДАТОК Б
Лістинг команди мовою Assembler
model small
public C joinhelp,C joinexec
.code
help db "Usage: join <file_1> <file_2> <dest_file_3>",10,13,"Join given 2 files to one",10,13,"$"
errormsg db "Error.",10,13,"$"
joinexec proc
arg argc:word,argv:word ;char**
push bp
mov bp,sp
mov si,argv;Load address of pointers array
mov dx,[si+2];Load address of second argument(argv[1])
mov ah,3ah
int 21h ;rmdir
jnc fin
push ds
push cs
pop ds
mov ah,9
mov dx,offset errormsg
int 21h
transerr:
mov ah,9
mov dx,offset transfermsg
int 21h
mov bx,file1
call fclose ;close src
mov bx,file2
call fclose ;close dst
pop ds
jmp fin
opensrc1err:
push ds
push cs
pop ds
mov ah,9
mov dx,offset erropen1
int 21h
pop ds
jmp fin
opendst2err:
push ds
push cs
pop ds
mov ah,9
mov dx,offset erropen2
int 21h
mov bx,file1
call fclose ;close src
pop ds
jmp fin
fin:pop bp
ret
pop ds
fin:pop bp
ret
joinexec endp
opensrc proc
mov ax,3d00h
mov dx,[si+2];Open src. file argv[1]
int 21h
ret
opensrc endp
fclose proc
mov ah,3eh
int 21h ;Close source
ret
fclose endp
createdst proc
mov ah,3ch
xor cx,cx
mov dx,[si+4];Open dst. file argv[2]
int 21h
ret
createdst endp
joinhelp proc
push ds
push cs
pop ds
mov ah,9
mov dx,offset help
int 21h
pop ds
ret
joinhelp endp
end
ДОДАТОК В
Алгоритм головної програми
|