Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование для начинающих #26


Служба Рассылок Subscribe.Ru

Программирование для начинающих

Выпуск 26

24 OCT 2001

 
 
 
Ведущий рассылки: Вячеслав Мацнев
e-mail: stac@stacmv.net
Здравствуйте, уважаемые подписчики!

В этом выпуске читайте:
ОТСЕБЯТИНА .::. DOS ... как много в этом слове ...

Сегодня мы продолжаем начатый в прошлом выпуске разговор о командном языке ДОС.

Большинство пользователей ПК уже не помнит, что такое ДОС, или просто не знает, что это такое. Хорошо, что вышесказанное не относится к вам, подписчикам этой рассылки.

Кое-кто, впрочем, сейчас тихонько посмеивается, читая эти строки. Мол, ты еще бы паровые машины вспомнил, в двадцать первом-то веке.

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

Это и системы трехмерной анимации (3D Studio), и чертежные пакеты (AutoCAD), и математические пакеты (MathCAD), и музыкальные редакторы (FastTracker II), и, конечно, системы программирования (Visual Basic), и, обязательно, игры (Civilization), игры (Doom), много игр (Leisure Suit Larry, Myst, Need For Speed, Dune 2).

Все приведенные мной примеры программных продуктов известны вам по их Windows-версиям, разве что кроме FastTracker II.

Кому-то, наверное, будет трудно представить 3D Studio под ДОС, но, поверьте, было время, когда было трудно представить 3D Studio работающим под Windows (Release 4 этой программы, которым мне довелось попользоваться, упорно не хотел запускаться из-под Windows, как и многие другие серьезные программы).

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

В минувшую субботу мне пришлось помогать одному знакомому восстановить работоспособность компьютера после действия вируса.

Или это он мне помогал, то и дело предлагая отметить то удачное разбиение винта, то его форматирование.

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

Разбирая гору непонятного происхождения дискет в поисках драйверов, я увидел экземпляр с надписью "Плакат". Увидел и, с молчаливого согласия хозяина, присвоил ее себе.

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

Впервые с программой "Плакат" мне довелось встретиться в начале 90-х прошлого века на машине, гордо называемой "Искра" (наш ответ IBM PC/XT).

"Плакат" или "Суперплакат" или "POSTER CHIZH" это адаптация программы "BannerMania" для России, выполненная Читашвили Н. Г. и НТК "Индекс" в 1990-м году.

Программа позволяла (и что интересно, позволяет до сих пор) создавать таблички и небольшие плакаты типа "Не курить! Штраф 50 руб." (если занимаетесь частным извозом, повесьте себе такую табличку в машину :), "Не стой под стрелой - работай!", "Шефа нет!", "Глазами не хлопать!" и т.п., накладывая на текст различные эффекты, типа тех, что сейчас делает WordArt из MS Office.

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

Да, было время...

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

Сейчас похожая ситуация складывается с Linux, для нее появляется все больше и больше программ. Windows этот путь уже прошла.

Причем то, что Windows 95 практически без проблем выполняла программы для DOS и Windows 3.x, по-моему, определило успех новой ОС.

Да что я говорю "было", "выполняла". Надо говорить "есть", "выполняет".

Когда видишь программы вроде "Плаката", понимаешь, нет, время ДОС еще не прошло.

Это же понимаешь, когда узнаешь, что некие энтузиасты написали свою версию DOS, которую назвали FreeDOS и выпускают под GPL (General Public License). Когда увидишь графическую оболочку для нее. Когда увидишь браузер Arachne.

Когда понимаешь, что и под Windows 9x прекрасно работают большинство ДОС программ и, конечно, все BAT-файлы, часто помогающие нам автоматизировать свою работу на компьютере.

Даже сейчас, когда появились альтернативы для BAT-файлов, типа JScript и VBScript, BAT-файлы остаются самым универсальным средством подобного рода, работающем на любой машине от окаменевшей уже "Искры" до новомодного Pentium 4.
DOS .::. BAT-файлы. Продолжение.

Константин Даниленко

BAT-файлы

Продолжение. Начало в Выпуске 25.

Законы ВАТ-файлов

Закон Первый. ВАТ-файл – это программа на алгоритмическом языке DOS;

Закон Второй. ВАТ-файл может принести вреда больше, чем пользы;

Закон Третий. ВАТ-файл не умеет больше того, что умеет DOS.

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

  1. if [not] exist имя команда
  2. if [not] параметр1==параметр2 команда
  3. if [not] errorlevel код команда

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

  1. Имя файла (или даже директории, правда, с неким ухищрением) понимается в широком смысле: локальное или полное (включая путь) имя конкретного файла, а также маска. Рассмотрим пример. Многие программы создают временные файлы (как правило, с расширениями ТМР, ВАК, OBJ). Эти файлы размножаются, занимают место и мозолят глаз. Полезно время от времени проводить «зачистки». Казалось бы, чего проще:

    del *.tmp

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

    if exist *.tmp del *.tmp

    Ключевое слово not, как нетрудно догадаться, обращает условие, преобразуя истину в ложь и наоборот:

    if not exist *.exe echo Нет ЕХЕ-файлов

  2. Попробуйте догадаться, чего нам не хватает, чтобы воспользоваться этим форматом. Давайте рассуждать логически. Что в DOS может пониматься под параметром? Имя файла (директории), больше ничего. Но если эти параметры заранее известны (являются константами), то теряется смысл их сравнивать. Следовательно, по меньшей мере один из параметров должен быть переменной ( Первый Закон в действии). А откуда взяться переменным? Конечно же, их надо передать файлу. А иначе, как из командной строки, сделать это невозможно. Вот так мы и поняли, что второй формат условной конструкции призван разбираться с ключами (параметрами) ВАТ-файла. Но как именно это делается, мы узнаем чуть позже.
  3. Самый загадочный и в то же время могущественный из форматов. Дело в том, что он нарушает Первый Закон ВАТ-файлов. Но, в конце концов, какое правило без исключений?
    Что же такое errorlevel? Справочники говорят об этом примерно так: «В определенных случаях некоторые программы возвращают число, которое иной раз кое-что и значит» . Англоязычные справочники именуют errorlevel как «exit code» – «код выхода» или «код завершения». То есть некоторые программы при завершении работы записывают в определенную область памяти код (целое неотрицательное число), которое как-то связано с результатом выполнения этих программ. Однако:
    • Нельзя заранее сказать, возвращает ли данная программа ненулевые коды выхода;
    • Если да, то неизвестно, сколько всего возможных кодов;
    • Даже если известно их количество, то неизвестно, каковы их значения;
    • Даже если значения известны, то неизвестно, какой смысл вкладывается в каждое из них.
    Нет иного пути извлечения кода выхода программы, кроме третьего формата условной конструкции ВАТ-файла. Не исключено, что существуют для этой цели некие специальные утилиты. Мне такие не встречались. Но даже они не в силах ответить на большинство вопросов.
    Слава богу, существует документация. Цитирую справочник по MS DOS 4.х:
    «Команда FORMAT возвращает следующие коды выхода:
    0 – успешное завершение;
    3 – прервано пользователем (нажатие Ctrl-C);
    4 – фатальная ошибка, отличная от 0, 3 и 5;
    5 – отрицательный ответ на запрос о форматировании жесткого диска»

    Обратите внимание, что ситуация «0», то есть «успех», названа ошибкой. Кроме того, где значения 1 и 2? Вторая цитата нас немного успокоит. Игорь Данилов, документация к антивирусу DrWeb:
    «0 – Вирусы не обнаружены;
    1 – Обнаружены известные вирусы;
    2 – Обнаружены неизвестные вирусы или подозрительные файлы»

    Вот это уже совсем другое дело. О том, как же обрабатывать эти коды, мы поговорим чуть позже.
    В. Э. Фигурнов в своем бестселлере «IBM PC для пользователя» даже приводит список внешних команд DOS, которые возвращают код выхода (Фигурнов его называет «код возврата»), однако не описывает их значения, количество и смысл. Хорошо, если у вас есть документация по DOS, а если нет? Тогда придется изрядно потрудиться, чтобы прояснить это для каждой конкретной программы.

Возникает законный вопрос: «А что если в случае истинности высказывания в условной конструкции надо выполнить не одну, а несколько команд?». Как поступают в этом случае современные языки программирования, нам известно. Но с ВАТ-файлом этот выход, увы, не всегда является наилучшим. От пресловутой команды безусловного перехода (goto) можно и отказаться, но прежде чем сделать это, рассмотрим, как ее применять.
Команда goto должна куда-то посылать... то есть отсылать – к метке. А меткой в ВАТ-файле считается любая строка, начинающаяся с двоеточия (обратите на отличие от Бейсика, где метка заканчивается на двоеточие - прим. ред.).
В одном учебнике было интересное предложение: не использовать команду rem ввиду ее неудобочитаемости, а комментарии оформлять как фиктивные метки, причем для отличия от меток фактических (на которые есть ссылки) после двоеточия писать какой-нибудь определенный символ, скажем, звездочку. Сравните эти два комментария:

rem Это комментарий
:* Это комментарий

Ни в одном учебнике мне не удалось найти четкого описания ограничений на вид метки. К примеру, правильно сработает такая ссылка:

goto (This is a very complicated label!)

:(This is a very complicated label!)

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


Настало время разобраться с переменными, которые позволят нам предметно обсуждать второй формат условной конструкции.
Как нам известно, большинство команд DOS, внешних и внутренних, и исполняемых файлов вообще, принимают параметры командной строки (ключи), отделяемые друг от друга пробелами. ВАТ-файлы не являются в этом смысле исключением. В свете того, что ВАТ-файлы являются своего рода процедурами DOS, нетрудно понять, что параметры командной строки суть ни что иное, как фактические параметры, передаваемые процедуре. Им должны соответствовать формальные параметры самой процедуры, то есть ВАТ-файла. Они имеют имена, состоящие из двух символов, из которых первый – символ %, а второй – цифра от 1 до 9. Например, если мы снабжаем имя ВАТ-файла тремя фактическими параметрами, то в самом ВАТ-файле им будут соответствовать формальные параметры %1, %2 и %3. Если формальных параметров больше, чем фактических, остальным присваиваются значения «пустая строка». Если фактических больше, то лишние игнорируются.
Пусть нам необходимо сархивировать содержимое некоторой директории в многотомный архив для копирования на дискеты. ВАТ- файлу нужно передать следующие фактические параметры:

  1. Имя директории, содержащей файлы;
  2. Имя архива;
  3. Размер тома.
Этим параметрам будут автоматически присвоены имена от %1 до %3, соответственно. Осталось лишь написать ВАТ-файл, использующий эти формальные параметры и названный SECOND.BAT.

@echo off 1
cls 2
echo Параметры ВАТ-файла %0: 3
echo %0 директория архив размер 4
echo. 5
echo где: 6
echo директория - имя директории-источника (без замыкающего символа \); 7
echo. 8
echo архив - имя архива-назначения (без замыкающей точки); 9
echo. 10
echo размер - размер тома (может быть 1440 или 1200). 11
echo. 12
echo Нажмите любую клавишу для продолжения или Ctrl-C (Ctrl-Break) для прерывания... 13
echo. 14
pause > nul 15
 
if -%1==- goto NoParam 16
if -%2==- goto NoParam 17
if -%3==- goto NoParam 18
 
if not exist %1\nul goto WrongParam 19
if -%3==-1440 goto Continue 20
if -%3==-1200 goto Continue 21
goto WrongParam 22
 
:Continue 23
arj a %1\%2 -y -v%3 %1\*.* 24
if errorlevel 1 goto ARJerror 25
echo Архивирование завершено успешно. 26
echo Вставьте дискету и нажмите любую клавишу... 27
pause > nul 28
copy %1\%2.arj a: 29
if exist %1\%2.a01 echo Остальные файлы скопируйте самостоятельно. 30
goto End 31
 
:ARJerror 32
echo Ошибка при архивировании. 33
goto TryAgain 34
 
:WrongParam 35
echo Неверные параметры. 36
goto TryAgain 37
 
:NoParam 38
echo Не хватает параметра. 39
 
:TryAgain 40
echo Будьте внимательны и попробуйте еще раз. 41
 
:End 42

Разумеется, строки пронумерованы лишь для удобства разбора.
[1] Как мы уже отмечали, это почти стандартное начало любого ВАТ-файла не дает ему быть чрезмерно болтливым.
[2] Команда cls наверняка не вызовет вопросов у тех, кто хоть немного программировал. Для остальных после паузы сообщим: команда cls очищает экран и устанавливает курсор в его левый верхний угол.
[3] Формальные параметры можно использовать не только в условных конструкциях, но и вообще где угодно. Параметр %0 отличается от остальных тем, что присутствует в любом ВАТ-файле. Дело в том, что нумерация параметров командной строки, разделенных пробелами, начинается с 0, как и положено. Просто нулевым параметром в таком случае неизбежно является имя самого ВАТ-файла, причем в той форме, в которой реально в этой строке фигурировало. Поясним. Мы работаем в Нортоне и запускаем наш ВАТ-файл на выполнение наиболее экономным образом: наводим на его имя курсор и нажимаем Ctrl-Enter. В командной строке появляется:

second.bat

Затем вручную вводим параметры и окончательно получаем:

second.bat c:\test two 1440

Тогда при отработке строки [3] на экране появится:

Параметры ВАТ-файла second.bat:

потому что именно так (в строчном регистре и с расширением) выглядел при запуске первый параметр (%0) командной строки.
Если же командная строка имела вид

SECOND c:\test two 1440

то и результат будет соответствующий:

Параметры ВАТ-файла SECOND:

Как мы понимаем, это не более чем косметика, поскольку DOS нечувствительна к регистру.
[3] ... [15] : Первый эшелон "защиты от дурака", то есть от умышленно неправильных или ошибочных действий пользователя. К сожалению, в узких рамках примитивного языка ВАТ-файла обеспечить полноценную защиту от дурака очень трудно, если вообще возможно, но... надо стараться. Ведь если в языке высокого уровня защита от дурака - зачастую требование удобства или хорошего тона, а не безопасности, то Второй Закон ВАТ-файлов требует, чтобы не то чтобы разрушительные, но даже непредсказуемые последствия ошибки были сведены к минимуму.
Причем это необходимо, даже если ВАТ-файл не предполагается давать кому-либо другому и единственным пользователем может быть лишь сам автор. Даже спустя месяц уже самому трудно вспомнить, в какой именно последовательности какие параметры надо указывать. Начальный этап выполнения позволяет пользователю сравнить подробное толкование параметров с тем, что он только что написал. Увидев, что совершена ошибка, надо нажать упомянутые клавиши (подсказка об очевидном - второй эшелон защиты), в противном случае продолжить выполнение.
Кстати, с точки зрения защиты от дурака команда cls в строке [2] не совсем корректна. Ведь теперь, когда экран очищен, пользователь не видит своей команды и ее параметров. Хорошо было бы, чтобы сравнение того, что есть, с тем, что должно быть, проводилось весомо, грубо и зримо. Так что лучше команду cls поместить после строки [15] . Еще, строке [7] можно придать вид:

echo директория - имя директории-источника (без замыкающего символа \). Вы задали: %1

И то же для строк [9] и [11] . Тогда, вообще говоря, строку [2] можно оставить в покое.
[16] ... [18] : Третий эшелон. Пользователю не верят на слово и проверяют истинное наличие параметров. Пока только наличие. Если параметров нет вовсе, на это среагирует строка [16] . Если он один, об этом узнает строка [17] . И, наконец, об отсутствии третьего параметра станет ясно после отработки строки [18]
. Разумеется, можно организовать четвертый эшелон защиты, предусмотрев отдельную обработку для каждого из случаев. Мы пошли по более простому пути, объединив все три случая. Если число параметров меньше трех, на экран будет выдано:

Не хватает параметра.
Будьте внимательны и попробуйте еще раз.

После этого выполнение ВАТ-файла завершится. Как аварийно прервать его выполнение, мы уже знаем. Штатное завершение выполнения возможно только по достижении конца файла. И, если первая строка почти всегда имеет вид @echo off, то последней разумно делать строку

:End

Тогда для штатного завершения работы ВАТ-файла можно использовать одну и ту же команду

goto End

Зачем стоят минусы перед именами параметров во втором формате? Слово В. Э. Фигурнову: "Сравнение второго параметра командного файла со строкой SSS не следует делать так: if %2==SSS... Ведь если в командном файле меньше двух параметров, то символы %2 будут замещены пустой строкой, и при выполнении команды возникнет ошибка. Правильное сравнение выглядит так: if -%2==-SSS... Оно годится в любом случае". Я даже не пытался поставить под сомнение слова Мэтра. И ни разу не пожалел об этом.
[19] : Четвертый эшелон защиты. Проверяется наличие заданной директории, в нашем случае C:\TEST. Напрямую ключевое слово exist относится только к файлам, но не к директориям, поэтому приходится использовать маленькие хитрости. Даже если директория пуста, она содержит устройство nul (нулевое, фиктивное, отсутствующее устройство). И лишь если директория %1 не существует, высказывание станет ложным и оператор goto отошлет выполнение к метке WrongParam.
[20] ... [21] : Пятый эшелон. Многотомное архивирование делается чаще всего для копирования на дискеты. Поэтому в архиватор ARJ "зашиты" стандартные форматы 360 кб, 720 кб, 1.2 Мб и 1.44 Мб. Первые два формата остались разве что в воспоминаниях о нашей розовой юности. Если быть до конца честным, то и "хайовые" пятидюймовки так и не успели достичь популярности, а оказались вытесненными трехдюймовками. Но ведь мы просто учимся, а эта благая цель оправдывает легкие прегрешения против действительности.
Какой бы параметр ни был задан - 1200 или 1440, отработается оператор goto и выполнение продолжится с метки Continue. И только если оба высказывания окажутся ложными, выполнение ВАТ-файла прервется - архивирование невозможно. Цепочку условных конструкций, аналогичную строкам [20] ... [23] , разумно приводить всегда, если параметр может принимать одно значение из конечного множества заранее известных. Например, параметры %1 и %2 этому требованию не удовлетворяют.
[24] : Кажется, мы сделали почти все, чтобы ошибочные параметры не пробились сквозь глубоко эшелонированную защиту от дурака. Тем досаднее будет, если архиватор ARJ, что называется, "не прописан". Разумеется, проще всего указать его полное имя. Но мы рассмотрим другой путь.
Если набрать в командной строке DOS произвольную комбинацию символов и нажать Enter, то DOS будет пытаться интерпретировать это как команду и выполнить ее, а для этого искать комбинацию:

  1. Вначале среди своих внутренних команд;
  2. Затем среди СОМ-файлов в текущей директории;
  3. Затем последовательно среди ЕХЕ- и ВАТ-файлов - там же;
  4. Наконец в том же приоритетном порядке (СОМ, ЕХЕ, ВАТ) среди всех директорий, указанных в значении переменной окружения %РАТН%;
  5. И только если последний этап завершится неудачей, DOS выдаст сообщение Bad command or file name.
Что же такое переменная %РАТН%? Заглянем в наш AUTOEXEC.BAT. Скорее всего, он будет выглядеть так:

@echo off
prompt $p$g
path c:\;c:\dos
c:\dos\mscdex /d:mscd000
c:\utils\rk.com
c:\utils\mmouse.com
c:\nc\nc.exe

Вторая строка устанавливает вид "приглашения DOS". Оно прописывается по умолчанию и, на мой взгляд, весьма разумному. Изучение других видов приглашений выходит за рамки данного исследования. Четвертая и последующие строки загружают: драйвер CD-ROM, русификатор, драйвер мыши и Нортон соответственно. Дело не в них, а в команде РАТН. Там-то и перечислены те самые "избранные" директории, где ищутся командные файлы с неуказанными путем и расширением. Разумно было бы включить в число "избранных" те директории, где лежат архиваторы, чтобы, набрав только arj, мы могли бы получить краткую справку о возможностях этой программы.
Пусть файл ARJ.EXE находится в C:\ARJ. Можно, конечно, изменить AUTOEXEC.BAT, чтобы третья строка имела вид

path c:\;c:\dos;c:\arj

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

path=%path%;c:\arj

Эта команда добавит путь C:\ARJ к списку "избранных", оставив остальные нетронутыми и даже не покусившись на их приоритет относительно c:\arj. Теперь можно быть уверенным, что файл ARJ.EXE будет найден и без указания его полного имени. Правда, после перезагрузки новый путь будет "забыт", а при исполнении SECOND.BAT - вновь "вспомнен".
[25] : В документации к архиватору ARJ перечислены все возможные коды выхода и растолкован их смысл. Значение 0, как обычно, соответствует отсутствию ошибок, а вот коды с 1 до 12 возвращаются в случае ошибки (для каждой - свой код). Мы вновь упростим ситуацию и будем рассматривать только два случая: "ошибка есть" и "ошибки нет". Дело в том, что высказывание "errorlevel число" идентично высказыванию "код выхода БОЛЬШЕ ИЛИ РАВЕН числу". Поэтому:

* Количество конструкций if errorlevel... должно равняться количеству ненулевых значений кода выхода;
* Коды выхода оцениваются строго в НИСХОДЯЩЕМ порядке.

Строка [25] , таким образом, будет отработана, если код ошибки больше или равен 1, то есть при наличии все равно какой ошибки. Мы умышленно нарушили первое из правил, лишив себя возможности узнать причину ошибки, но второе правило соблюли.
Высказывание будет ложно тогда и только тогда, когда архивирование прошло успешно, о чем и уведомляет строка [26] .
[27] ... [29] : Копирование файла на дискету. Раз архивирование свершилось, в заданной директории наверняка существует файл %2.ARJ, то есть, в нашем случае, TWO.ARJ. Что же касается второго тома (TWO.A01) и всех последующих, то их существование уже зависит от суммарного объема файлов. Отчасти это предусматривает строка [30] .
Итак, мы завершили более чем подробный анализ ВАТ-файла. Осталось совсем немного. Вот пример файла, проводящего проверку диска на вирус с помощью DrWeb:

@echo off
drweb c: /cl /nm
if errorlevel 2 goto NewVir
if errorlevel 1 goto Vir
echo Вирусы не обнаружены
goto End

:Vir
echo Обнаружен известный вирус
pause
goto End
:NewVir
echo Подозрение на неизвестный вирус
pause

:End

Мы уже цитировали комментарий И. Данилова к своему детищу. Данный ВАТ-файл демонстрирует последовательность обработки кодов выхода: строго в нисходящем порядке!


Продолжение в следующем выпуске.

ОКРУЖЕНИЕ

Сайт проекта FREEDOS: http://www.freedos.org

Различные DOS-приложения для работы с Интернетом: http://www.fdisk.com

Библиотека, где можно найти ряд интересных книг по DOS и не только: http://www.libru.nm.ru


Школа - сайт со шпаргалками, сочинениями, рефератами только для школьников!

DO Sледующего выпуска!


С уважением,
Вячеслав Stac Мацнев mailto:stac@stacmv.net
24.10.01.



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу
Рейтингуется SpyLog

В избранное