Лабораторная работа №2 Вариант 10
.doc
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ
ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
ЛИПЕЦКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
КАФЕДРА АВТОМАТИЗИРОВАННЫХ СИСТЕМ УПРАВЛЕНИЯ
Лабораторная работа №2
по дисциплине
«Операционные системы»
на тему:
«Реализация интерпретатора командной строки»
|
Студент |
|
|
|
Филатов А.А. |
|
||||||||
|
|
|
подпись, дата |
|
фамилия, инициалы |
|
||||||||
|
Группа |
|
АС-09-1 |
|
|
|
|
|||||||
|
|
|
|
|
|
|
||||||||
|
Принял |
|
|
|
|
|
||||||||
|
|
|
|
|
Журавлева М.Г. |
|
||||||||
|
ученая степень, звание |
|
подпись, дата |
|
фамилия, инициалы |
|
Липецк 2011
1.Задание
Реализовать на языке C/C++ интерпретатор командной строки (shell) для ОС Windows.
Вариант 10. Написать программу попарного переименования файлов, названия которых заданы первыми 2n параметрами командной строки (1 n 4), и вывода всех строк полученных файлов, соответствующих шаблону, заданному последним 2n+1-ым параметром командной строки. Все файлы, заданные нечетными параметрами, необходимо переименовать соответственно в файлы, заданные четными параметрами (без учета названия программы).
2.Алгоритм
1. Считываем команду.
2. Анализируем ее – при совпадении символов, использующихся для обозначения перенаправления, изменяем потоки ввода-вывода на введенные.
3. Для выполнения функции считываем аргументы, начиная со следующего после названия функции, в память, выполняем функцию.
3. Листинг
#define UNICODE
#define _UNICODE
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <iostream>
#include <string.h>
#include <tchar.h>
#include <io.h>
#include <stdlib.h>
#include <fcntl.h>
#define BUF_SIZE 0x100
int IsWriteLine(WCHAR*, WCHAR*);
void func(int argc, WCHAR* argv []);
int console(void)
{
_wsetlocale(LC_ALL, _T("Rus"));
DWORD read;
ZeroMemory(&read, sizeof(read));
WCHAR cmd[255], **cParseCmd, **argv;
int dNumWhite, i, argc, k=0,j,newDescr, old;
HANDLE oFile;
HANDLE hOldStdOut;
STARTUPINFO si = {sizeof(STARTUPINFO)};
PROCESS_INFORMATION pi;
wprintf(_T("\n>"));
fflush( stdout );
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), cmd, 254, &read, NULL);
cmd[read-2]=0;
i=0;
dNumWhite=0;
bool Output;
while(cmd[i]!='\0')
{
if(cmd[i]==' ')
dNumWhite++;
i++;
}
cParseCmd=(WCHAR**)malloc(sizeof(WCHAR*)*(dNumWhite+1));
for(i=0;i<dNumWhite+1;i++)
cParseCmd[i]=(WCHAR*)malloc(sizeof(WCHAR*)*(256));
//парсер строки команды
for (i=0; i<dNumWhite+1; i++)
{
j=0;
while ((cmd[k]!=' ') && (cmd[k]!='\0'))
{
cParseCmd[i][j]=cmd[k];
j++;
k++;
}
cParseCmd[i][j]=WCHAR(0);
k++;
}
if(wcsstr(cParseCmd[0],_T("exit")))
return 0;
//если установлен флаг -о вывода в файл
if(wcsstr(cParseCmd[dNumWhite],_T("-o")))
{
oFile = CreateFile(_T("output.txt"), GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
argc=dNumWhite;
//запоминаем старый handle (консоли)
hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//переназначаем handle вывода
SetStdHandle(STD_OUTPUT_HANDLE, oFile);
//запоминаем старый дескриптор (консоли)
old = _dup(1);
// Открываем существующий HANDLE как дескриптор (файла)
newDescr = _open_osfhandle((intptr_t)oFile, _O_APPEND );
// Переназначаем файловый дескриптор
_dup2(newDescr, 1);
Output=true;
}
else
{
argc=dNumWhite+1;
Output=false;
}
if(wcsstr(cParseCmd[0],_T("func")))
{
//формирование параметров
argv=(WCHAR**)malloc(sizeof(WCHAR*)*argc);
for(i=0;i<argc;i++)
argv[i]=(WCHAR*)malloc(sizeof(WCHAR*)*(256));
for(i=0;i<argc;i++)
argv[i]=cParseCmd[i];
func(argc,argv);
}
else
{
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
CreateProcess(NULL, cmd, NULL, NULL, Output, CREATE_UNICODE_ENVIRONMENT, NULL, NULL, NULL, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
fflush( stdout );
if(Output)
{
// Сбрасываем поток (возвращаем вывод в консоль)
CloseHandle(oFile);
SetStdHandle(STD_OUTPUT_HANDLE, hOldStdOut);
_dup2(old, 1 );
}
return 1;
}
void main(void)
{
while(console());
}
//поиск и вывод строк соответствующих шаблону
void func(int argc, WCHAR* argv [])
{
//попарное переименование и поиск для каждого файла начиная с конца списка
int err;
for(int i=argc;i>3;i-=2)
{
if(err=IsWriteLine(argv[i-3], argv[argc-1]))
{
printf("No hits. Error: %d \n", err);
}
if(!MoveFile(argv[i-3],argv[i-2]))
{
wprintf(_T("Error: %x \n\n"), GetLastError());
wprintf(_T("Cannot rename %s to %s \n"), argv[i-3],argv[i-2]);
}
else
wprintf(_T("File %s renamed в %s \n\n"), argv[i-3],argv[i-2]);
}
}
int IsWriteLine(WCHAR* filename, WCHAR* str)
{
HLOCAL local;
HANDLE fp;
DWORD dread, size;
WCHAR *buf;
// открываем файл
fp = CreateFile((LPCWSTR)filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(fp == INVALID_HANDLE_VALUE)
{
wprintf(_T("file '%s' not found\n"),filename);
return 1;
}
// получаем кол-во байт в файле
size = SetFilePointer(fp, 0L, NULL, FILE_END);
if(! size)
{
CloseHandle(fp);
return 2;
}
SetFilePointer(fp, 0L, NULL, FILE_BEGIN);
local = LocalAlloc(LPTR, size + 1u); // выделяем память в локал-области
if(local == NULL)
{
CloseHandle(fp);
return 3;
}
buf = (LPTSTR) LocalLock(local); // блокируем выделенную память для записи
ReadFile(fp, (LPVOID)buf, size, &dread, NULL); // читаем весь файл разом
CloseHandle(fp);
buf[dread] = WCHAR(0); // завершить строку нулем
// поиск по совпаддению
int i=0, dNum=0, j=0, k=0;
WCHAR **cParseBuf;
while(buf[i]!=WCHAR(0))
{
if(buf[i]=='\n')
dNum++;
i++;
}
buf[0]=_T(' ');
cParseBuf=(WCHAR**)malloc(sizeof(WCHAR*)*(dNum+1));
for(i=0;i<dNum+1;i++)
cParseBuf[i]=(WCHAR*)malloc(sizeof(WCHAR*)*(256));
//парсер строки команды
for (i=0; i<dNum+1; i++)
{
j=0;
while ((buf[k]!='\n') && (buf[k]!=WCHAR(0)))
{
cParseBuf[i][j]=buf[k];
j++;
k++;
}
cParseBuf[i][j]=WCHAR(0);
k++;
}
for(int i=0;i<dNum+1;i++)
{
if(wcsstr(cParseBuf[i],str))
wprintf(_T(" %d: %s\n "),i,cParseBuf[i]);
}
LocalUnlock(local);
LocalFree(local); // освободить занимаемую память
local = NULL;
return 0;
}
4.Контрольный пример
5.Список используемой литературы
-
Харт, Джонсон, М. Системное программирование в среде Windows, 3-е издание. : Пер. с англ. – М. : Издательский дом «Вильямс», 2005. – 592с. ил.