PostgreSQL 8.0: новые возможности Сергей Супрунов ALTER TABLE test ALTER COLUMN mynum TYPE NUMERIC(4,2); COPY mytable FROM ‘/path/to/file.csv’ WITH CSV; ----------------------------------------------------------------------------------------------------------------- Эмуляция при помощи QEMU Сергей Яремчук # su # tar zxvf qemu-0.6.1.tar.gz # cd qemu-0.6.1 # ./configure # make # make install qemu [options] [disk_image] # qemu -cdrom /dev/cdrom # qemu -dummy-net -cdrom /dev/cdrom # qemu -dummy-net -cdrom movix.iso #!/bin/sh sudo /sbin/ifconfig $1 192.168.0.1 # qemu -smb /mnt/qemu -user-net -cdrom /dev/cdrom -redir [tcp|udp]:host-port:[guest-host]:guest-port # qemu -redir tcp:1234::23 -cdrom /dev/cdrom # telnet localhost 1234 # qemu -snapshot -hda /dev/hda # qemu-img create linux.img 1500M # dd of=hd.img bs=1024 seek=1048576 count=0 # qemu -hda linux.img -cdrom /dev/cdrom -boot d # qemu -monitor stdio -hda linux.img -cdrom altlinux_cd1.iso -boot d # qemu change -cdrom altlinux_cd2.iso # qemu linux.img # qemu-mkcow cowimage.cow 1024 # qemu-img convert –f cow cowimage.cow image.raw # qemu-fast -nographic -hda linux.img -kernel bzImage-2.4.21 -append "console=ttyS0 root=/dev/hda sb=0x220,5,1,5 ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe" # cd qemu-0.6.1 # tar zxvf /tmp/kqemu-0.6.2-1.tar.gz # mknod /dev/kqemu c 250 0 # chmod 666 /dev/kqemu # qemu-PPC ./qemu-tests/PPC/ls C:\>qemu.exe -hda guest_image_name.img -boot c -user-net # kmdr-executor /home/sergej/work/kqemu-0.1/kqemu-0.1.kmdr ----------------------------------------------------------------------------------------------------------------- Linux Xinerama: один монитор хорошо, а много лучше Павел Закляков Section "ServerLayout" Option "Xinerama" "on" Identifier "Multi Head" Screen 0 "Screen0" 0 0 Screen 1 "Screen1" LeftOf "Screen0" InputDevice "Mouse0" "CorePointer" InputDevice "Keyboard0" "CoreKeyboard" InputDevice "DevInputMice" "AlwaysCore" EndSection Section "Files" RgbPath "/usr/X11R6/lib/X11/rgb" FontPath "unix/:7100" EndSection Section "Module" Load "dbe" Load "extmod" Load "fbdevhw" Load "glx" Load "record" Load "freetype" Load "type1" Load "dri" EndSection Section "InputDevice" Identifier "Keyboard0" Driver "keyboard" Option "XkbRules" "xfree86" Option "XkbModel" "pc104" Option "XkbLayout" "ru" Option "XkbVariant" "winkeys" Option "XkbOptions" "grp:alt_shift_toggle" EndSection Section "InputDevice" Identifier "Mouse0" Driver "mouse" Option "Device" "/dev/mouse" Option "Protocol" "IMPS/2" Option "Emulate3Buttons" "no" Option "ZAxisMapping" "4 5" EndSection Section "InputDevice" Identifier "DevInputMice" Driver "mouse" Option "Protocol" "IMPS/2" Option "Device" "/dev/input/mice" Option "ZAxisMapping" "4 5" Option "Emulate3Buttons" "no" EndSection Section "Monitor" DisplaySize 1024 768 ModeLine "1024x768" 135.920 1024 1104 1216 1392 768 769 772 814 -hsync +vsync Identifier "Monitor0" VendorName "Samsing" ModelName "Samsung SyncMaster 700IFT (CSH780B*)" HorizSync 30.0 - 98.0 VertRefresh 50.0 - 160.0 Option "dpms" EndSection Section "Monitor" DisplaySize 1024 768 ModeLine "1024x768" 135.920 1024 1104 1216 1392 768 769 772 814 -hsync +vsync Identifier "Monitor1" VendorName "Samsung" ModelName "SyncMaster 700IFT (CSH780B*)" HorizSync 30.0 - 98.0 VertRefresh 50.0 - 160.0 Option "dpms" EndSection Section "Device" Identifier "Videocard0" Driver "radeon" VendorName "Videocard vendor" BoardName "ATI Radeon VE" BusID "AGP:1:5:0" Screen 0 EndSection Section "Device" Identifier "Videocard1" Driver "radeon" VendorName "Videocard vendor" BoardName "ATI Radeon VE" BusID "AGP:1:5:0" Screen 1 EndSection Section "Screen" Identifier "Screen0" Device "Videocard0" Monitor "Monitor0" DefaultDepth 16 SubSection "Display" Modes "1024x768" Depth 16 EndSubSection EndSection Section "Screen" Identifier "Screen1" Device "Videocard1" Monitor "Monitor1" DefaultDepth 16 SubSection "Display" Depth 16 Modes "1024x768" EndSubSection EndSection [Modelines] 1024x768="1024x768" 135,920 1024 1104 1216 1392 768 769 772 814 -hsync +vsync 768 точек * 120 Гц * 1,05 = 96,768 КГц HorizSync 30.0 – 96.0 Option "Device" "/dev/mouse" Option "Device" "/dev/input/mice" Section "ServerLayout" Identifier "dual head configuration" Screen 0 "Screen0" 0 0 InputDevice "Mouse0" "CorePointer" InputDevice "Keyboard0" "CoreKeyboard" EndSection #Section "ServerFlags" # Option "Xinerama" "true" #EndSection Section "Files" RgbPath "/usr/X11R6/lib/X11/rgb" FontPath "unix/:7100" EndSection Section "Module" Load "dbe" Load "extmod" Load "fbdevhw" Load "glx" Load "record" Load "freetype" Load "type1" Load "dri" EndSection Section "InputDevice" Identifier "Keyboard0" Driver "keyboard" Option "XkbRules" "xfree86" Option "XkbModel" "pc104" Option "XkbLayout" "ru" Option "XkbVariant" "winkeys" Option "XkbOptions" "grp:alt_shift_toggle" EndSection Section "InputDevice" Identifier "Mouse0" Driver "mouse" Option "Device" "/dev/input/mice" Option "Protocol" "IMPS/2" Option "Emulate3Buttons" "no" Option "ZAxisMapping" "4 5" EndSection Section "InputDevice" Identifier "DevInputMice" Driver "mouse" Option "Protocol" "IMPS/2" Option "Device" "/dev/input/mice" Option "ZAxisMapping" "4 5" Option "Emulate3Buttons" "no" EndSection Section "Monitor" Identifier "Monitor0" VendorName "Samsung" ModelName "Samsung SyncMaster 700IFT (CSH780B*)" DisplaySize 1024 768 HorizSync 30.0 - 98.0 VertRefresh 50.0 - 160.0 ModeLine "1024x768" 135.9 1024 1104 1216 1392 768 769 772 814 -hsync +vsync Option "dpms" EndSection Section "Device" Identifier "Videocard0" Driver "radeon" VendorName "Videocard vendor" BoardName "ATI Radeon VE" BusID "AGP:1:5:0" Option "MonitorLayout" "CRT, CRT" Option "CRT2Position" "LeftOf" Option "MergedFB" "yes" EndSection Section "Screen" Identifier "Screen0" Device "Videocard0" Monitor "Monitor0" DefaultDepth 24 SubSection "Display" Depth 24 Modes "1024x768" "800x600" "640x480" EndSubSection EndSection Option "CRT2HSync" "30.0-86.0" Option "CRT2VRefresh" "50.0-120.0 #Section "ServerFlags" # Option "Xinerama" "true" #EndSection Section "ServerLayout" Identifier "dual head configuration" Screen 0 "Screen1" 0 0 Screen 1 "Screen0" RightOf "Screen1" InputDevice "Mouse0" "CorePointer" InputDevice "Keyboard0" "CoreKeyboard" EndSection Section "ServerFlags" Option "Xinerama" "true" EndSection Section "Files" RgbPath "/usr/X11R6/lib/X11/rgb" FontPath "unix/:7100" EndSection Section "Module" Load "dbe" Load "extmod" Load "fbdevhw" Load "glx" Load "record" Load "freetype" Load "type1" Load "dri" EndSection Section "InputDevice" Identifier "Keyboard0" Driver "keyboard" Option "XkbRules" "xfree86" Option "XkbModel" "pc104" Option "XkbLayout" "ru" Option "XkbVariant" "winkeys" Option "XkbOptions" "grp:alt_shift_toggle" EndSection Section "InputDevice" # Modified by mouseconfig # Option "Device" "/dev/mouse" Identifier "Mouse0" Driver "mouse" Option "Device" "/dev/input/mice" Option "Protocol" "IMPS/2" Option "Emulate3Buttons" "no" Option "ZAxisMapping" "4 5" EndSection Section "InputDevice" Identifier "DevInputMice" Driver "mouse" Option "Protocol" "IMPS/2" Option "Device" "/dev/input/mice" Option "ZAxisMapping" "4 5" Option "Emulate3Buttons" "no" EndSection Section "Monitor" Identifier "Monitor0" VendorName "Samsung" ModelName "Samsung SyncMaster 700IFT (CSH780B*)" DisplaySize 1024 768 HorizSync 30.0 - 98.0 VertRefresh 50.0 - 160.0 ModeLine "1024x768" 135.9 1024 1104 1216 1392 768 769 772 814 -hsync +vsync Option "dpms" EndSection Section "Monitor" Identifier "Monitor1" VendorName "Samsung" ModelName "My TFT Monitor" DisplaySize 1024 768 HorizSync 30.0 - 98.0 VertRefresh 50.0 - 160.0 Option "dpms" EndSection Section "Device" Identifier "Videocard0" Driver "radeon" VendorName "Videocard vendor" BoardName "ATI Radeon VE" BusID "AGP:1:5:0" Option "MonitorLayout" "CRT, CRT" #!! Option "CRT2Position" "LeftOf" #!! Option "MergedFB" "yes" EndSection Section "Device" Identifier "Videocard1" Driver "s3" BoardName "S3" BusID "PCI:0:10:0" EndSection Section "Screen" Identifier "Screen0" Device "Videocard0" Monitor "Monitor0" DefaultDepth 16 SubSection "Display" Depth 16 Modes "1024x768" "800x600" "640x480" EndSubSection EndSection Section "Screen" Identifier "Screen1" Device "Videocard1" Monitor "Monitor1" DefaultDepth 16 SubSection "Display" Depth 16 Modes "1024x768" "800x600" "640x480" EndSubSection EndSection BusID "PCI:0:10:0" # lspci ----------------------------------------------------------------------------------------------------------------- FreeBSD tips: использование ipnat Сергей Супрунов Файл /etc/ipf.rules pass in from any to any pass out from any to any # ipf -Fa -f /etc/ipf.rules # ipnat -CF -f /etc/ipnat.rules map rl0 from 192.168.0.0/24 to any -> 100.100.100.101/32 map rl0 192.168.0.0/24 -> 100.100.100.101/32 map rl0 192.168.0.0/24 -> 100.100.100.101/32 portmap tcp 10000:10999 bimap rl0 192.168.0.125/32 -> 100.100.100.125/32 rdr rl0 100.100.100.180/32 port 80 -> 192.168.0.80 port 8080 tcp rdr rl0 100.100.100.180/32 port 80 -> 192.168.0.80 port 8080 tcp round-robin rdr rl0 100.100.100.180/32 port 80 -> 192.168.0.81 port 8080 tcp round-robin # ipnat -s # ipnat -l ----------------------------------------------------------------------------------------------------------------- FreeBSD в домене Microsoft Windows Рашид Ачилов > id user1 > id user1 template homedir = /usr/home/%U template shell = /bin/tcsh dmap gid = 15000-30000 idmap uid = 15000-30000 winbind use default domain = true winbind separator = + winbind enum users = yes winbind enum groups = yes group: files winbind passwd: files winbind >id user2 > ls -l auth sufficient pam_unix.so no_warn try_first_pass nullok auth required pam_winbind.so use_first_pass # auth auth required pam_nologin.so no_warn auth sufficient pam_unix.so no_warn try_first_pass nullok auth required pam_winbind.so use_first_pass AllowedAuthentications keyboard-interactive AuthKbdInt.Optional pam AllowedAuthentications keyboard-interactive AuthPAM on --- pam_group.c.old Tue Dec 14 19:38:56 2004 +++ pam_group.c Tue Dec 14 19:38:56 2004 @@ -70,7 +70,7 @@ return (PAM_IGNORE); /* get applicant */ - if (pam_get_item(pamh, PAM_RUSER, &ruser) != PAM_SUCCESS + if (pam_get_item(pamh, PAM_USER, &ruser) != PAM_SUCCESS || ruser == NULL || (pwd = getpwnam(ruser)) == NULL) return (PAM_AUTH_ERR); # auth auth required pam_nologin.so no_warn auth sufficient pam_unix.so no_warn try_first_pass nullok auth required pam_group.so group=ntstaff auth required pam_winbind.so use_first_pass >id user2 ----------------------------------------------------------------------------------------------------------------- PhpGACL – cистема управления правами Кирилл Сухов var $_db_table_prefix = 'galc_'; // префикс для наименования таблиц в базе данных var $_db_type = 'mysql'; // тип базы данных var $_db_host = 'localhost'; // хост базы данных var $_db_user = 'root'; //пользователь базы данных var $_db_password = ''; //пароль пользователя var $_db_name = 'gacl'; //имя базы данных var $_db = ''; // объект ADODB database connector (если ADODB не использовалось и не настраивалось, можно оставить пустым) Добавление ARO “Раздел -> Значение”: “Billing_group -> Vasya” “Managers_group -> Oksana” // Подключаем базовый API include('phpgacl/gacl.class.php'); $gacl = new gacl(); $username = $db->quote($_POST['username']); $password = $db->quote(md5($_POST['password'])); $sql = 'SELECT name FROM users WHERE name='; $sql .= $username.' AND password='.$password; $row = $db->GetRow($sql); if($gacl->acl_check('system','login','user',$row['name'])){ $_SESSION['username'] = $row['name']; return true; } else return false; ----------------------------------------------------------------------------------------------------------------- Практикум Python: отправка файлов по электронной почте Сергей Супрунов C:\Temp>send to me file “Годовой отчет.doc” as year2004.zip Листинг 1. Начало сценария send.py # -*- coding: cp1251 -*- ######################################################### # Utility for send files by e-mail from command line #-------------------------------------------------------- # Usage: # send to files [(nonzipped | as )] ######################################################### import sys, os, glob, myzip, pymaconf from mystd import mystdin, mystdout from pysender import pysender Листинг 2. Середина сценария send.py (класс pyma) classpyma: # функция инициализации – вводим переменные, # которым нужно задать значения по умолчанию def __init__(self): self.FLG_NZ = False # будем ли упаковывать файлы self.ZIPNAME = '' # имя zip-архива # Функция разбора параметров, введенных в командной строке def parseParameters(self, *argv): STOP = 0 # должно быть не менее 5 параметров iflen(argv) < 5: self.Usage() # (имя программы + еще 4) # 1-й обязательно «to» if argv[1][:2] != 'to': self.Usage() # 3-й обязательно «fi[les]» if argv[3][:2] != 'fi': self.Usage() self.TO = self.getaddrbyalias(argv[2]) # если последний параметр начинается ifargv[-1][:2] == 'no': # с «no», не упаковывать self.FLG_NZ = True STOP = -1 # если предпоследний – «as» elif argv[-2][:2] == 'as': # то последний – имя архива self.ZIPNAME = argv[-1] STOP = -2 # иначе имя архива – по 1-му файлу else: self.ZIPNAME = zn = argv[4] if zn.find('*') > -1 or zn.find('?') > -1: self.ZIPNAME = 'archive.zip' self.ZIPNAME = Unicode(self.ZIPNAME, pymaconf.fsyscodepage).encode(pymaconf.fzipcodepage) if self.ZIPNAME[-4:] != '.zip': self.ZIPNAME = self.ZIPNAME + '.zip' # все остальные параметры – шаблоны файлов ifSTOP: files = argv[4:STOP] else: files = argv[4:] if not files: self.Usage() # формируем список файлов по шаблонам self.FILELIST = [] for pattern in files: tmplist = glob.glob(pattern) for file in tmplist: if os.path.isfile(file): self.FILELIST.append(file) if not self.FILELIST: print '\nERROR: no files found.' self.Usage() # если нужно – запрос темы if pymaconf.promptsubj: tmp = raw_input('Subject: ') if tmp: pymaconf.defsubject = tmp print # если нужно – запрос сообщения ifpymaconf.promptmess: tmp = raw_input('Message: ') if tmp: pymaconf.defmessage = tmp print # Функция определения полного адреса по псевдониму def getaddrbyalias(self, addr): abf = os.path.dirname(__file__) + os.path.sep + 'addrbook.ab' ab = open(abf, 'r').readlines() aliases = {} for line in ab: alias, fulladdr = line.split() aliases[alias] = fulladdr try: fulladdr = aliases[addr] except: fulladdr= addr return fulladdr # Функция формирования и отправки сообщения def sendmail(self): self.parseParameters(*sys.argv) ifself.FLG_NZ: # если не упаковывать – отправка файлов по списку pysender().sendfiles(self.TO, self.FILELIST) else: # иначе упаковываем по списку и отправляем архив myzip.writepattzip(self.ZIPNAME, self.FILELIST) pysender().sendfiles(self.TO, (self.ZIPNAME,)) os.remove(self.ZIPNAME) # Функция вывода сообщения о правильном синтаксисе def Usage(self): print ''' Utility for send files by e-mail from command line Usage: send to files [(nonzipped | as )]''' sys.exit() send–t amsand@rambler.ru –f report.txt –z rep2.zip send to amsand@rambler.ru file report.txt as rep2.zip Листинг 3. Конец сценария send.py if __name__ == '__main__': mo = mystdout() mi = mystdin() mo.setmystdout() mi.setmystdin() nc = pyma() nc.sendmail() mo.setorigin() mi.setorigin() Листинг 4. Конфигурационный сценарий pymaconf.py # -*- coding: cp1251 -*- # Имя smtp-сервера smtpserver = 'my.server.ru' # Параметры smtp-авторизации authrequire = 0 authlogin = '' authpassword = '' # Адрес отправителя fromaddr = 'pyma.test@my.server.ru' # Запрашивать ли тему сообщения promptsubj = 1 # Тема сообщения по умолчанию defsubject = 'Отправка файла' # Запрашивать ли текст письма promptmess = 1 # Текст письма по умолчанию defmessage = 'Отправка файла\n\n\t-= pyma v.0.1 =-' # Отправлять ли копии писем на указанный адрес backmail = 1 backaddr = 'pyma.back@my.server.ru' # Параметры перекодировок basecodepage = 'cp1251' # текст в исходниках termcodepage = 'cp866' # терминал (ввод-вывод) mailcodepage = 'cp1251' # кодировка писем fsyscodepage = 'cp1251' # кодировка имен файлов в системе fzipcodepage = 'cp1251' # кодировка имени zip-архива buh ivanova@my.server.ru me amsand@rambler.ru .. .. .. abf = os.path.dirname(__file__) + os.path.sep + 'addrbook.ab' Листинг 5. Модуль pysender.py # -*- coding: cp1251 -*- import os, smtplib, pymaconf, pymalog class pysender: # Функция инициализации def __init__(self): # Разбираем файл mime-типов. mtf = os.path.dirname(__file__) + os.path.sep + 'mime.types' mt = open(mtf, 'r').readlines() self.mimetypes = {} for line in mt: mimetype, mimeext = line[:-1].split() self.mimetypes[mimeext] = mimetype # Шаблон заголовка письма, включая тело письма messagepart = '''From: %(fromaddr)s To: %(toaddr)s Subject: %(subject)s X-Mailer: PyMa 0.1 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="%(boundary)s" This is a multi-part message in MIME format. --%(boundary)s Content-Type: text/plain; charset="%(codepage)s" Content-Transfer-Encoding: Base64 %(message)s ''' # Шаблон вложения в письме attachpart = '''--%(boundary)s Content-Type: %(mimetype)s; name="%(filename)s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="%(filename)s" %(mimed)s''' # Функция возвращает mime-тип по расширению файла # Используется словарь, сформированный во время инициализации класса def getmimetypebyext(self, ext): try: mt = self.mimetypes[ext] except: mt = 'application/octet-stream' return mt # Функция формирует сообщение и отправляет его def sendfiles(self, toaddr, filelist): # заполняем словарь параметров, используемых в шаблоне param = {} param['boundary'] = '-=-=_BOUNDARY_adba_YRADNUOB_=-=-' param['fromaddr'] = pymaconf.fromaddr if pymaconf.backmail and pymaconf.backaddr: param['toaddr'] = toaddr + '\nBcc: ' + pymaconf.backaddr envtoaddr = [toaddr] envtoaddr.append(pymaconf.backaddr) else: param['toaddr'] = toaddr envtoaddr = [toaddr] param['subject'] = pymaconf.defsubject param['message'] = pymaconf.defmessage param['codepage'] = pymaconf.mailcodepage param['message'] = smtplib.base64.encodestring(param['message']) msg= self.messagepart % param # для каждого файла из списка формируем часть сообщения, объявляющего вложение files = '' print 'pysender: MIME-преобразование вложений:' for filename in filelist: files += filename + ',' param['filename'] = filename base, ext = os.path.splitext(filename) param['mimetype'] = self.getmimetypebyext(ext[1:]) print 'pysender: + %s...' % filename ist = open(filename, 'rb').read() param['mimed'] = smtplib.base64.encodestring(ist) msg = msg + (self.attachpart % param) # отправка сообщения print 'pysender: соединение с %s...' % pymaconf.smtpserver try: session = smtplib.SMTP(pymaconf.smtpserver) if pymaconf.authrequire: session.login(pymaconf.authlogin, pymaconf.authpassword) print 'pysender: выполняется отправка...' session.sendmail(pymaconf.fromaddr, envtoaddr, msg) print 'pysender: отправка завершена.' session.quit() pymalog.write('SENT: %s to %s' % (files, toaddr)) except: print 'pysender: ОШИБКА ОТПРАВКИ.' pymalog.write('ERROR: %s to %s' % (files, toaddr)) Листинг 6. Модуль pymalog.py # -*- coding: cp1251 -*- import time, os name = os.path.dirname(__file__) + os.path.sep + 'pyma.log' def write(str): dt = time.strftime('%d.%m.%Y %H:%I:%S') log = open(name, 'a+') log.write('%s: %s\n' % (dt, str)) log.close() if __name__ == '__main__': write('qwerty') Листинг 7. Модуль mystd.py # -*- coding: cp1251 -*- import sys from pymaconf import termcodepage, basecodepage # Класс переопределения потока ввода classmystdin: def readline(self): str = self.origin.readline() return unicode(str, termcodepage).encode(basecodepage) def setmystdin(self): self.origin, sys.stdin = sys.stdin, self def setorigin(self): sys.stdin = self.origin # Класс переопределения потока вывода classmystdout: def write(self, str): self.setorigin() print unicode(str, basecodepage).encode(termcodepage), self.setmystdout() def setmystdout(self): self.origin, sys.stdout = sys.stdout, self def setorigin(self): sys.stdout = self.origin Листинг 8. Изменения в модуле zipfile: close def close(self): """Close the file, and for mode "w" and "a" write the ending records.""" .. .. .. .. .. .. self.fp.write(centdir) # self.fp.write(zinfo.filename) try: fn4zip = unicode(zinfo.filename, pymaconf.termcodepage).encode('cp866') self.fp.write(fn4zip) except: self.fp.write(zinfo.filename) self.fp.write(zinfo.extra) .. .. .. .. .. .. Листинг 9. Изменения в модуле zipfile: getinfo def getinfo(self, name): """Return the instance of ZipInfo given 'name'.""" try: name = unicode(name, 'cp866').encode(pymaconf.termcodepage) except: pass return self.NameToInfo[name] Листинг 10. Изменения в модуле zipfile: _RealGetContents def _RealGetContents(self): """Read in the table of contents for the ZIP file.""" .. .. .. .. .. .. if self.debug > 2: print centdir filename = fp.read(centdir[_CD_FILENAME_LENGTH]) filename = unicode(filename, 'cp866').encode(pymaconf.termcodepage) # Create ZipInfo instance to store file information x = ZipInfo(filename) .. .. .. .. .. .. \myprogs\python\python \myprogs\utils\pyma\send.py %1 %2 %3 %4 %5 %6 %7 %8 %9 sendtome files *.py as pyma #!/usr/local/bin/python Листинг 11. Изменения в pymaconf.py для FreeBSD basecodepage = 'cp1251' termcodepage = 'koi8-r' mailcodepage = 'cp1251' fzipcodepage = 'cp1251' fsyscodepage = 'koi8-r' ----------------------------------------------------------------------------------------------------------------- Восстановление удаленных файлов под Linux Крис Касперски cp /dev/sdb1 my_dump mount my_dump mount_point -o loop cp my_dump /dev/sdb1 Листинг 1. Структура дискового тома, размеченного под ext2fs Смещение Размер Описание ------- ------- ----------- 0 1 boot record ; загрузочный сектор -- block group 0 -- ; группа блоков 0 (1024 bytes) 1 superblock ; суперблок 2 1 group descriptors ; дескриптор группы 3 1 block bitmap ; карта свободных блоков 4 1 inode bitmap ; карта свободных inode 5 214 inode table ; массив inode (сведения о файлах) 219 7974 data blocks ; блоки данных (файлы, директории) -- block group 1 -- ; группа блоков 1 8193 1 superblock backup ; копия суперблока 8194 1 group descriptors backup ; копия дескрпиора группы 8195 1 block bitmap ; карта свободных блоков 8196 1 inode bitmap ; карта свободных inode 8197 214 inode table ; массив inode (сведения о файлах) 8408 7974 data blocks ; блоки данных (файлы, директории) -- block group 2 -- ; группа блоков 2 16385 1 block bitmap ; карта свободных блоков 16386 1 inode bitmap ; карта свободных inode 16387 214 inode table ; массив inode (сведения о файлах) 16601 3879 data blocks ; блоки данных (файлы, директории) Листинг 2. Формат представления inode Смещение Размер Описание ------- ------- ----------- 0 2 i_mode ; формат представления описание 2 2 i_uid ; uid пользователя 4 4 i_size ; размер файла в байтах 8 4 i_atime ; время последнего доступа к файлу 12 4 i_ctime ; время создания файла 16 4 i_mtime ; время модификации файла 20 4 i_dtime ; время удаления файла 24 2 i_gid ; gid группы 26 2 i_links_count ; количество ссылок на файл (0 - файл удален) 28 4 i_blocks ; количество блоков, принадлежащих файлу 32 4 i_flags ; разные флаги 36 4 i_osd1 ; OS dependant value 40 12 x 4 i_block ; 12 DIRECT BLOCKS (ссылки на первые 12 блоков файла) 88 4 i_iblock ; 1x INDIRECT BLOCK 92 4 i_2iblock ; 2x INDIRECT BLOCK 96 4 i_3iblock ; 3x INDIRECT BLOCK 100 4 i_generation ; поколение файла (используется NFS) 104 4 i_file_acl ; внешние атрибуты 108 4 i_dir_acl ; higer size 112 4 i_faddr ; положение последнего фрагмента 116 12 i_osd2 ; OS dependant structure Листинг 3. Формат представления массива директорий Смещение Размер Описание ------- ------- ----------- 0 4 inode ; ссылка на inod'у 4 2 rec_len ; длина данной записи 6 1 name_len ; длина имени файла 7 1 file_type ; тип файла 8 ... name ; имя файла ----------------------------------------------------------------------------------------------------------------- Использование альтернативных потоков данных Максим Костышин NotePad C:\test.txt:example.txt NotePad C:\test.txt:example.txt type C:\boot.ini > C:\test.txt:boot.ini type C:\boot.ini > C:\test.txt:boot.ini ren temp.txt test.txt type temp.txt > test.txt del temp.txt md C:\example type C:\example.txt > c:\example:example.txt type C:\example.txt > c:\:example.txt type C:\example.doc > C:\test.txt:example.doc «C:\Program Files\Windows NT\Accessories\WordPad.exe» C:\test.txt:example.doc "C:\Program Files\Microsoft Office\Office10\WinWord.exe" C:\test:example.doc type WordPad.exe > C:\example.txt:WordPad.exe start C:\example.txt:WordPad.exe ----------------------------------------------------------------------------------------------------------------- Автоматизация процесса подключения баз 1С с помощью сценария регистрации пользователей в сети Иван Коробко [разделM] параметр1M=значение1M параметр2M =значение2M ………………………. параметрNM=значениеNM [1C] 1C_Letter=R 1C_Path=\\Server\1C_Bases$ value=ReadProfileString ("file_name", "section", "key") $FName=”config.ini” $Section=”1C” $1C_Letter_VaL = ReadProfileString($FName, $Section, “1C_Letter”) ;чтение параметра 1C_Letter $1C_Path_Val = ReadProfileString($FName, $Section, “1C_Path”) ; чтение параметра 1C_Path Use $1C_Letter_Val + ":" /delete /persistent ; отключение сетевого диска Use $1C_Letter_Val + ":" $1c_Path_Val ; подключение сетевого диска [1C] 1C_Prefix=”1C$_” [1C] 1C_Symbol=”#” … $meta = ReadProfileString($FName, $Section, “1C_Symbol”) $p=0 DO $group=EnumGoup($p) If Instr($group, $meta)<>0 ? $group End if UNTIL Len($group)=0 $1C_Letter_VaL = ReadProfileString($FName, $Section, “1C_Letter”) $1C_Group=Right($group, Len(group)-InstrRev($group,”\”)-Len($meta)) $1C_Base=$1C_Letter_VaL+”:\”+$1C_Group ; вид переменной R:\Folder_with_Base Set rootDSE_ = GetObject("LDAP://RootDSE") d_def=rootDSE_.Get("defaultNamingContext") long_Ldap_name = "LDAP://" + d_def short_WinNT_name= mid(d_def, instr(d_def,"=")+1,instr(d_def,",")-instr(d_def,"=")-1) Wscript.Echo long_Ldap_name ; имеет вид «DC=domain, DC=ru» Wscript.Echo short_ WinNT_name ; имеет вид «Domain» $1C_Group_Descr=GetObject(“WinNT://”+short_WinNT_name+”/”+$1C_Group).Description $strADSQuery = "SELECT description FROM 'LDAP://" + $long_Ldap_name + "' WHERE Name = "' + $1C_Group + "' and objectClass='group'" $objADOConn = createObject("ADODB.Connection") $objADOConn.Provider = "ADsDSOObject" $objADoConn.Open ("Active Directory Provider") $objADOCommand = CreateObject("ADODB.Command") $objADOCommand.ActiveConnection = $objADOConn $objADOCommand.CommandText = $strADSQuery $objQueryResultSet = $objADOCommand.Execute $1C_Group_Descr =$objQueryResultSet.Fields("description") $meta = ReadProfileString($FName, $Section, “1C_Symbol”) $1C_Letter_VaL = ReadProfileString($FName, $Section, “1C_Letter”) Set rootDSE_ = GetObject("LDAP://RootDSE") d_def=rootDSE_.Get("defaultNamingContext") long_Ldap_name = "LDAP://" + d_def $p=0 $q=0 Dim $1C_Must[] DO $group=EnumGoup($p) If Instr($group, $meta)<>0 $1C_Group=Right($group,Len(group)-InstrRev($group,”\”)-Len($meta)) ;вид переменной R:\Folder_with_Base $1C_Base=$1C_Letter_VaL+”:\”+$1C_Group $strADSQuery = "SELECT description FROM 'LDAP://" + $long_Ldap_name + "' WHERE Name = "' + $1C_Group + "' and objectClass='group'" $objADOConn = createObject("ADODB.Connection") $objADOConn.Provider = "ADsDSOObject" $objADoConn.Open ("Active Directory Provider") $objADOCommand = CreateObject("ADODB.Command") $objADOCommand.ActiveConnection = $objADOConn $objADOCommand.CommandText = $strADSQuery $objQueryResultSet = $objADOCommand.Execute $1C_Group_Descr =$objQueryResultSet.Fields("description") ; переопределение размера динамического массива Redim Preserve $1C_Must[$q] $1C_Must[$q]= UCase($1C_Base)+$meta+$1C_Group_Descr $q=$q+1 End if $p=$p+1 UNTIL Len($group)=0 [1C] ; по умолчанию ветвь HKCU 1C_Registry=Software\1c\1cv7\7.7\Titles $1C_Registry_Val = ReadProfileString($FName, $Section, “1C_Registry”) dim $1c_connected[] $m=0 $n=0 DO $1c_Title=EnumValue($1C_Registry_Val, $m) $1c_Name=ReadValue($1C_Registry_Val, $1c_Title) if Lcase(Left($1c_Title,1))=Lcase($1C_Letter_VaL) ReDim Preserve $1C_Connected[$n] $1C_Connected[$n]=Ucase($1c_Title)+ї $meta +$1c_Name $n=$n+1 endif $m = $m + 1 ; удаление лишних баз for $dfg=0 to ubound($1c_Сonnected) $flag_p=0 $flag_p=AScan($1c_Must, $1c_Connected[$dfg]) if $flag_p=-1 $group=$1c_Connected[$dfg] DelValue ($1c_path, ї Left($Group,Instrrev($Group,$meta)-1)) endif next ; подключение недостающих баз for $dfg=0 to ubound($1c_must) $flag_p=0 $flag_p=Ascan($1c_connected,$1c_must[$dfg]) if $flag_p=-1 $group=$1c_must[$dfg] WriteValue ($1c_Path, Left($group, ї Instrrev($group,$meta)-1), Right($group,Len($group)-Instrrev($group, $meta) - Len($meta)+1),"REG_SZ") endif next WriteValue ($1c_base+"\"+Right($group,Len($group) - Instrrev($group, $meta)-Len($meta)+1)+"\StartUp", "UserName", @userid, "REG_SZ") ----------------------------------------------------------------------------------------------------------------- Сага о биллинге, или Считаем трафик на FreeBSD (ng_ipacct + perl + MySQL) Часть 2 Владимир Чижиков # touch ng_stat_in.pl #!/usr/bin/perl -w use DBI; use Time::localtime; # cd /usr/ports/databases/p5-DBI/ # make && make install && make clean && rehash # cd /usr/ports/databases/p5-DBD-mysql # make && make install && make clean && rehash # Список основных переменных my $serverdb = "test"; my $dbname = "test"; my $dbuser = "test"; my $dbpass = "test"; my $table_auth = "test"; my $table_proto = "test"; my $listen_host = "test"; my @listen_interf; my @ng_modules; my $ng_modules_def = "netgraph,ng_ether,ng_socket,ng_tee,ng_ipacct"; my $threshold = 5000; my $ipacct_log = '/usr/local/script/ng_stat/log/ng.log'; # Проверяем время. $gm = localtime(); $year = ($gm->year()) + 1900; $mounth = ($gm->mon()) + 1; $mday = $gm->mday(); $date = "$mday-$mounth-$year"; $hour = $gm->hour(); $min = $gm->min(); $sec = $gm->sec(); $hour=sprintf("%02d",$hour); $min=sprintf("%02d",$min); $sec=sprintf("%02d",$sec); $time = "$hour\:$min\:$sec"; $table_date = "$year\_$mounth"; while (@listen_interf){ $interface = shift @listen_interf; my $pid; $pid = fork; if (defined $pid) { if ($pid == 0){ #$IPACCTCTL ${IFACE}_ip_acct:$IFACE checkpoint exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface checkpoint" or die "Ошибка передачи записи в checkpoint-базу!\n"; exit; } } else { print "Фатальная ошибка ветвления!\n.................\n"; die "Разделение на процессы невозможно.\n Принудительный выход из дочернего процесса: $!\n"; } do { $kid = waitpid $pid,0; if ($kid == -1) { print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n"; } elsif ($kid == 0) { print "Задан не блокирующий вызов и процесс еще не завершен!\n"; } } until $kid=$pid; undef $pid; $pid = fork; if (defined $pid) { if ($pid == 0){ #$IPACCTCTL ${IFACE}_ip_acct:$IFACE show >> $DIR/$SDIR/$NAME exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface show >> $ipacct_log\.$interface" or die "Ошибка передачи записей из checkpoint-базы в файл!\n"; exit; } } else { print "Фатальная ошибка ветвления!\n.................\n"; die "Разделение на процессы невозможно.\n Принудительный выход из дочернего процесса: $!\n"; } do { $kid = waitpid $pid,0; if ($kid == -1) { print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n"; } elsif ($kid == 0) { print "Задан не блокирующий вызов и процесс еще не завершен!\n"; } } until $kid=$pid; undef $pid; $pid = fork; if (defined $pid) { if ($pid == 0){ #$IPACCTCTL ${IFACE}_ip_acct:$IFACE clear exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface clear" or die "Ошибка при очистке checkpoint-базы! \nБаза не очищена. Возможно переполнение. Очистите базу в ручную\n"; exit; } } else { print "Фатальная ошибка ветвления!\n.................\n"; die "Разделение на процессы невозможно.\n Принудительный выход из дочернего процесса: $!\n"; } do { $kid = waitpid $pid,0; if ($kid == -1) { print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n"; } elsif ($kid == 0) { print "Задан не блокирующий вызов и процесс еще не завершен!\n"; } } until $kid=$pid; undef $pid; $TMPLOG= "$ipacct_log\.$interface"; open (TMPLOG, "$TMPLOG"); $TMPLOG =~ s/\||`|&&|<|>//gi; #Очистка ряда символов | ` && < > из пути к файлу. while (){ $tmp_log_line=$_; chomp $tmp_log_line; $tmp_log_line = "$tmp_log_line $date $time $listen_host $interface"; push @ipacct_arr,$tmp_log_line; } close (TMPLOG); truncate ($TMPLOG,0); undef $pid; } $tmp_log_line = "$tmp_log_line $date $time $listen_host $interface"; push @ipacct_arr,$tmp_log_line; truncate(“$TMPLOG”,0); my @ipacct_arr; my @ipacct_arr_in; open (IPCTLOG,">>$ipacct_log"); while (@ipacct_arr){ $line_arr = shift @ipacct_arr; $line_arr = "$line_arr\n"; print IPCTLOG $line_arr; } close(IPCTLOG); open (IPCTLOG,">>$ipacct_log"); while (@listen_interf){ $interface = shift @listen_interf; my $pid; $pid = fork; if (defined $pid) { if ($pid == 0){ #$IPACCTCTL ${IFACE}_ip_acct:$IFACE checkpoint exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface checkpoint" or die "Ошибка передачи записи в checkpoint-базу!\n"; exit; } } else { print "Фатальная ошибка ветвления!\n.................\n"; die "Разделение на процессы невозможно.\n Принудительный выход из дочернего процесса: $!\n"; } do { $kid = waitpid $pid,0; if ($kid == -1) { print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n"; } elsif ($kid == 0) { print "Задан не блокирующий вызов и процесс еще не завершен!\n"; } } until $kid=$pid; undef $pid; $pid = fork; if (defined $pid) { if ($pid == 0){ #$IPACCTCTL ${IFACE}_ip_acct:$IFACE show >> $DIR/$SDIR/$NAME exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface show >> $ipacct_log\.$interface" or die "Ошибка передачи записей из checkpoint-базы в файл!\n"; exit; } } else { print "Фатальная ошибка ветвления!\n.................\n"; die "Разделение на процессы невозможно.\n Принудительный выход из дочернего процесса: $!\n"; } do { $kid = waitpid $pid,0; if ($kid == -1) { print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n"; } elsif ($kid == 0) { print "Задан не блокирующий вызов и процесс еще не завершен!\n"; } } until $kid=$pid; undef $pid; $pid = fork; if (defined $pid) { if ($pid == 0){ #$IPACCTCTL ${IFACE}_ip_acct:$IFACE clear exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface clear" or die "Ошибка при очистке checkpoint-базы! \nБаза не очищена. Возможно переполнение. Очистите базу вручную\n"; exit; } } else { print "Фатальная ошибка ветвления!\n.................\n"; die "Разделение на процессы невозможно.\n Принудительный выход из дочернего процесса: $!\n"; } do { $kid = waitpid $pid,0; if ($kid == -1) { print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n"; } elsif ($kid == 0) { print "Задан не блокирующий вызов и процесс еще не завершен!\n"; } } until $kid=$pid; undef $pid; $TMPLOG= "$ipacct_log\.$interface"; open (TMPLOG, "$TMPLOG"); $TMPLOG =~ s/\||`|&&|<|>//gi; #Очистка ряда символов | ` && < > из пути к файлу. while (){ $tmp_log_line=$_; chomp $tmp_log_line; $tmp_log_line = "$tmp_log_line $date $time $listen_host $interface"; push @ipacct_arr,$tmp_log_line; } close (TMPLOG); truncate ($TMPLOG,0); undef $pid; } open (IPCTLOG,">>$ipacct_log"); while (@ipacct_arr){ $line_arr = shift @ipacct_arr; $line_arr = "$line_arr\n"; print IPCTLOG $line_arr; } close(IPCTLOG); &parse_log_file; &check_in_mysql; &insert_data_db; } sub parse_log_file { open (PARSFILE, "$ipacct_log"); while ($line_parse=) { chomp $line_parse; $line_parse =~ s/[\s\t]+/\t/g; push @ipacct_arr_in, $line_parse; } close (PARSFILE); truncate ("$ipacct_log",0); } my ($dbh,$sth,$count); $dbh = DBI->connect("DBI:mysql:host=$serverdb;database=$dbname", "$dbuser", "$dbpass") or &error_connection; $sth = $dbh->prepare("SHOW tables"); $sth->execute (); my @row; my $tables; while (@row = $sth->fetchrow_array) { foreach $tables (@row){ push @dbtables, $tables; } } $crt_tbl="yes"; while (@dbtables) { $table = shift @dbtables; if (defined $table) { if ($table eq $table_date) { $crt_tbl="no"; } } } if ($crt_tbl eq "yes") { # print "Создаем таблицу\n"; &crt_table_log; } $sth->finish; $dbh->disconnect; sub error_connection { print "Проверьте правильность имени и пароля на базу в MySQL, ее существование\n"; print "Возможной причиной ошибки также может являться то, что сервер временно недоступен\n"; print "Будет произведено копирование всех данных в файл:\n\n$ipacct_log \n\n"; print "Накопление статистики в файл не лимитировано, но это может повлечь за собой"; print " всплеск нагрузки на сеть и сервера. Поэтому обратите внимание на данное"; print " сообщение и выясните конкретную причину.\n"; foreach $line_arr(@ipacct_arr_in) { open (DUMPFILE, ">>$ipacct_log"); $line_arr = "$line_arr\n"; print DUMPFILE $line_arr; close (DUMPFILE); } die "Выход.\n"; } sub crt_table_log { my ($dbh,$sth,$count); $dbh = DBI->connect("DBI:mysql:host=$serverdb; database=$dbname", "$dbuser", "$dbpass") or &error_connection; $select = "CREATE TABLE $table_date (ip_from varchar(255),s_port varchar(128),ip_to varchar(255), d_port varchar(128), proto varchar(32), packets int(8), bytes int(16) default 0,date_ins varchar(32), time_ins time, host varchar(128), interface varchar(8), index (ip_from),index (ip_to),index (proto), index (packets), index (bytes),index (host), index (time_ins), index (date_ins), index (interface))"; $sth = $dbh->prepare("$select"); $sth->execute (); $sth->finish; $dbh->disconnect; } sub insert_data_db { my ($dbh,$sth,$count); $dbh = DBI->connect("DBI:mysql:host=$serverdb; database=$dbname","$dbuser","$dbpass") or &error_connection_in; $insert = "INSERT INTO $table_date (ip_from,s_port,ip_to,d_port,proto,packets,bytes,date_ins,time_ins,host,interface) VALUES (?,?,?,?,?,?,?,?,?,?,?)"; $sth = $dbh->prepare("$insert"); print "$insert\n"; while (@ipacct_arr_in) { $line_in = shift @ipacct_arr_in; ($ip_from, $s_port,$ip_to,$d_port,$proto,$packets, $bytes,$date_ins,$time_ins,$host,$interface)=split(/[\s\t]+/,$line_in); if (!defined $proto){ $proto="0"; } if (!defined $packets){ $packets="0"; } if (!defined $bytes){ $bytes="0"; } $sth->execute ($ip_from,$s_port,$ip_to,$d_port,$proto,$packets,$bytes,$date_ins,$time_ins,$host,$interface); } $sth->finish; $dbh->disconnect; } */15 * * * * root /usr/local/script/ng_stat/bin/ng_stat_in.pl ----------------------------------------------------------------------------------------------------------------- Защита сетевых сервисов с помощью stunnel Часть 3 Андрей Бешков countryName_default = RU stateOrProvinceName_default = Rostov region localityName = Rostov-on-Don 0.organizationName_default = Tigrisha Home emailAddress = tigrisha@unreal.net # openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout win2000key.pem -out win2000cert.pem # openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout altlinuxkey.pem -out altlinuxcert.pem # openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout freebsdkey.pem -out freebsdcert.pem # make win2000.pem # make altlinux.pem # make freebsd.pem # cat altlinuxcert.pem freebsdcert.pem > trusted.pem cert = C:\stunnel\certs\win2000cert.pem key = C:\stunnel\certs\win2000key.pem CAFile = C:\stunnel\certs\trusted.pem CRLfile = C:\stunnel\certs\crl.pem debug = 7 output = C:\stunnel\stunnel.log verify = 3 [vnc] accept = 10.10.21.46:5800 connect = 127.0.0.1:5800 [vnc-https] cert = C:\stunnel\certs\win2000cert.pem key = C:\stunnel\certs\win2000key.pem debug = 7 output = C:\stunnel\stunnel.log accept = 10.10.21.46:5900 connect = 127.0.0.1:5900 cert = /usr/local/etc/stunnel/certs/freebsdcert.pem key = /usr/local/etc/stunnel/certs/freebsdkey.pem CAFile = /usr/local/etc/stunnel/certs/trusted.pem CRLfile = /usr/local/etc/stunnel/certs/crl.pem chroot = /var/tmp/stunnel/ pid = /stunnel.pid setuid = stunnel setgid = stunnel debug = 7 output = /var/log/stunnel.log client = yes verify = 3 [vnc] accept = 127.0.0.1:5800 connect = 10.10.21.46:5800 cert = /usr/local/etc/stunnel/certs/altlinuxcert.pem key = /usr/local/etc/stunnel/certs/altlinuxkey.pem CAFile = /usr/local/etc/stunnel/certs/trusted.pem CRLfile = /usr/local/etc/stunnel/certs/crl.pem chroot = /var/tmp/stunnel/ pid = /stunnel.pid setuid = stunnel setgid = stunnel debug = 7 output = /var/log/stunnel.log client = yes verify = 3 [vnc] accept = 127.0.0.1:5800 connect = 10.10.21.46:5800 # /var/lib/ssl/misc/CA.pl -newca # /var/lib/ssl/misc/CA.pl -newreq # /var/lib/ssl/misc/CA.pl -sign CRLpath = /usr/local/etc/stunnel/certs/trusted/ CApath = /usr/local/etc/stunnel/certs/crl/ CRLpath = C:\stunnel\certs\crl\ CApath = C:\stunnel\certs\trusted\ # /var/lib/ssl/misc/c_hash / /usr/local/etc/stunnel/certs/trusted/*.pem ----------------------------------------------------------------------------------------------------------------- Мониторинг сетевых событий при помощи sguil Сергей Яремчук # groupadd sguil # useradd -g sguil -s /bin/false -c "Sguil NSM" sguil # /etc/init.d/mysqld start # mysql -u root mysql # mysql -u root -p -e "show tables" # tclsh # ./sguild -adduser sguil # ./sguild -adduser sguil # ./sguild -adduser sguil # cat /etc/sguild/sguild.users sensor 192.168.0.20 client 127.0.0.1 # ср /home/source/sguil-0.5.3/server/sguild /usr/bin # ср -R /home/source/sguil-0.5.3/server/lib /etc/sguil # sguild # ./sguil.tk -- -c /etc/sguil/sguil.conf # cd src/preprocessors # cp spp_portscan.c spp_portscan.c.bak # cp spp_stream4.c spp_stream4.c.bak # cp /sensors/snort_mods/2_1/spp_portscan_sguil.patch # cp /sensors/snort_mods/2_1/spp_stream4.patch # patch spp_portscan.c < spp_portscan_sguil.patch # patch spp_stream4.c < spp_stream4_sguil.patch preprocessor portscan: $HOME_NET preprocessor portscan: $HOME_NET 4 3 /var/snort_data/gateway/portscans syn preprocessor stream4: detect_scans, disable_evasion_alerts, keepstats db /var/snort_data/ gateway/ssn_logs output log_unified: filename snort.log, limit 128 # mkdir /var/snort_data/gateway/portscans # mkdir /var/snort_data/gateway/ssn_logs # chown -R sguil /var/snort_data # chgrp -R sguil /var/snort_data # snort -u sguil -g sguil -l /var/snort_data/ -c /etc/snort/snort.conf -U -A none -m 501 -i eth0 # cp /sensor/log_packets.sh /usr/bin/ 00 0-23/1 * * * /usr/bin/log_packets.sh restart # sguil #---- # This output plug-in is used to generate output for use # with the SGUIL user interface. To learn more about # SGUIL, go to http://sguil.sourceforge.net # output sguil: mysql, sensor_id 0, database sguildb, server syn, user sguil,password sguilpasswd, sguild_host syn, sguild_port 7736 # /usr/sbin/barnyard -c /etc/snort/barnyard.conf -d /var/snort_data/ -g /etc/snort/gen-msg.map -s /etc/snort/sid-msg.map -f snort.log -w /etc/snort/waldo.file # ./sensor_agent.tcl ----------------------------------------------------------------------------------------------------------------- Шифрование данных в Linux – новый взгляд на аппаратные ключи Александр Похабов CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_CRYPTO_AES_586=y sys-fs/cryptsetup dev-libs/openssl dev-libs/openct sys-fs/device-mapper # emerge unmerge opensc # cvs -d :pserver:cvs@cvs.opensc.org:/cvsroot login # cvs -z3 -d :pserver:cvs@cvs.opensc.org:/cvsroot co opensc # cd opensc # ./bootstrap # ./configure --prefix=/usr --exec-prefix=/usr --with-pam-dir=/путь_к/libpam --with-pam --with-openct=/путь_к/libopenct --with-openssl=/путь_к/openssl # make # make install # modprobe dm_crypt # mkdir /crypt # cd /crypt # chmod 700 /crypt # chown chiko:root /crypt # pkcs15-tool --read-public-key 45 > mykey.pub # dd if=/dev/random of=/crypt/key.plain bs=1 count=96 # openssl rsautl -encrypt -pubin -inkey mykey.pub -in /crypt/key.plain -pkcs -out /crypt/key # rm /crypt/key.plain # rm /crypt/mykey.pub # pkcs15-crypt --raw --pkcs1 --decipher -k 45 -i /crypt/key # dd if=/dev/urandom of=/dev/sda1 bs=1M count=240 # dd conv=notrunc if=/dev/zero of=/dev/sda1 bs=1024 count=1024 # dd conv=notrunc if=/crypt/key of=/dev/sda1 bs=1 # md5sum /crypt/key # rm /crypt/key # dd if=/dev/sda1 bs=1 count=128 of=/crypt/key # md5sum /crypt/key # pkcs15-crypt --raw --pkcs1 --decipher -k 45 -i /crypt/key | cryptsetup --hash=plain --cipher=aes --key-size=256 --offset=2048 create mynewhome /dev/sda1 # mkfs.ext2 /dev/mapper/mynewhome # mount /dev/mapper/mynewhome /home/chiko # chown –R chiko:root /home/chiko # umount /home/chiko # cryptsetup remove mynewhome # rm /crypt/key #cat /etc/security/pam_mount.conf debug 0 # При возникновении ошибок будет полезно иметь вывод: debug 1 options_allow nosuid,nodev,loop,encryption # Здесь и строкой ниже по желанию options_require nosuid,nodev lsof /usr/sbin/lsof %(MNTPT) fsck /bin/true # Для FLASH-накопителя с ext2fs не счел нужным проверять fsck.ext2 losetup /bin/true [пс] unlosetup /bin/true [пс] cifsmount /bin/mount -t cifs //%(SERVER)/%(VOLUME) %(MNTPT) -o "username=%(USER)%(before=\",\" OPTIONS)" smbmount /bin/mount -t smbfs //%(SERVER)/%(VOLUME) %(MNTPT) -o "username=%(USER)%(before=\",\" OPTIONS)" ncpmount /bin/mount -t ncpfs %(SERVER)/%(USER) %(MNTPT) -o "pass-fd=0,volume=%(VOLUME)%(before=\",\" OPTIONS)" umount /bin/umount %(MNTPT) lclmount /sbin/mount.crypt %(VOLUME) %(MNTPT) -o %(OPTIONS) # Не забудьте заменить /sbin/mount.crypt скриптом из Debian cryptmount /sbin/mount.crypt %(VOLUME) %(MNTPT) -o %(OPTIONS) nfsmount /bin/mount %(SERVER):%(VOLUME) "%(MNTPT)%(before=\"-o \" OPTIONS)" pmvarrun /usr/sbin/pmvarrun -u %(USER) -d -o %(OPERATION) # Строка, описывающая имя пользователя, раздел, точку и опции монтирования volume chiko crypt - /dev/sda1 /home/chiko loop,cipher=aes - - # В самом начале добавьте строку read PIN LOSETUP=/sbin/losetup CRYPTSETUP=/bin/cryptsetup MOUNT=/bin/mount OPTIONS="" read PIN # Таким образом передаем PIN в pkcs15-crypt USAGE="dev dir [-o options] # Найдите и закомментируйте, как в примере, четыре следующие строки: #HASHOPT="ripemd160" #if [ -n "$HASH" ]; then # HASHOPT="$HASH" #fi # Вместо них подставьте свои: HASHOPT="" if [ ! -z "$HASH" ]; then HASHOPT="-h $HASH" fi KEYSIZEOPT="256" if [ -n "$KEYSIZE" ]; then KEYSIZEOPT="$KEYSIZE" fi # Сразу же после KEYSIZEOPT-секции добавляем три новых строки: dd if=/dev/sda1 bs=1 count=128 of=/crypt/key /usr/local/bin/pkcs15-crypt --raw -p $PIN --pkcs1 --decipher -k 45 -i /crypt/key | $CRYPTSETUP --cipher=aes --hash=plain --key-size=256 --offset=2048 create $DMDEVICE $DEVICE rm /crypt/key # Следующую строку из оригинала закомментируем, так как выше используем собственный аналог: #$CRYPTSETUP -c $CIPHEROPT -h $HASHOPT -s $KEYSIZEOPT create $DMDEVICE $DEVICE # cat /etc/pam.d/login #%PAM-1.0 auth optional pam_mount.so auth required /usr/local/lib/security/pam_opensc.so use_first_pass session optional pam_mount.so use_first_pass account required /lib/security/pam_stack.so service=system-auth session required /lib/security/pam_stack.so service=system-auth pam_mount: reading options_allow... pam_mount: reading options_require... pam_mount: back from global readconfig pam_mount: per-user configurations not allowed by pam_mount.conf pam_mount: real and effective user ID are 0 and 0. pam_mount: checking sanity of volume record (/dev/sda1) pam_mount: about to perform mount operations pam_mount: information for mount: pam_mount: -------- pam_mount: (defined by globalconf) pam_mount: user: chiko pam_mount: server: pam_mount: volume: /dev/sda1 pam_mount: mountpoint: /home/chiko pam_mount: options: loop,cipher=aes pam_mount: fs_key_cipher: pam_mount: fs_key_path: pam_mount: use_fstab: pam_mount: -------- pam_mount: checking to see if /dev/mapper/_dev_sda1 is already mounted at /home/chiko pam_mount: checking for encrypted filesystem key configuration pam_mount: about to start building mount command pam_mount: command: /crypt/mount.crypt /dev/sda1 /home/chiko -o loop,cipher=aes /home/chiko pam_mount: mount errors (should be empty): pam_mount: 128+0 records in pam_mount: 128+0 records out pam_mount: waiting for mount pam_mount: clean system authtok (0) pam_mount: command: /usr/sbin/pmvarrun -u chiko -d -o 1 pam_mount: pmvarrun says login count is 1 pam_mount: done opening session # mount | grep mapper ----------------------------------------------------------------------------------------------------------------- Система создания документации POD Часть 1 Алексей Мичурин Конвертировать EPS-файл в любой другой формат можно программой C, имеющей неисчислимое множество опций и возможностей. Пример: gs -sDEVICE=png16 \ -sOutputFile=drag.png \ -dBATCH \ -dNOPAUSE \ -r72x72 \ -sPAPERSIZE=a5 \ drag.eps =pod Привет от POD. =cut =pod Привет от POD. =cut =head1 Алгоритмы построения Приведу здесь два алгоритма, отличающихся принципиально. =head2 Итерационный алгоритм построения дракона Настоящая программа использует именно этот алгоритм. Всё построение ведёт подпрограмма C. Она получает следующие параметры: =over =item $x, $y Первый и второй E координаты начала вектора. =item $dx, $dy Третий и четвёртый E координаты самого вектора. =item $d Текущая глубина рекурсии. =back pod2text input.pod >output.txt Часть текста можно выделить I<курсивом>, некоторые фрагменты - B<полужирным шрифтом> или C<моноширинным шрифтом>. S<Ситникова О.В.> S<5 кг.> B10A> B<< I>10A >> C<<< cat part >> file2append >>> C<< cat part >> file2append >> << cat part >Z<>> file2append >> B10A> EZ<><60> #!/usr/bin/sed -f s/E/--/g s/E/ градусов/g ./antiescape file.pod | pod2text >file.text #!/usr/bin/perl undef $/; $_=<>; %h=(); $c=0; s/href="#(.+?)"/$c++; $h{$1}=$c; qq|href="#$c"|/ge; s/name="(.+?)"/"name=\"".($h{$1}?$h{$1}:$1)."\""/ge; print; pod2html file.pod | antirus.pl > file.html =pod =head1 Глава I L<это ссылка на Главу I|/"Глава I"> =for html
=begin html
=end html =for html
=begin html =end html =for html pod2html --css file.css file.pod >file.html #!/usr/bin/perl undef $/; $_=<>; s|| |; print;

текст заголовка

----------------------------------------------------------------------------------------------------------------- Программирование на shell в экстремальных условиях Гаспар Чилингаров cut_atomic () { local DELIM STRING # разделитель может быть любой строкой, не только один символ DELIM="$1" shift # оставшиеся аргументы STRING=$* result=${STRING%%${DELIM}*} return 0 } cut -d${разделитель} -f${начальное_поле} -${конечное_поле} cut () { local DELIM POS1 POS2 STRING STR1 POSTFIX DELIM="$1" # разделитель POS1=$2 # начальный индекс POS2=$3 # конечный индекс shift 3 STRING=$* # оставшиеся параметры функции # если конечный индекс меньше начального, возвращаем ошибку if [ $POS2 -lt $POS1 ]; then result="" return 1 # код выхода > 0 fi # удаляем первые ${POS1}-1 элементов из строки I=1 while [ $I -lt $POS1 ]; do STRING=${STRING#*${DELIM}} I=$(($I+1)) done STR1="$STRING" # запоминаем результат # удаляем все элементы вплоть до последнего элемента, который нам нужен, от строки оставляем суффикс, # состоящий из ненужных элементов while [ $I -le $POS2 ]; do STRING=${STRING#*${DELIM}} I=$(($I+1)) done # у нас уже есть ненужный суффикс с переменной STRING, удаляем его из запомненного результата result=${STR1%${DELIM}${STRING}} return 0 } extract_manufacturer () { # определяем IFS как локальную переменную, чтобы ее изменение не влияло на другие функции local STR IFS # запоминаем все аргументы функции в STR STR=$* # устанавливаем в качестве разделителя символ ':' IFS=':' # присваиваем позиционным параметрам содержимое STR set -- $STR result="$1:$2:$3" return 0 } # пример использования функции S=`ifconfig fxp0` # получить результат работы команды ifconfig S=${S##*ether} # стереть вплоть до ключевого слова ether extract_manufacturer "$S" echo "manufacturer code: $result" match_pattern_strict () { local PATTERN STRING # двойные кавычки обязательны, чтобы не происходило раскрытие символов подстановки PATTERN="$1" shift STRING=$* result="" case "$STRING" in $PATTERN) # полное соответствие шаблону return 0 esac return 1 } match_pattern() { local PATTERN STRING PATTERN="$1" shift STRING=$* result="" case "$STRING" in *${PATTERN}*) # проверяется соответствие шаблону return 0 # части строки esac return 1 } match_pattern_strict '[0-9]*.[0-9]*.[0-9]*.*[0-9]' 192.168.0.1 # посчитать количество элементов в массиве # arr_count ИМЯ_МАССИВА ИМЯ_КЛЮЧА arr_count () { local ARRNAME KEYNAME VAL I ARRNAME=$1 # имя массива KEYNAME=$2 # имя ключа в массиве I=0 result="" # основная магия происходит здесь – в команде eval формируется правильное название переменной, # которая соответствует элементу массива eval VAL=\${${ARRNAME}_${I}_${KEYNAME}} if [ "x$VAL” = "x" ];then # если первый же ключ пустой (т.е. foo[0][A]) мы предполагаем, что такой массив не существует return 1 fi while [ "x$VAL" != "x" ] ; do I=$(($I+1)) eval VAL=\${${ARRNAME}_${I}_${KEYNAME}} done result=$I return 0 } eval VAL=\${foo_1_bar}, # array_name ИМЯ_МАССИВА ИМЯ_КЛЮЧА ИМЯ_ПОЛЯ # ЗНАЧЕНИЕ_КЛЮЧА arr_lookup_by_key () { local i array kfield vfield kvalue key value array=$1 kfield=$2 vfield=$3 kvalue=$4 i=0 result="" key="x" # принудительно заставим цикл выполнится хотя бы 1 раз while [ "$key" != "" ]; do # конструируем имя переменной eval key=\${${array}_${i}_${kfield}} # если значение ключа совпало, возвращаем значение if [ "$key" = "$kvalue" ]; then # конструируем имя возвращаемого поля eval result=\${${array}_${i}_${vfield}} return 0 fi i=$(($i+1)) done # цикл закончился – следовательно такого значения ключа нет return 1 } # arr_lookup_by_index ИМЯ_МАССИВА ИМЯ_КЛЮЧА ИМЯ_ПОЛЯ ИНДЕКС arr_lookup_by_index () { local i array index vfield value kfield array=$1 kfield=$2 vfield=$3 kvalue=$4 eval key=\${${array}_${index}_${kfield}} if [ "$key" = "" ]; then # возвратить код ошибки, т.к. обнаружен пустой ключ return 1 fi eval result=\${${array}_${index}_${vfield}} return 0 } # arr_set_by_index ИМЯ_МАССИВА ИМЯ_КЛЮЧА ИМЯ_ПОЛЯ НОМЕР_ИНДЕКСА ЗНАЧЕНИЕ_КЛЮЧА ЗНАЧЕНИЕ_ПОЛЯ arr_set_by_index() { local i array kfield vfield index kvalue value array=$1 kfield=$2 vfield=$3 index=$4 kvalue=$5 shift 5 vvalue=$* i=0 result="" eval ${array}_${index}_${kfield}=${kvalue} eval ${array}_${index}_${vfield}=${vvalue} return 0 } # arr_set_by_key ИМЯ_МАССИВА ИМЯ_КЛЮЧА ИМЯ_ПОЛЯ ЗНАЧЕНИЕ_КЛЮЧА ЗНАЧЕНИЕ_ПОЛЯ arr_set_by_key() { local i array kfield vfield kvalue vvalue array=$1 kfield=$2 vfield=$3 kvalue=$4 shift 4 vvalue=$* result="" i=0 eval key=\${${array}_${i}_${kfield}} while [ "x$key" != "x" ]; do eval key=\${${array}_${i}_${kfield}} if [ "x$key" = "x$kvalue" ]; then break fi i=$(($i+1)) done arr_set_by_index $array $kfield $vfield $i $kvalue $vvalue return 0 } IFS=: i=0 while read name pass uid gid gcos homedir shell junk; do echo "$i|$name|$uid|$gid|$gcos|$homedir|$shell|$junk|" i=$(($i+1)) done < /etc/passwd echo "total lines: $i" while read name pass uid gid gcos homedir shell junk < /etc/passwd; do ... done cat /etc/passwd | while read name pass uid gid gcos homedir shell junk; do echo "$i|$name|$uid|$gid|$gcos|$homedir|$shell|$junk|" i=$(($i+1)) done echo "total lines: $i" IFS=: i=0 while read name pass uid gid gcos homedir shell junk; do echo "$i|$name|$uid|$gid|$gcos|$homedir|$shell|$junk|" i=$(($i+1)) done < cache_len) (cache_len - (addr % cache_len)) Листинг 1. Формула для расчета оптимальной кратности выравнивания для процессоров Intel Pentium II и выше if ((addr % cache_len + sizeof(ops)) > cache_len) align = cache_len – (addr % cache_len); Листинг 2. Если выражение (a == b) истинно, выражение (c == d) уже не проверяется if ((a == b) || (c == d))… Листинг 3. Неоптимизированный вариант if (n > 10) a++; else return 0; if (n > 5) a++; else return 0; // избыточная проверка if (n < 2) a++; else return 0; // заведомо ложна проверка Листинг 4. Оптимизированный вариант if (n > 10) a+=2; else return 0; Листинг 5. Неоптимизированный вариант f1(int *p) { // проверка №2 (может быть удалена компилятором т.к. ей предшествовала запись по указателю) if (p) return *p+1; else return –1; } f2(int *p) { // проверка №1/запись по указателю if (p) *p = 0x69; else return -1; return f1(p); } Листинг 6. Неоптимизированный вариант, 2 проверки if (CPU_TYPE == AMD) // проверка x = AMD_f1(y); else x = INTEL_f1(y); … if (CPU_TYPE == AMD) // еще одна проверка a = AMD_f2(b); else a = INTEL_f2(b); Листинг 7. Оптимизированный вариант, только одна проверка if (CPU_TYPE == AMD) // только одна проверка { x = AMD_f1(y); a = AMD_f2(b); } else { x = INTEL_f1(y); a = INTEL_f2(b); } Листинг 8. Неоптимизированный вариант goto lab_1 ; // переход к метке lab_1 на безусловный переход к метке lab_2 …. lab_1: goto lab_2 ; // переход к метке lab_2 …. lab_2: Листинг 9. Оптимизированный вариант goto lab_2 ; // сразу переходим к метке lab_2, минуя lab_1 …. lab_1: goto lab_2 ; // переход к метке lab_2 …. lab_2: Листинг 10. Неоптимизированный вариант while(a) // lab_1: if (!a) goto lab_4 { while(b) // lab_2: if (!b) goto lab_3 /* переход на безусловный переход */ { /* код цикла */ } // goto lab_2 } // lab_3: goto lab_1 // lab_4: Листинг 11. Оптимизированный вариант while(a) // lab_1: if (!a) goto lab_4 { while(b) // lab_2: if (!b) goto lab_1 /* оптимизировано */ { /* код цикла */ } // goto lab_2 } // lab_3: goto lab_1 // lab_4: Листинг 12. Неоптимизированный вариант jmp lab_1 ; // переход на условный переход … lab_1: jnz lab_2 Листинг 13. Оптимизированный вариант jnz lab_2 ; // оптимизировано … lab_1: jnz lab_2 Листинг 14. Трансформация условных переходов, до которых процессор не может «дотянуться» jz far_far_away jnz next_lab ———трансформация—————> jmp far_far_away next_lab: Листинг 15. Неоптимизированный вариант f(int a, int b) { while(a--) { if (a == b) break; // условный переход на return a; } return a; } Листинг 16. Оптимизированный вариант f(int a, int b) { while(a--) { if (a == b) return a; //непосредственный return a; } return a; } Листинг 17. Неоптимизированный вариант if (x) a=a*2; else goto lab_1; // двойное ветвление if – else b=a+1 lab_1: c=a*10 Листинг 18. Оптимизированный вариант if (!x) goto lab_1; // одинарное ветвление a=a*2; b=a+1; lab_1: c=a*10; Листинг 19. Неоптимизированный вариант, 2 ветвления while(1) { if (a==0x66) break; // условный переход a=a+rand(); }; // скрытый безусловный переход на начало цикла Листинг 20. Оптимизированный вариант, 1 ветвление (ветвление перед началом цикла не считается, т.к. исполняется всего лишь раз) if (a!=0x66) // «сдирание» одной итерации цикла do{ a=a+rand(); }while(a!=0x66); // инвертируем переход, только одно ветвление Листинг 21. Сравнение двух чисел на языке ассемблера cmp eax,ebx // сравниваем eax с ebx, запоминая результат во флагах jl lab_1 // переход, если eax < ebx jg lab_2 // переход, если eax > ebx lab_3: // раз мы здесь, eax == ebx Листинг 22. Сравнение двух чисел на языке высокого уровня if (a < 0x69) printf("b"); if (a > 0x69) printf("g"); if (a == 0x69) printf("e"); Листинг 23. Поиск максимума среди двух целых чисел без использования ветвлений SUB b, a ; отнять от содержимого 'b' значение 'a', записав результат в 'b', если a > b, то процессор установит флаг заема в единицу SBB c, c ; отнять от содержимого 'c' значение 'c' с учетом флага заема, записав результат обратно в 'c' ('c' – временная переменная). ; Если a <= b, то флаг заема сброшен, и 'c' будет равно 0. Если a > b, то флаг заема установлен и 'c' будет равно -1 AND c, b ; выполнить битовую операцию (c & b), записав результат в 'c'. Если a <= b, то флаг заема равен нулю, 'c' равно 0, ; значит, с =(c & b) == 0, в противном случае: c == b - a ; ADD a, c ; выполнить сложение содержимого 'a' со значением 'c', записав результат в 'a'. ; если a <= b, то c = 0 и a = a ; если a > b, то c = b - a, и a = a + (b-a) == b Листинг 24. Неоптимизированный вариант с ветвлениями short a[4], b[4], c[4]; for (i=0; i<4; i++) c[i] = a[i] > b[i] ? a[i] : b[i]; Листинг 25. Устранение ветвлений путем использования функции select_gt библиотеки классов Intel SIMD Is16vec4 a, b, c // функция векторного поиска максимума без ветвлений c = select_gt(a, b, a, b); Листинг 26. Неоптимизированный вариант оператора множественного выбора switch (a) { case 98 : /* код обработчика */ break; case 4 : /* код обработчика */ break; case 3 : /* код обработчика */ break; case 9 : /* код обработчика */ break; case 22 : /* код обработчика */ break; case 0 : /* код обработчика */ break; case 11 : /* код обработчика */ break; case 666: /* код обработчика */ break; case 96 : /* код обработчика */ break; case 777: /* код обработчика */ break; case 7 : /* код обработчика */ break; } Листинг 27. Неоптимизированный switch, организованный по принципу упорядоченной арифметической прогрессии switch (a) { case 1 : /* код обработчика */ break; case 2 : /* код обработчика */ break; case 3 : /* код обработчика */ break; case 4 : /* код обработчика */ break; case 5 : /* код обработчика */ break; case 6 : /* код обработчика */ break; case 7 : /* код обработчика */ break; case 8 : /* код обработчика */ break; case 9 : /* код обработчика */ break; case 10 : /* код обработчика */ break; case 11 : /* код обработчика */ break; } Листинг 28. Дизассемблерный листинг оптимизированного варианта оператора switch cmp eax, 0Bh ; switch 12 cases ; сравниваем a с 11 ja short loc_80483F5 ; default ; если a > 11 выходим из оператора switch ; jmp ds:off_804857C[eax*4] ; switch jump ; передаем управление соответствующему case-обработчику, таким образом, мы имеем всего лишь ; одно сравнение и два ветвления ; // таблица смещений case-обработчиков off_804857C dd offset loc_80483F5 ; DATA XREF: main+11­r dd offset loc_80483E8 ; jump table for switch statement dd offset loc_80483F9 dd offset loc_8048402 dd offset loc_804840B dd offset loc_8048414 dd offset loc_804841D dd offset loc_8048426 dd offset loc_804842F dd offset loc_8048438 dd offset loc_8048441 dd offset loc_804844F Листинг 29. Неоптимизированный switch, организованный по принципу упорядоченной арифметической прогрессии switch (a) { case 11 : /* код обработчика */ break; case 2 : /* код обработчика */ break; case 13 : /* код обработчика */ break; case 4 : /* код обработчика */ break; case 15 : /* код обработчика */ break; case 6 : /* код обработчика */ break; case 17 : /* код обработчика */ break; case 8 : /* код обработчика */ break; case 19 : /* код обработчика */ break; case 10 : /* код обработчика */ break; case 21 : /* код обработчика */ break; }