Всеволод Стахов Хеви Хадвеер Установка и настройка коммутаторов CISCO CATALYST vconfig set_name_type [name-type] - тип наименования виртуальных устройств, может принимать следующие значения: VLAN_PLUS_VID имя устройства будет выглядеть так: vlan0005 VLAN_PLUS_VID_NO_PAD имя устройства будет выглядеть так: vlan5 DEV_PLUS_VID имя устройства будет выглядеть так: eth0.0005 DEV_PLUS_VID_NO_PAD(по умолчанию) имя устройства будет выглядеть так: eth0.5 # ifconfig eth0 0.0.0.0 up # vconfig add eth0 2 # vconfig add eth0 3 # ifconfig -a # ifconfig -i vlan0002 192.168.2.1 broadcast 192.168.2.255 netmask 255.255.255.0 up # ifconfig -i vlan0003 192.168.3.1 broadcast 192.168.3.255 netmask 255.255.255.0 up # echo 1 > /proc/sys/net/ipv4/ip_forward # vconfig rem vlan0002 >enable #rename flash:config.text flash:ДРУГОЕ_ИМЯ.text #reload (config)# interface FastEthernet x/x (нужный вам порт), затем вы в режиме конфигурации порта - (config-if)# switchport access vlan ID - единственная vlan switchport multi vlan ID, ID, ID или switchport multi vlan ID-ID, ID-ID, ID - список допустимых vlan switchport trunk allowed vlan LISTID - допустимые для магистрали vlan(по умолчанию 1-1005) prunning vlan LISTID - фильтрация широковещательного трафика между vlan encapsulation - тип пакета(disl или dot1q - IEEE 802.1q) native vlan ID - для trunk магистрали типа IEEE 802.1q номер vlan, для которой не изменяется формат пакета (по умолчанию 1 vlan) switchport access vlan ID - единственная vlan switchport multi vlan ID, ID, ID или switchport multi vlan ID-ID, ID-ID, ID - список допустимых vlan switchport trunk allowed vlan LISTID - допустимые для магистрали vlan(по умолчанию 1-1005) prunning vlan LISTID - фильтрация широковещательного трафика между vlan encapsulation - тип пакета(disl или dot1q - IEEE 802.1q) native vlan ID - для trunk магистрали типа IEEE 802.1q номер vlan, для которой не изменяется формат пакета (по умолчанию 1 vlan) switchport access vlan ID - единственная vlan switchport multi vlan ID, ID, ID или switchport multi vlan ID-ID, ID-ID, ID - список допустимых vlan switchport trunk allowed vlan LISTID - допустимые для магистрали vlan(по умолчанию 1-1005) prunning vlan LISTID - фильтрация широковещательного трафика между vlan encapsulation - тип пакета(disl или dot1q - IEEE 802.1q) native vlan ID - для trunk магистрали типа IEEE 802.1q номер vlan, для которой не изменяется формат пакета (по умолчанию 1 vlan) no switchport multi vlan ... no switchport mode multi (config-if)#exit (config)#exit #show running-config #write memory - если надо записать настройки #vlan database (vlan)# (vlan)#show - для показа состояния vlan на данном свитче: (vlan)#vlan ID ? - список возможных настроек: vlan database vtp domain domain-name vtp password password-value vtp server(client) exit show vtp status # vlan database (vlan)# vtp domain Avitek Установка имени домена Avitek (vlan)# vtp domain Avitek password LAVA Установка пароля для данного домена. (vlan)# vtp server Включение режима VTP сервера. (vlan)# exit Настройки применены. Выходим.... # show vtp status VTP Version : 2 Configuration Revision : 0 Maximum VLANs supported locally : 68 Number of existing VLANs : 6 Вячеслав Калошин Удобная почтовая система # tar zxvf cyrus-sasl-1.5.27.tar.gz # cd cyrus-sasl-1.5.27. # patch -b -p1 < sasl-ldap+mysql.patch # autoheader # autoconf # automake -i. # ./configure —with-mysql=/usr/include/mysql —enable-login. # make # make install # ln -s /usr/local/lib/sasl /usr/lib/sasl # echo /usr/lib/sasl >> /etc/ld.so.conf # ldconfig # cd .. # cat > /usr/local/lib/sasl/smtpd.conf pwcheck_method: mysql mysql_user: postfix mysql_passwd: postfix mysql_host: localhost mysql_database: mail mysql_table: aliases mysql_uidcol: alias mysql_pwdcol: password ^D # tar zxvf postfix-1.1.11.tar.gz # cd postfix-1.1.11. # make -f Makefile.init makefiles «CCARGS=-DHAS_MYSQL -DUSE_SASL_AUTH -I/usr/include/mysql -I/usr/local/include -L /usr/local/lib -lsasl -lmysqlclient» # make # adduser postfix # groupadd postdrop # make install install _ root: [/] tempdir: [/usr/src/post/postfix- 1.1.11] /tmp config_directory: [/etc/postfix] daemon_directory: [/usr/libexec/postfix] command_directory: [/usr/sbin] queue_directory: [/var/spool/postfix] sendmail_path: [/usr/sbin/sendmail] newaliases_path: [/usr/bin/newaliases] mailq_path: [/usr/bin/mailq] mail_owner: [postfix] setgid_group: [postdrop] manpage_directory: [/usr/local/man] sample_directory: [/etc/postfix] readme_directory: [no] # cd /etc/postfix/ # mcedit main.cf broken_sasl_auth_clients = yes smtpd_sasl_auth_enable = yes transport_maps = mysql:/etc/postfix/transport.cf virtual_mailbox_base = / virtual_uid_maps = mysql:/etc/postfix/ids.cf virtual_gid_maps = mysql:/etc/postfix/gids.cf virtual_mailbox_maps = mysql:/etc/postfix/aliases.cf virtual_maps = mysql:/etc/postfix/remote_aliases.cf relay_domains = $transport_maps smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated,check_relay_domains disable_vrfy_command = yes # cat > transport.cf user = postfix password = postfix dbname = mail table = transport select_field = transport where_field = domain hosts = localhost ^D # cat > ids.cf user = postfix password = postfix dbname = mail table = aliases select_field = id where_field = alias hosts = localhost ^D # cat > gids.cf user = postfix password = postfix dbname = mail table = aliases select_field = gid where_field = alias hosts = localhost ^D. # cat > aliases.cf user = postfix password = postfix dbname = mail table = aliases select_field = maildir where_field = alias hosts = localhost ^D # cat > remote_aliases.cf user = postfix password = postfix dbname = mail table = remote_aliases select_field = rcpt where_field = alias hosts = localhost ^D # postfix check. mysql> create database mail; Query OK, 1 row affected (0.62 sec) mysql> grant insert, select, delete, update on mail.* to postfix@localhost identified by «postfix»; Query OK, 0 rows affected (0.72 sec) mysql> use mail; Database changed mysql> create table transport (domain varchar(255) PRIMARY KEY, transport char(8)); Здесь будет храниться информация о доменах, обслуживаемых postfix. mysql> create table aliases (id int(6), gid int(6), alias varchar(255) PRIMARY KEY, maildir varchar(255), password varchar(128), infovarchar(128)); Здесь информация о почтовых пользователях системы. mysql> create table remote_aliases (alias varchar(255) PRIMARY KEY, rcptvarchar(255)); А здесь информация о почтовых переадресациях и прочем. Небольшие списки рассылки тоже можно включать сюда. # mysql -u postfix –p # postfix start postfix/postfix-script: starting the Postfix mail system mysql> insert into transport values (“test.ru”,’virtual:’); mysql> insert into aliases values(1000,12,’multik@test.ru’,’/var/spool/vmail/test.ru_multik/’,’testpassword’,’info’); # mkdir /var/spool/vmail # chown nobody.mail /var/spool/vmail # chmod 770 /var/spool/vmail $ telnet localhost 25 Trying 127.0.0.1... Connected to localhost. Escape character is “^]”. 220 mail.test.ru ESMTP Postfix mail from: multik@test.ru 250 Ok rcpt to: multik@test.ru 250 Ok data 354 End data with . hello . 250 Ok: queued as 252BFEEAE6 Jun 28 16:24:21 multik postfix/smtpd[21863]: connect frommultik.ip-tel.int[127.0.0.1] Jun 28 16:24:23 multik postfix/smtpd[21863]: 252BFEEAE6: client=multik.ip-tel.int[127.0.0.1] Jun 28 16:24:32 multik postfix/cleanup[21919]: 252BFEEAE6:message-id=<20020628122423.252BFEEAE6@mail.test.ru> Jun 28 16:24:32 multik postfix/qmgr[21762]: 252BFEEAE6: from=,size=340, nrcpt=1 (queue active) Jun 28 16:24:32 multik postfix/virtual[21921]: 252BFEEAE6: to=,relay=virtual, delay=9, status=sent (maildir) # ls -lR /var/spool/vmail /var/spool/vmail: итого 4 drwx——— 5 1000 mail 4096 Июн 28 16:26 test.ru_multik /var/spool/vmail/test.ru_multik: итого 12 drwx——— 2 1000 mail 4096 Июн 28 16:26 cur drwx——— 2 1000 mail 4096 Июн 28 16:26 new drwx——— 2 1000 mail 4096 Июн 28 16:26 tmp /var/spool/vmail/test.ru_multik/cur: итого 0 /var/spool/vmail/test.ru_multik/new: итого 4 -rw——— 1 1000 mail 389 Июн 28 16:261025267217.21935_0.multik.ip-tel.int /var/spool/vmail/test.ru_multik/tmp: итого 0 # tar zxvf courier-imap-1.5.1.tar.gz # adduser courier # chown courier.courier courier-imap-1.5.1 # cd courier-imap-1.5.1 # su - courier # cd /{куда распаковывали}/courier-imap-1.5.1 # ./configure # make # authlib/authinfo AUTHENTICATION_MODULES=«authdaemon» AUTHDAEMONMODULELIST=«authcustom authcram authmysql authuserdb authpam» SASL_AUTHENTICATION_MODULES=«CRAM-SHA1 CRAM-MD5 PLAIN LOGIN» # exit # make install # make install_configure # cd /usr/lib/courier-imap/etc/ # cp authdaemonrc.dist authdaemonrc authmodulelist=«authcustom authcram authuserdb authmysql authpam» authmodulelist=«authmysql» # cat > authmysqlrc MYSQL_SERVER localhost MYSQL_USERNAME postfix MYSQL_PASSWORD postfix MYSQL_PORT 3306 MYSQL_DATABASE mail MYSQL_USER_TABLE aliases MYSQL_CLEAR_PWFIELD password DEFAULT_DOMAIN test.ru MYSQL_UID_FIELD id MYSQL_GID_FIELD gid MYSQL_LOGIN_FIELD alias MYSQL_HOME_FIELD maildir MYSQL_NAME_FIELD info MYSQL_MAILDIR_FIELD maildir ^D /usr/lib/courier-imap/libexec/pop3d.rc startъ # telnet localhost 110 Trying 127.0.0.1... Connected to localhost. Escape character is “^]”. +OK Hello there. user multik@test.ru +OK Password required. pass testpassword +OK logged in. list+ OK POP3 clients that break here, they violate STD53. 1 400 . quit +OK Bye-bye. Connection closed by foreign host. Jun 28 17:27:17 multik pop3d: LOGIN, user=multik@test.ru, ip=[::ffff:127.0.0.1] Jun 28 17:27:24 multik pop3d: LOGOUT, user=multik@test.ru,ip=[::ffff:127.0.0.1], top=0, retr=0 drweb-4.28.1-linux.tgz drweb-postfix-4.28.4-linux.tgz # cd /opt/drweb # ./drweb Key file: /opt/drweb/drweb.key Registration info: 0100003942 Evaluation Key (ID Anti-Virus Lab. Ltd, St.Petersburg) This is an EVALUATION version with limited functionality! To get your registration key, call regional dealer. Loading /var/drweb/bases/drwebase.vdb - Ok, virus records: 29405 # adduser drweb # mkdir /var/spool/drweb # chown drweb.drweb /var/spool/drweb # chmod 770 /var/spool/drweb smtp inet n - n - 50 smtpd - ocontent_filter=filter: dummy filter unix - n - n - pipe flags=R user=drweb argv=/opt/drweb/drweb -postfix -f ${sender} — ${recipient} SkipObject = pass Я хочу пропускать те обьекты, которые drweb не переваривает. MailbombObject = pass Один из доменов, который обслуживается у меня, принадлежит дизайнерам и прочему художественному люду. Они очень обожают кидаться друг в друга архивами с картинками, которые сжаты очень сильно. DrWeb обычно считает такие письма за мэйлбомбы. AdminMail = root@test.ru Кто тут у нас администратор. FilterMail = DrWeb-DAEMON@ip-tel.ru И от кого будет приходить почта с руганью и прочими сообщениями. Далее везде: SenderNotify = no Не надо извещать посылателя писем - в 90% случаев это безполезно и лишь забивает почтовые каналы. Если отправитель известен адресату, то он сам напишет ему гневное письмо. cd /var/drweb chown -R drweb.drweb * /etc/init.d/drwebd start Starting Dr. Web daemon...Key file: /opt/drweb/drwebd.key Registration info: 0100003943 Evaluation Key (ID Anti-Virus Lab. Ltd, St.Petersburg) This is an EVALUATION version with limited functionality! To get your registration key, call regional dealer.Loading /var/drweb/bases/drwebase.vdb - Ok, virus records: 29405 Daemon is installed, TCP socket created on port 3000 /etc/init.d/drwebd start Starting Dr. Web daemon...Key file: /opt/drweb/drwebd.key Registration info: 0100003943 Evaluation Key (ID Anti-Virus Lab. Ltd, St.Petersburg) This is an EVALUATION version with limited functionality! To get your registration key, call regional dealer.Loading /var/drweb/bases/drwebase.vdb - Ok, virus records: 29405 Daemon is installed, TCP socket created on port 3000 Jun 29 13:41:08 multik drweb-postfix: load configuration from/etc/drweb/drweb_postfix.conf Jun 29 13:41:08 multik drweb-postfix: Actions: infected=Q, suspicious=Q, skip=P,mailbomb=P, scanning_error=T, processing_error=R, empty_from=C, spam_filter=P Jun 29 13:41:08 multik drweb-postfix: dwlib:read_conf(/etc/drweb/drweb_postfix.conf): successfully loaded Jun 29 13:41:08 multik drweb-postfix: dwlib: startup: set timeout for wholesession to 60000 milliseconds (-1 means infinite) Jun 29 13:41:08 multik drweb-postfix: drweb-pipe: [2250] started ... # tar zxvf String-CRC32-1.2.tar.gz # cd String-CRC32-1.2 # perl Makefile.PL # make # make test # make install # cd /opt/drweb/update # ./update.pl Key file: /opt/drweb/drweb.key Registration info: 0100003942 Evaluation Key (ID Anti-Virus Lab. Ltd, St.Petersburg) This is an EVALUATION version with limited functionality! To get your registration key, call regional dealer. Loading /var/drweb/bases/drwtoday.vdb - Ok, virus records: 173 Loading /var/drweb/bases/drw42807.vdb - Ok, virus records: 33Loading /var/drweb/bases/drw42806.vdb - Ok, virus records: 57 Loading /var/drweb/bases/drw42805.vdb - Ok, virus records: 133 Loading /var/drweb/bases/drw42804.vdb - Ok, virus records: 123 Loading /var/drweb/bases/drw42803.vdb - Ok, virus records: 73 Loading /var/drweb/bases/drw42802.vdb - Ok, virus records: 143 Loading /var/drweb/bases/drw42801.vdb - Ok, virus records: 76 Loading /var/drweb/bases/drwebase.vdb - Ok, virus records: 29405 mysql> create table admins (login varchar(20) NOT NULL, password varchar(20),rights int(6)); $ telnet localhost 25 Trying 127.0.0.1... Connected to localhost. Escape character is “^]”. 220 mail.test.ru ESMTP Postfix ehlo multik 250-mail.test.ru 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-XVERP250 8BITMIMEК 250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5 250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5 saslpasswd -c -u `postconf -h myhostname` username Дмитрий Галышев Миграция с Windows на Linux [global] ... domain master = yes ... [global] ... domain logons = yes ... [netlogon] path = /usr/local/samba/lib/netlogon read only = yes write list = ntadmin [global] ... encrypt passwords = yes ... root# useradd -g 100 -d /dev/null -c <имя_машины> -s /bin/false <имя_машины>$ root# passwd -l <имя_машины>$ root# smbpasswd -a -m <имя_машины> add user script = /usr/bin/adduserscript %u #!/bin/sh /usr/sbin/useradd -d /dev/null -g 100 -s /bin/false -m $1 Сергей Яремчук Что такое SAMBA? sergej@grinder sergej]$ whereis samba samba: /usr/sbin/samba /etc/samba /usr/share/man/man7/samba.7.gz [sergej@grinder sergej]$ ps -aux | grep smbd root 1122 0.0 0.6 4440 380 ? S 16:36 0:00 smbd –D workgroup = имя_группы # название рабочей группы в сети Windows netbios name = имя сервера в сети server string = комментарий, который виден в окне свойств просмотра сети guest ok = yes # разрешение гостевого входа ( guest ok = no - гостевой вход запрещен) guest account = nobody # имя под которым разрешен гостевой вход в систему security = user # Уровень доступа. user - на уровне пользователя, security = share - аутентификация на основе имени и пароля. %a - архитектура ОС на клиентской машине (возможные значения Win95, Win NT, UNKNOWN и т.д.) %m - NetBIOS-имя компьютера клиента. %L - NetBIOS-имя сервера SAMBA. %v - версия SAMBA. %I - IP-адрес компьютера клиента. %T - дата и время. %u - имя пользователя, работающего с сервисами. %H - домашняя директория пользователя %u. [homes] comment = Home Directories # комментарий который виден в окне свойств сети browseable = no # определяет выводить ли ресурс в списке просмотра. writable = yes # разрешает (no - запрещает) запись в домашнюю директорию create mode = 0750 # права доступа для вновь созданных файлов directory mode = 0775 # тоже, но только для каталогов [public] comment = Public Stuff path = /home/samba public = yes writable = no printable = no write list = administrator, @sales /mnt /etc/auto.misc —timeout=60 cdrom fstype=iso9660,ro,nosuid,nodev :/dev/cdrom [cdrom] path = /mnt/cdrom writable = no [cdrom] path = /mnt/cdrom read only = yes root preexec = mount /mnt/cdrom #монтировать ресурса имеет право только root root postexec = umount /mnt/cdrom # естественно эти точки монтирования должны быть описаны в файле /etc/fstab иначе необходимо указать и остальные данные. # useradd -s /bin/false -d /home/samba/sergej -g sales sergej # smbpasswd -a sergej printcap name = /etc/printcap # файл описания принтеров, подключенных к системе load printers = yes #, указывает на необходимость автоматического включения в список сетевых ресурсов printing = lprng # система печати (для Linux может еще использоваться bsd) [printers] path = /var/spool/samba # указывает на каталог в который помещаются зада ния на печать browseable = yes printable = yes read only = yes http://localhost:901 Роман Сузи Python в администрировании: почему бы и нет? #!/usr/bin/python import os, string users = {} for line in open("/etc/passwd").readlines(): rec = string.split(line, ":") users[rec[0]] = int(rec[2]), int(rec[3]) # uid и gid for file in os.listdir("."): try: uid, gid = users[file] except: print "Сирота: ", file uid, gid = 0, 0 # root os.chmod(file, 0600) os.chown(file, uid, gid) #!/usr/bin/python import os, pwd, glob default = pwd.getpwnam("root") for file in glob.glob("*"): try: rec = pwd.getpwnam(file) except: print "Сирота: ", file rec = default os.chmod(file, 0600) os.chown(file, rec[2], rec[3]) #!/bin/bash # Не работает, если имена файлов содержат точку или пробел for file in * do chown $file.$file $file || chown root.root $file chmod 600 $file done ­ #!/usr/bin/python import smtplib, poplib try: p = poplib.POP3("mymail") p.quit() except: error = "connection" try: s = SMTP("othermail") s.sendmail("admin@mymail", "admin@othermail", """From: admin@mymail To: admin@othermail Subject: POP3 down!!! Please, restart pop3 at mymail. """) s.quit() except: print "нет связи" #!/usr/bin/python """Анализ лога Sendmail""" import os, re, sys, anydbm, time server_name = "mail" # имя сервера, фигурирующее в логах def createdb(file): """Создание БД""" try: os.unlink(file) # удаляем старую БД except: pass # игнорируем исключения return anydbm.open(file, "c") # ключ: значение f = createdb("from.db") # ид сессии: отправитель t = createdb("to.db") # ид сессии: получатели r = createdb("relay.db") # ид сессии: почтовый хост d = createdb("date.db") # время и ид сессии: ид сессии ''' Примеры четырех характерных случаев: Aug 11 20:24:25 mail sendmail[4720]: g7BGOHY2004720: from=, size=103655, class=0, nrcpts=1, msgid=<000c01c2414e$d175ad80$3075a8c0@awx.ru>, proto=SMTP, daemon=MTA, relay=[212.28.127.12] Aug 11 20:24:25 mail sendmail[4720]: g7BGOHY2004720: to=, delay=00:00:07, pri=133655, stat=Headers too large (32768 max)''' Aug 11 04:02:31 mail sendmail[17058]: g7B02UY2017058: from=, size=33977, class=0, nrcpts=1, msgid=<20020811030027_hk_=2087=top=n=n_@subscribe:news.listsoft.lnx>, proto=SMTP, daemon=MTA, relay=relay1.aport.ru [194.67.18.127] Aug 11 07:18:20 mail sendmail[28329]: g7B3ICY2028329: ... User unknown''' # характерные части регулярных выражений (префикс, хост и адрес) P = "(?P.{15}) %(server_name)s sendmail\[[0-9]+\]: (?P[^:]+): " % vars() R = "relay=(?P.*(?:\[(?P.+?)\])?)" A = "\[^(),>]+)\>?" # регулярные выражения, соответствующие разным случаям log1_re = re.compile(r"%(P)s(?Pto)=%(A)s, (.*), stat=(?P.*)" % vars()) log2_re = re.compile(r"%(P)s(?Pfrom)=%(A)s, size=(?P[0-9]+), .*, %(R)s" % vars()) log3_re = re.compile(r"%(P)s(?Pfrom)=%(A)s, .*, %(R)s" % vars()) log4_re = re.compile(r"%(P)s%(A)s\.\.\. (?PUser unknown)" % vars()) input_file = open(sys.argv[1], "r") # открываем файл с логом while 1: line = input_file.readline() if not line: # обнаружен конец файла: выход из цикла break # сравниваем строку лога с шаблонами m = log1_re.match(line) or log2_re.match(line) \ or log3_re.match(line) or log4_re.match(line) if m: # если хоть один шаблон сработал: found = m.groupdict() # получаем словарь групп результата date, session_id, addr = found["date"], found["session"], found["addr"] direc = found.get("direc", "to") # по умолчанию "to" stat = found.get("stat", "") # по умолчанию - пустая строка if direc == "to" and stat[:4] != "Sent" and stat != "User unknown": continue # такие сообщения не интересуют if direc == "to": # в зависимости от направления if t.has_key(session_id): t[session_id] = t[session_id] + addr + ";" else: t[session_id] = addr + ";" else: f[session_id] = addr r[session_id] = found.get("relay_ip", "") or found.get("relay", "") d[date + session_id] = session_id input_file.close() f.close(); t.close(); r.close(); d.close() #!/usr/bin/python """Анализируем собранные данные""" import re, sys, anydbm, string # открываем базы f = anydbm.open("from.db", "r") t = anydbm.open("to.db", "r") r = anydbm.open("relay.db", "r") d = anydbm.open("date.db", "r") # показывать только случаи отправления >= LIM получателям try: LIM = int(sys.argv[1]) except: LIM = 4 dkeys = d.keys() # получаем все ключи в один список # сортируем (фактически, по времени). Пренебрегаем сменой месяцев dkeys.sort() good_guys_re = re.compile(".*(gluck@subscribe.ru|-errors@maillist.ru|@lists.cityline.ru|@host4.list.ru)\Z") def our_filter(x): """Функция для фильтрации получателей""" return "@" in x for date_sess_id in dkeys: i = d[date_sess_id] # находим идентификатор сессии try: recps = string.split(t[i], ";") # список получателей # берем только адреса с @ recps = filter(our_filter, recps) sender = f[i] # отправитель # показываем if len(recps) >= LIM and not good_guys_re.match(sender): relay = r[i] dte = date_sess_id[:15] # первые 15 символов -- дата print f[i], relay, dte, "->\n ", string.join(recps, "\n ") except: # если возникли ошибки, пропускаем pass f.close(); t.close(); r.close() Евгений Коновалов Работа с текстом, или философия Perl 1. Introduction. 1. Introduction 1. Introduction 2. CPUs and CPU Sockets 3. Supported Memory types and speed. Chipset features 4. Built-in video and audio cards 5. Hard drive support. USB ports and extension slots 1. Introduction 2. CPUs and CPU Sockets 3. Supported Memory types and speed. Chipset features 4. Built-in video and audio cards 5. Hard drive support. USB ports and extension slots Текст пункта оглавления
Motherboard Description

Introduction.



Mainboard is the most vital component of every PC. If we compare a PC with a living organism, the processor can be compared to a heart, and the mainboard is like a system of artherias and veins which deliver information from a processor to other parts of PC.

CPUs and CPU Sockets.

So, it is time for you to buy a new PC. We will not discuss the modern processors in this section, as it is revealed in our processors section, but will concentrate on the parts responsible to connecting CPU (Central Processor Unit) to the mainboard, the sockets, since there is a great variety of them nowadays.

Supported Memory types and speed. Chipset features.

Not only the CPU is responsible for overall performance of your desktop (or notebook) system. Even the extremely speedy processor will be found slowed by less performing RAM (Random Ac ss Memory).

Built-in video and audio cards.

As you see, the latest chipsets have built-in audio cardsnd video adapters.

Hard drive support. USB ports and extension slots.

The times when you had to install multiple intput-output cards can be forgotten and now you have all drive (hard and floppy) support on the mainboard.

@Pages_Info = { #Хэш структур (см. ниже) Tags => {%Tags}, #Хэш структур (см. ниже) Tags_Seq_Page => {%Tags_Seq_Page}, #Общее количество стартовых тегов в пределах одной главы Num_Of_Tags => $Num_Of_Tags, #Массив, каждое значение - порядковый номер тега в Документе, для которого в Главе необходимо добавить стартовый тег. Start_Tags_To_Add => {@Start_Tags_To_Add}, #Массив, каждое значение - порядковый номер тега в Документе, для которого в Главе необходимо добавить завершающий тег. End_Tags_To_Add => {@End_Tags_To_Add}, #Хэш, ключ хэша - значение атрибута href Внутренней Гиперссылки, значение хэша - номер Главы Local_Links => %Local_Links, #Хэш, ключ хэша - значение атрибута href Внутренней Гиперссылки на одну из Глав, значение хэша - номер Главы Local_Links_To_Pages => %Local_Links_To_Pages }; #Хэш структур, ключ хэша - порядковый номер тега в текущей Главе %Tags_Seq_Page = { #Имя тега Tag_Name => $Tag_Name, #Порядковый номер тега во всем Документе Tag_Num_In_Doc => $Tag_Num_In_Doc }; #Хэш структур, ключ хэша - имя (тип) тега %Tags = { #Количество начальных HTML-тегов данного типа в Главе Start_Tag_Num => $Start_Tag_Num, #Количество заключительных HTML-тегов данного типа в Главе End_Tag_Num => $End_Tag_Num }; $Doc_Info = { #Хэш структур (см. ниже) Tags_Seq_Doc => {%Tags_Seq_Doc}, #Хэш структур (см. ниже) Tags => {%Tags}, #Общее количество стартовых тегов в пределах Документа All_Start_Tags_Num => $All_Start_Tags_Num, #Общее количество завершающих тегов в пределах Документа All_End_Tags_Num => $All_End_Tags_Num, #Хеш, ключ хэша - имя анкера, значение хеша - номер Главы, в которой расположен анкер Local_Anchors => %Local_Anchors }; #Хэш структур, ключ хэша - порядковый номер тега в Документе %Tags_Seq_Doc = { #Имя тега Tag_Name => $Tag_Name, #HTML-код тега Tag_Orig_Text => $Tag_Orig_Text, #Номер тега в Главе Tag_Num_In_Page => $Tag_Num_In_Page, #Номер Главы, в которой найден данный тег Tag_Page_Num => $Tag_Page_Num }; $Work_Container { #В эту переменную заносится номер Главы, в которой недостает завершающего тега. Глава становится стартовой для итерационного поиска той Главы, в которой содержится недостающий завершающий тег Start_Page_Num => $Start_Page_Num, #Имя анализируемого тега Tag_Name => $Tag_Name, #Номер анализируемого тега в Документе Tag_Num_In_Doc => $Tag_Num_In_Doc, #Номер анализируемого тега в Главе Tag_Num_In_Page => $Tag_Num_In_Page, #Переменная для подсчета общего количества стартовых HTML-тегов в Документе Start_Tag_Num_Total => $Start_Tag_Num_Total, #Переменная для подсчета общего количества завершающих HTML-тегов в Документе End_Tag_Num_Total => $End_Tag_Num_Total }; my $Man_Cont_Parser = Manual_Cont_Parser->new(); $Man_Cont_Parser->parse($contents); my @Contents_Hrefs = $Man_Cont_Parser->Get_Links_Hrefs; $Man_Parser->parse($Document_Text); my $Man_Parser = Manual_Parser->new(\@Contents_Hrefs); $Man_Parser->Insert_Pages_In_DB(); sub start { my $self = shift; #Получение параметров тега (описание см. ранее) my ($tag, $attr, $attrseq, $origtext) = @_; my @Temp_Cont_HREFs = @{$self->{Contents_HREFs}}; #Проверка: входит ли найденный стартовый тег в список тех тегов, для которых не обязательно указывать парный концевой тег if (!($self->Tag_Is_Exception_Check($tag))) { #Проверка: является ли найденный тег гиперссылкой или анкером if ($tag eq “a”) { my $Last_Tag_Is_Cont_Href=0; #Для каждого имени Анкера Разметки foreach $Temp (@Array) { #Проверка: найденный тег - Анкер Разметки if ($attr->{“name”} eq $Temp && $attr->{“name”} ne “”) Выставление флагов, изменения счетчиков { #Счетчик числа тегов в Главе (инициализируется в конструкторе при создании объекта) - значение равно порядковому номеру (в Главе) анализируемого тега $self->{Tag_Num_In_Curr_Page}=0; #Счетчик числа страниц (инициализируется в конструкторе при создании объекта) - значение равно порядковому номеру текущей анализируемой Главы $self->{Current_Page}++; $Last_Tag_Is_Cont_Href=1; last; } #Проверка: найденный тег - гиперссылка на одну из Глав elsif ($attr->{“href”} eq join(“”,’#’,$Temp)) { #Сохранить в структуре данные о найденной Внутренней Гиперссылке на одну из Глав my $Temp2 = $attr->{“href”}; $Temp2 =~ s/#//; $self->{Pages_Info}[$self->{Current_Page}]->{Local_Links_To_Pages}{$Temp2}=$self->{Current_Page}; $Last_Tag_Is_Cont_Href=1; } } #Проверка: последний найденный тег - не Анкер Разметки и не Внутренняя Гиперссылка на одну из Глав if ($Last_Tag_Is_Cont_Href==0) { #Проверка: найденный тег - анкер if ($attr->{“name”} ne “”) { $self->{Doc_Info}->{Local_Anchors}{$attr->{“name”}}=$self->{Current_Page}; } #Проверка: найденный тег - Внутренняя Гиперссылка if ($attr->{“href”} =~ /^#/ ) { my $Temp2 = $attr->{“href”}; $Temp2 =~ s/#//; $self->{Pages_Info}[$self->{Current_Page}]->{Local_Links}{$Temp2}=$self->{Current_Page}; } } } #Обновление статистики по найденному тегу в структуре данных по текущей Главе $self->{Pages_Info}[$self->{Current_Page}]->{Num_Of_Tags}++; $self->{Pages_Info}[$self->{Current_Page}]->{Tags}{«$tag»}->{Start_Tag_Num}++; $self->{Pages_Info}[$self->{Current_Page}]->{Tags_Seq_Page}{$self->{Tag_Num_In_Curr_Page}}->{Tag_Name}=$tag; $self->{Pages_Info}[$self->{Current_Page}]->{Tags_Seq_Page}{$self->{Tag_Num_In_Curr_Page}}->{Tag_Num_In_Doc} = $self->{Tag_Num_In_Doc}; #Обновление статистики по найденному тегу в структуре данных по Документу $self->{Doc_Info}->{Tags}{«$tag»}->{Start_Tag_Num}++; $self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}->{Tag_Name}=$tag; $self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}->{Tag_Orig_Text}=$origtext; $self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}->{Tag_Num_In_Page}=$self->{Tag_Num_In_Curr_Page}; $self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}->{Tag_Page_Num}=$self->{Current_Page}; $self->{Doc_Info}->{All_Start_Tags_Num}++; $self->{Tag_Num_In_Curr_Page}++; #Счетчик числа тегов вдокументе (инициализируется в конструкторе при создании объекта) $self->{Tag_Num_In_Doc}++; } } sub end { my $self = shift; #Получение параметров тега (описание см. ранее) ($tag, $origtext)=@_; #Проверка: входит ли найденный стартовый тег в список тех тегов, для которых не обязательно указывать парный концевой тег if (!($self->Tag_Is_Exception_Check($tag))) { #Обновление статистики по концевым HTML-тегам для текущей Главы $self->{Pages_Info}[$self->{Current_Page}]->{Tags}{«$tag»}->{End_Tag_Num}++; #Обновление статистики по концевым HTML-тегам для всего Документа $self->{Doc_Info}->{Tags}{«$tag»}->{End_Tag_Num}++; $self->{Doc_Info}->{All_End_Tags_Num}++; } } sub _Separate_Manual_Into_Pages { my $self = shift; my $Manual_Text = shift; my @Manual_Parts; for ($i=-1; $i<=$#Array; $i++) { #Проверка: выбираем из Документа первую Главу if($i==-1) { $Manual_Text =~ /(.*)<\s*a\s+name=»*$Array[$i+1]»*\s*>/is; $Manual_Parts[$i+1]=$1; } #Проверка: выбираем из Документа промежуточную Главу elsif ($i<$#Array) { $Manual_Text =~ /(<\s*a\s+name=»*$Array[$i]»*\s*>.*<\s*\/a\s*>.*)<\s*a\s+name=»*$Array[$i+1]»*\s*>/is; $Manual_Parts[$i+1]=$1; } #Проверка: выбираем из Документа последнюю Главу else { $Manual_Text =~ /(<\s*a\s+name=»*$Array[$i]»*\s*>.*<\s*\/a\s*>.*)/is; $Manual_Parts[$i+1]=$1; } } #Возвращает массив, каждый элемент которого содержит текст одной из Глав return @Manual_Parts; } sub Generate_Manual_Parts { my $self = shift; #Получение Глав в виде отдельных фрагментов HTML-кода и сохранение их в массив my @Manual_Parts=$self->_Separate_Manual_Into_Pages($Manual_Text); #Инициализация счетчика страниц my $Current_Page_Num=0; #Для каждой полученной Главы for (my $i=0; $i<=$#Manual_Parts; $i++) { $Current_Page_Num=$i; #Для каждого тега анализируемой Главы for (my $j=0; $j<$self->{Pages_Info}[$i]->{Num_Of_Tags}; $j++) { #Запомнить имя (тип) тега в $Current_Tag_Name my $Current_Tag_Name = $self->{Pages_Info}[$i]->{Tags_Seq_Page}{$j}->{Tag_Name}; #Проверка: для тегов запомненного типа количество стартовый и концевых тегов в Главе не совпадает if ($self->{Pages_Info}[$i]->{Tags}{$Current_Tag_Name}->{Start_Tag_Num} != $self->{Pages_Info}[$i]->{Tags}{$Current_Tag_Name}->{End_Tag_Num}) { #Пометить текущую страницу как стартовую в рамках итерационного поиска парного завершающего тега $self->{Work_Container}->{Start_Page_Num}=$i; Занести в «рабочий контейнер» тип парного концевого тега, который необходимо найти в одной из Глав $self->{Work_Container}->{Tag_Name}=$Current_Tag_Name; Занести в «рабочий контейнер» порядковый номер текущего стартового тега в Документе $self->{Work_Container}->{Tag_Num_In_Doc} = $self->{Pages_Info}[$i]->{Tags_Seq_Page}{$j}->{Tag_Num_In_Doc}; Занести в «рабочий контейнер» порядковый номер текущего стартового тега в Главе $self->{Work_Container}->{Tag_Num_In_Page}=$j; $self->{Work_Container}->{Start_Tag_Num_Total} = $self->{Pages_Info}[$i]->{Tags}{$Current_Tag_Name}->{Start_Tag_Num}; $self->{Work_Container}->{End_Tag_Num_Total} = $self->{Pages_Info}[$i]->{Tags}{$Current_Tag_Name}->{End_Tag_Num}; >{End_Tag_Num}; } #Проверка: концевой тег был найден if ($Current_Page_Num <= $#Manual_Parts) { #Для всех Глав участвовавших в итеарционном поиске парного тега for ($k=$self->{Work_Container}->{Start_Page_Num}; $k <= $Current_Page_Num; $k++) { #Для стартовой Главы итерационного поиска if ($k == $self->{Work_Container}->{Start_Page_Num}) { #Запомнить порядковый номер тега в Документе, для которого необходимо добавить парный концевой тег в Главе push (@{$self->{Pages_Info}[$k]->{End_Tags_To_Add}}, $self->{Work_Container}->{Tag_Num_In_Doc}); $self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}->{End_Tag_Num}++; $self->{Doc_Info}->{Tags}{$Current_Tag_Name}->{End_Tag_Num}++; } #Для заключительной Главы итерационного поиска elsif ($k == $Current_Page_Num) { #Запомнить порядковый номер тега в Документе, для которого необходимо добавить парный стартовый тег в Главе push (@{$self->{Pages_Info}[$k]->{Start_Tags_To_Add}}, $self->{Work_Container}->{Tag_Num_In_Doc}); $self->{Doc_Info}->{Tags}{$Current_Tag_Name}->{Start_Tag_Num}++; $self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}->{Start_Tag_Num}++; } #Для промежуточных Глав итерационного поиска else { #Запомнить порядковый номер тега в Документе, стартовый и концевой теги которго будут добавлены в промежуточную страницу push (@{$self->{Pages_Info}[$k]->{Start_Tags_To_Add}}, $self->{Work_Container}->{Tag_Num_In_Doc}); $self->{Doc_Info}->{Tags}{$Current_Tag_Name}->{Start_Tag_Num}++; $self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}->{Start_Tag_Num}++; push (@{$self->{Pages_Info}[$k]->{End_Tags_To_Add}}, $self->{Work_Container}->{Tag_Num_In_Doc}); $self->{Doc_Info}->{Tags}{$Current_Tag_Name}->{End_Tag_Num}++; $self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}->{End_Tag_Num}++; } } } } } } #Для всех Глав for (my $i=0; $i<=$#Manual_Parts; $i++) #Выполнить добавление недостающих стартовых и концевых тегов (корректировка HTML-структуры) { @{$self->{Pages_Info}[$i]->{Start_Tags_To_Add}}= sort {$b <=> $a} @{$self->{Pages_Info}[$i]->{Start_Tags_To_Add}}; @{$self->{Pages_Info}[$i]->{End_Tags_To_Add}} = sort {$b <=> $a} @{$self->{Pages_Info}[$i]->{End_Tags_To_Add}}; #Добавить стартовые теги foreach my $value (@{$self->{Pages_Info}[$i]->{Start_Tags_To_Add}}) { $Manual_Parts[$i]=join (“”, $self->{Doc_Info}->{Tags_Seq_Doc}{$value}->{Tag_Orig_Text}, $Manual_Parts[$i]); } #Добавить концевые теги foreach my $value (@{$self->{Pages_Info}[$i]->{End_Tags_To_Add}}) { $Manual_Parts[$i]=$Manual_Parts[$i].’{Doc_Info}->{Tags_Seq_Doc}{$value}->{Tag_Name}.’>’; } } #Вернуть Главы с откорректированной HTML-структурой return @Manual_Parts; } Корректировка Внутренних Гиперссылок на Главы foreach $key (keys %{$self->{Pages_Info}[$i]->{Local_Links_To_Pages}}) { $Manual_Parts[$i] =~ s/(<\s*?a\s{1}.*?href\s*?=\s*?»?)#$key(«?\s?.*?>)/$1строка_http-запроса_указывающая_ путь_с_точностью_до_документа&page=$i$2/is; } #Корректировка прочих Внутренних Гиперссылок foreach $key (keys %{$self->{Pages_Info}[$i]->{Local_Links}}) { $Manual_Parts[$i] =~ s/(<\s*?a\s{1}.*?href\s*?=\s*?»?)(#$key»?\s?.*?>)/$1строка_http-запроса_указывающая_ путь_с_точностью_до_документа&page=$self->{Doc_Info}->{Local_Anchors}{$key}$2/is; } Даниил Алиевский Эффективное использование памяти в Perl при работе с большими строками sub a { my $text= "very large string.... (1 MB)"; работаем с $text; #просто выходим из функции, предполагая, #что сборщик мусора автоматически освободит #память из-под $text (как это происходит #со стековыми переменными в C++ и Pascal) } sub a { my $text= "very large string.... (1 MB)"; работаем с $text; undef $text; } sub a { my $text= "very large string.... (1 MB)"; return $text; } my $v= a(); работаем с $v; sub a { my $text= "very large string.... (1 MB)"; return \$text; } my $v= a(); работаем с $$v; undef $$v; #освобождаем память, отведенную функцией a my $v= $text."\n"; sub a { my $text= $_[0]; #параметр $_[0] содержит строку длиной 1 MB работаем с $text; undef $text; } my $text= "very large string.... (1 MB)"; a($text); sub a { my $text= $_[0]; #параметр $_[0] содержит ССЫЛКУ на строку работаем с $$text; } my $text= "very large string.... (1 MB)"; a(\$text); my $newtext= "$a$text$b"; my $newtext= $a.$text.$b; my $newtext= $a; $newtext.= $text; $newtext.= $b; my $text= "very large string.... (1 MB)"; $text= substr($text,10); my $text= "very large string.... (1 MB)"; substr($text,0,10)= ""; my $text= "very large string.... (1 MB)"; substr($text,0,10,""); my $text= "very large string.... (1 MB)"; $text= substr($text,100000,500000); sub substrlarge { # - Returns a reference to substr($_[0],$_[1],$_[2]) # and doesn't use extra memory when $len is very large # Example: # my $ps= substrlarge($text,500,1000000); # some actions with $$ps; # undef $$ps; # - it is an economical equivalent for # my $s= substr($text,500,1000000); # some actions with $s; my $offset= $_[1]; my $len= $_[2]; $len= length($_[0])-$offset unless defined $len; if ($len*20) result.append(separator); result.append(String.valueOf( java.lang.reflect.Array.get(v,k))); } return result.toString(); } return String.valueOf(v); } double s= 0.0; for (int k=0; k=0) { sb.append(buf,0,len); } s= sb.toString(); } catch (IOException e) { e.printStackTrace(); } myTextResource= s; } public static void main(String[] args) { System.out.println(«Loaded resource:»); System.out.println(myTextResource); } } public static java.io.File getClassFile(Class clazz) { // The file will exist only if it is usual class-file, // not a part of JAR or Web resource String s= clazz.getName(); s= s.substring(s.lastIndexOf(«.»)+1); s= clazz.getResource(s+».class»).getFile(); try { s= java.net.URLDecoder.decode(s,»UTF-8"); } catch(java.io.UnsupportedEncodingException e) { } return new java.io.File(s); } public static Class forName(String className) throws ClassNotFoundException Class clazz= Class.forName(«java.lang.String»); public Object newInstance() throws InstantiationException, IllegalAccessException Object object= clazz.newInstance(); public interface LanguageTranslator { public String translate(String source, String sourceLanguage, String targetLanguage); // переводит текст source с языка sourceLanguage // на язык targetLanguage } String source= «текст, требующий перевода»; String sourceLanguage= «Russian»; String targetLanguage= «English»; Class clazz= Class.forName(«полное_имя_класса_переводчика»); Object object= clazz.newInstance(); if (!(object instanceof LanguageTranslator)) { throw new Exception(«...»); // сообщаем об ошибке: указанный класс // не реализует требуемый интерфейс, // т.е. не является переводчиком } String result= ((LanguageTranslator)object) .translate(source,sourceLanguage,targetLanguage); public Constructor[] getConstructors(), public Field[] getFields(), public Method[] getMethods(), public Constructor[] getDeclaredConstructors(), public Field[] getDeclaredFields(), public Method[] getDeclaredMethods() public Constructor getConstructor(Class[] parameterTypes), public Field getField(String name), public Method getMethod(String name, Class[] parameterTypes), public Constructor getDeclaredConstructor(Class[] parameterTypes), public Field getDeclaredField(String name), public Method getDeclaredMethod(String name, Class[] parameterTypes) public String getName(); public Class getDeclaringClass(); public int getModifiers(); import java.lang.reflect.*; public class TestClass { public int a; public TestClass(int a) {this.a= a;} public void b() {a= 1;} public void b(int p1) {a= p1;} public String toString() {return a+"";} public static void main(String[] args) throws Exception { Class clazz= TestClass.class; Constructor c= clazz.getConstructor(new Class[] {int.class}); Object o= c.newInstance(new Object[] {new Integer(23)}); Field f= clazz.getField("a"); System.out.println(f.getInt(o)); f.setInt(o,24); System.out.println(o); Method m= clazz.getMethod("b",new Class[] {}); m.invoke(o,new Object[] {}); System.out.println(o); m= clazz.getMethod("b",new Class[] {int.class}); m.invoke(o,new Object[] {new Integer(2)}); System.out.println(o); } } private char value[]; import java.lang.reflect.*; public class HackString { public static void main(String[] args) throws Exception { String s= «Hello!»; System.out.println(s); Field f= s.getClass().getDeclaredField(«value»); // Именно getDeclaredField, а не getField: // последний метод просто не нашел бы скрытого поля f.setAccessible(true); char[] value= (char[])f.get(s); value[5]= “?”; System.out.println(s); } } Coldfusion или, возможно, лучшее решение для создания динамических сайтов Александр Меженков 1. <% 2. Dim RandomFraction 3. Randomize 4. RandomFraction = Rnd 5. Response.Write(RandomFraction) %> 1. #RandomFraction# 1. Официальная страница описания стандарта CGI http://www.w3.org/CGI/ 2. Документация и примеры CGI программ http://hoohoo.ncsa.uiuc.edu/cgi/ 3. Программные продукты Macromedia - нынешнего владельца ColdFusion. Отсюда же можно скачать пробные (trial)версии http://www.macromedia.com/software/ 4. Developer's exchange. Коллекция готовых решений на ColdFusion http://devex.macromedia.com/developer/gallery/index.cfm 5. ColdFusion форумы http://webforums.macromedia.com/coldfusion/ 7. On-line документация по ColdFusion http://www.macromedia.com/support/coldfusion/documentation.html Программирование сервисов в Windows 2000 Всеволод Стахов SC_HANDLE OpenSCManager (const char *MachineName, const char* DatabaseName, DWORD Desired Access); SC_HANDLE CreateService( SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword ); CreateService (hsSManager,lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, lpServiceStartName, lpPassword); #include int main(int argc, char **argv){ SC_HANDLE sh; SC_HANDLE svdb; // Дескриптор базы сервисов SERVICE_TABLE_ENTRY DispatchTable[] = { { «MyService», MyServiceStart }, { NULL, NULL } }; if(argc < 2){ // Запуск без аргументов // Запуск сервиса if (!StartServiceCtrlDispatcher( DispatchTable)) { write_to_log(«Can`t execute service»); } } if(argc == 2){ // Передан один параметр if(strcmp(argv[1], “-i”)) install_service(); // Установка сервиса если аргумент -i if(strcmp(argv[1], “-u”)) uninstall_service(); // Удаление сервиса если аргумент -u } else{ write_to_log(“Bad usage”); return -1; } return 0; } struct SERVICE_STATUS { DWORD dwServiceType; — это поле означает то же, что и в функции CreateService, т.е. тип приложения сервиса(отдельный, драйвер ядра, драйвер ФС). DWORD dwCurrentState; — а вот это специфическое поле - содержит текущее состояние сервиса, именно его должна устанавливать ServiceMain. Допустимые значения: SERVICE_STOPPED - сервис остановлен; SERVICE_START_PENDING - сервис запускается; SERVICE_STOP_PENDING - сервис останавливается; SERVICE_RUNNING - сервис уже запущен; SERVICE_CONTINUE_PENDING - сервис продолжает работу; SERVICE_PAUSE_PENDING - сервис переходит в режим паузы; SERVICE_PAUSED - сервис находится в режиме паузы. DWORD dwControlsAccepted; — битовая маска, содержащая допустимые состояния сервиса(через побитное «или»). Допустимые константы: SERVICE_ACCEPT_STOP - сервис может быть остановлен; SERVICE_ACCEPT_PAUSE_CONTINUE - сервис может быть поставлен и снят с паузы; SERVICE_ACCEPT_SHUTDOWN - сервис будет оповещён при выходе из системы. DWORD dwWin32ExitCode; — этот параметр сообщает системе значение, которое возвращает сервис при ошибке, подробнее ошибка определяется следующим параметром. DWORD dwServiceSpecificExitCode; — конкретная ошибка, произошедшая в сервисе. DWORD dwCheckPoint; — а это положение прогресс-бара при запуске-остановке сервиса, используется для визуализации процесса запуска сервиса. DWORD dwWaitHint; — время в миллисекундах, которое ждёт вызывающая программа до изменения либо текущего статуса, либо dwCheckPoint. Если этого не случилось, то считается, что запуск сервиса был неудачен. Если данное значение ноль, то убиения не происходит. }; void MyServiceStart (DWORD argc, LPTSTR *argv) { DWORD status; DWORD specificError; SERVICE_STATUS MyServiceStatus; //Эта та самая структура статуса // А вот мы её заполняем MyServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; MyServiceStatus.dwCurrentState = SERVICE_START_PENDING; MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; MyServiceStatus.dwWin32ExitCode = 0; MyServiceStatus.dwServiceSpecificExitCode = 0; MyServiceStatus.dwCheckPoint = 0; MyServiceStatus.dwWaitHint = 5000; //Регистрируем обработчик событий MyServiceStatusHandle = RegisterServiceCtrlHandler(«MyService», MyServiceCtrlHandler); if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) { write_to_log(«Can not register handler function»); return; } //А теперь выполняем некоторые инициализационные действия. status = MyServiceInitialization(argc,argv, &specificError); // Проверяем, как прошла инициализация if (status != NO_ERROR) { //Ошибка - останавливаем сервис и выходим MyServiceStatus.dwCurrentState = SERVICE_STOPPED; MyServiceStatus.dwCheckPoint = 0; MyServiceStatus.dwWaitHint = 5000; MyServiceStatus.dwWin32ExitCode = status; MyServiceStatus.dwServiceSpecificExitCode = specificError; SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus); return; } // Всё прошло успешно :) идём дальше. MyServiceStatus.dwCurrentState = SERVICE_RUNNING; MyServiceStatus.dwCheckPoint = 0; MyServiceStatus.dwWaitHint = 0; if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus)) { status = GetLastError(); write_to_log(«Can not set service status 8-(«); } //Сервис начал работать. write_to_log(«Yeah, this works!»,0); return; } Владимир Мешков Анализатор сетевого трафика #include #include #include #include #include #include #include #include struct ip_packet { struct iphdr ip; char *ip_data; } ip_pack; struct ifreq ifr; struct sockaddr_in s; struct iphdr *ip; struct ethhdr eth; struct ifparam { u_long ip; u_long mask; u_long subnet; int mtu; int index; } ifp; #include «ip.h» #include int getifconfig (struct ifreq *ifr, char *intf, struct ifparam *ifp) { if (( fd= socket (AF_INET, SOCK_DGRAM, 0)) <0 ) { perror ( «socket» ); return ( - 1 ); } sprintf (ifr->ifr_name, «%s», intf); if (ioctl (fd, SIOCGIFADDR, ifr) <0 ) { perror («ioctl»); return (-1); } memset(&s, 0, sizeof (struct sockaddr_in)); memcpy(&s, &ifr->ifr_addr, sizeof (struct sockaddr)); memcpy(&ifp-ip, &to.sin_addr.s_addr, sizeof (u_long)); if (ioctl (fd, SIOCGIFNETMASK, ifr) <0 ) { perror («ioctl»); return (-1); } memset(&s, 0, sizeof (struct sockaddr_in)); memcpy(&s, &ifr->ifr_netmask, sizeof (struct sockaddr)); memcpy(&ifp-mask, &to.sin_addr.s_addr, sizeof (u_long)); ifp->sunbet = check_subnet(ifp->mask, ifp->ip); if (ioctl (fd, SIOCGIFMTU, ifr) <0 ) { perror («ioctl»); return (-1); } ifp -> mtu = ifr -> ifr_mtu; if ( ioctl (fd, SIOCGIFINDEX, ifr) <0 ) { perror («ioctl»); return (-1); } ifp -> index = ifr -> ifr_ifindex; if ( ioctl (fd, SIOCGIFFLAGS, ifr) <0 ) { perror («ioctl»); close (fd); return (-1); } ifr -> ifr_flags |= IFF_PROMISC; if ( ioctl (fd, SIOCSIFFLAGS, ifr) <0 ) { perror («ioctl»); close (fd); return (-1); } return 1; } BITS 32 GLOBAL check_subnet SECTION .text check_subnet: push ebp - сохраним адрес возврата из функции mov ebp, esp mov edx, [ebp+8] - первый параметр - маска подсети mov eax, [ebp+12] - второй параметр - IP адрес mov cx, 32 - число разрядов в IP адресе в формате IPv4 push cx - сохраним значение в стеке xor esi, esi - обнулим счетчик .label bt edx, esi - сканируем маску в поисках 1 jnc .msk - выход из цикла при совпадении inc esi - инкремент счетчика loop .label - продолжить поиск .mask pop cx - извлечь ранее сохраненное значение из стека sub cx, si - число разрядов в адресе, отведенных под хостовую часть shl eax, cl - логический сдвиг на это значение mov esp, ebp pop ebp - восстановим стек ret - возврат из функции #include #include #include #include #include int getsock_recv (int index) { int fd; struct sockaddr_ll s_ll; if (( fd= socket (SOCK_PACKET, SOCK_RAW, htons (ETH_P_ALL) )) <0 ) { perror ( «socket» ); return ( - 1 ); } memset (&s_ll, 0, sizeof (struct sockaddr_ll)); s_ll.sll_family = PF_PACKET; - тип сокета s_ll.sll_protocol = htons (ETH_P_ALL); - тип принимаемого протокола s_ll.sll_ifindex = index; - номер интерфейса s_ll.sll_pkttype = PACKET_HOST; - тип пакета (для локальной машины) if ((bind (fd, (struct sockaddr *) &s_ll, sizeof (struct sockaddr_ll)) <0 ) { perror («bind»); close (fd); return (-1); } return (fd); } #include «ip.h» int main () { memset (&ifr, 0, sizeof (struct ifreq)); if (getifconfig (&ifr, «eth0», &ifp) <0 ) { perror («getifconfig»); exit (1); } buff = (char *) malloc (ifp.mtu + 18); memset(&ip, 0, sizeof (struct ip_packet)); ip_pack.ip_data = (char *) malloc ( ifp.mtu - sizeof (struct iphdr)); ip=(struct iphdr *)&ip_pack.ip; if ((e0_r = getsock_recv (ifp.index)) <0 ) { perror («getsock_recv»); exit(1); } for (;;) { Обнулим буфер: bzero (buff, ifp.mtu+18); rec = 0; Принять пакет: rec=recvfrom (e0_r, (char *)buff, ifp.mtu+18, 0, NULL, NULL); if (rec<0) { perror («recvfrom»); exit(1); } printf («\nrec = %d\n», rec); memcpy ((char *) ð, buff, 12); memcpy ((char *)&ip.pack, (buff + 14), ifp.mtu ); if ((ip -> version) !=4) continue; printf (« %.2x: %.2x: %.2x: %.2x: %.2x: %.2x \t -> \t «, eth.h_source[0], eth.h_source[1], eth.h_source[2], eth.h_source[3], eth.h_source[4], eth.h_source[5]); printf (« %.2x: %.2x: %.2x: %.2x: %.2x: %.2x», eth.h_dest[0], eth.h_ dest[1], eth.h_ dest[2], eth.h_ dest[3], eth.h_ dest[4], eth.h_ dest[5]); printf («%d \n», ip -> ihl); - длина заголовка IP-пакета printf («%d \n», ntohs (ip -> tot_len)); - длина всего пакета printf («%d \n», ip -> protocol); - протокол верхнего уровня printf («%s \t -> \t», inet_ntoa (ip -> saddr)); - адрес источника printf («%s \n», inet_ntoa (ip -> daddr)); - адрес назначения } return (1); } # Компилятор С CC = gcc # Компилятор ассемблера NASM = nasm # Имя исполняемого модуля name = ip IP = ip.o check_snet.o getsock_recv.o getifconf.o $(name): $(IP) $(CC) -g -o $(name) $(IP) ip.o: ip.c $(CC) -c ip.c check_snet.o: check_snet.asm $(NASM) -f elf check_snet.asm getsock_recv.o: getsock_recv.c $(CC) -c getsock_recv.c getifconf.o: getifconf.c $(CC) -c getifconf.c clean: rm -f *.o Владимир Мешков Сканер портов: пример реализации #include #include #include #include #include #include #include #include #include #include #include struct ifreq *ifr - структура для хранения параметров сетевого интерфейса struct iphdr *ih - структура, содержащая заголовок IP-пакета sturct tcphdr *th - структура, содержащая заголовок TCP-пакета struct sockaddr_in local - структура, содержащая адресную информацию о локальной системе struct sockaddr_in dest - структура, содержащая адресную информацию об удаленной системе struct p_header { u_long s_addr; u_long d_addr; u_char zer0; u_char protocol; u_int lenght; } *pseudo - псевдозаголовок. Необходим при расчете контрольной суммы TCP-пакета (взят из исходных текстов сканера Nmap) int fd - дескриптор вспомогательного сокета e0_s- дескриптор сокета для передачи e0_r- дескриптор сокета для приема sent- число переданных байт rec- число принятых байт port- номер сканируемого порта index- индекс интерфейса, через кото рый осуществляется сканирование. u_char *packet- пакет, передаваемый в сеть. #include #include #include #include #include #include int getsock_send ( char *intf) - вызов функции int fd - дескриптор сокета const int on=1 - флаг включения заголовка (см. ниже) struct ifreq ifr - структура для хранения параметров сетевого интерфейса. if (( fd = socket ( AF_INET, SOCK_RAW, htons(ETH_P_IP) )) < 0 ) { perror ( «socket» ); return (-1); } if ( setsockopt ( fd, IPPROTO_IP, IP_HDRINCL, ( const void *) &on, sizeof ( on ) ) < 0 ) { perror ( «setsockopt IP_HDRINCL» ); close ( fd ); return ( -1 ); } sprintf ( ifr.ifr_name, «%s», intf ); if ( setsockopt ( fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof (ifr)) <0 ) { perror ( « SO_BINDTODEVICE» ); close ( fd ); return ( -1 ); } #include #include #include #include #include int getsock_recv (int index) - вызов функции int fd; struct sockaddr_ll s_ll; if (( fd= socket (SOCK_PACKET, SOCK_DGRAM, htons (ETH_P_ALL) )) <0 ) { perror ( «socket» ); return ( - 1 ); } memset (&s_ll, 0, sizeof (struct sockaddr_ll)); s_ll.sll_family = PF_PACKET; - тип сокета s_ll.sll_protocol = htons (ETH_P_ALL); - тип принимаемого протокола s_ll.sll_ifindex = index; - номер интерфейса s_ll.sll_pkttype = PACKET_HOST; - тип пакета (для локальной машины) if ((bind (fd, (struct sockaddr *) &s_ll, sizeof (struct sockaddr_ll)) <0 ) { perror («bind»); close (fd); return (-1); } return (fd) #include «scan.h» - файл с переменными и header-файлами int main ( int argc, char *argv [ ] ) - вызов главной функции void usage () { printf ( « \n scan [ dest_IP ] [ dest_port ] \n» ); return; } if ( argc != 3 ) { usage (); exit ( 1 ); } port = atoi ( argv [2] ); memset ( &dest, 0, sizeof ( struct sockaddr_in )); dest.sin_addr.s_addr = inet_ntoa ( argv [1] ); dest.sin_port = htons ( port ); memset ( &local, 0, sizeof ( struct sockaddr_in )); fd = socket ( AF_INET, SOCK_DGRAM, 0 ); sprintf ( ifr -> ifr_name, «%s», «eth0»); octl ( fd, SIOCGIFADDR, ifr ); memcpy (( char *) &local, ( char *)&( ifr -> ifr_addr ), sizeof ( struct sockaddr )); local.sin_port = htons (53); ioctl ( fd, SIOCGIFINDEX, ifr ); index = ifr -> ifindex; packet = ( u_char * )malloc( sizeof ( struct iphdr ) + sizeof ( struct tcphdr )); in = ( struct iphdr * ) packet; th = ( struct tcphdr * ) (packet + sizeof ( struct iphdr )); pseudo = (struct p_header *) ( packet + sizeof ( struct iphdr) - sizeof ( struct p_header )); memset ( pseudo, 0, sizeof ( struct p_header )); - обнулим структуру pseudo -> s_addr = local.sin_addr.s_addr; - адрес локального хоста pseudo -> d_addr = dest.sin_addr.s_addr; - адрес удаленного хоста pseudo -> protocol = 6; - протокол (TCP) pseudo -> lenght = htons ( sizeof ( struct tcphdr )); - длина псевдозаголовка memset ( th, 0, sizeof ( struct tcphdr )); - обнулим структуру th -> source = local.sin_port; - локальный порт th -> dest = dest.sin_port; - удаленный порт th -> seq = htonl ( 1156270349 ); - начальный порядковый номер th -> ack_seq = 0; - номер подтверждения th -> doff = 5; - длина заголовка ( в 32-х разрядных словах ) th -> syn = 1; - установить флаг SYN th -> window = htons ( 3072 ); - размер окна th -> check = 0; -обнулить поле контрольной суммы th -> check = in_cksum (( u_short *)pseudo, sizeof ( struct tcphdr) + sizeof ( struct p_header)); memset ( ih, 0, sizeof ( struct iphdr )); - обнулим структуру ih -> version = 4; - версия протокола ih -> ihl = 5; - длина заголовка (число 32-х битных слов) ih -> tot_len = htons (sizeof (struct iphdr)+sizeof(struct tcphdr)); - длина пакета ih -> id = 3290; - порядковый номер пакета (идентификация) ih -> ttl = 42; - время жизни ih -> protocol = 6; - транспортный протокол (TCP) ih -> saddr = local.sin_addr.s_addr; - локальный адрес ih -> daddr = dest.sin_addr.s_addr; - удаленный адрес ih -> check = in_cksum (( u_short *) ih, sizeof (struct iphdr )); - контрольная сумма printf ( «IP-адрес назначения \t -\t %s \n «, inet_ntoa ( ih -> daddr )); printf ( «IP-адрес источника \t - \t %s \n «, inet_ntoa ( ih -> saddr )); printf ( «Порт назначения \t \t - \t %d \n «, ntohs ( th -> dest )); printf ( «Порт источника \t\t - \t %d \n «, ntohs ( th -> source )); if (( e0_s = getsock_send ( «eth0» )) < 0 ) { perror ( «getsock_send» ); exit ( 1 ); } if (( e0_r = getsock_recv ( index )) < 0 ) { perror ( «getsock_recv» ); exit ( 1 ); } dest.sin_family = AF_INET; sent = sendto ( e0_s, (char *) packet, ntohs ( ih -> tot_len), 0, ( struct sockaddr *)&dest, sizeof (struct sockaddr_in)); if ( sent <= 0 ) { perror ( «sendto» ); exit ( 1 ); } printf ( «\n Передано %d байт \n», sent ); for ( ; ; ) { bzero ( packet, sizeof (packet)); rec = 0; rec = recvfrom ( e0_r, (char *) packet, sizeof ( struct iphdr ) + sizeof ( struct tcphdr ), 0, NULL, NULL ); if ( rec <0 || rec > 1500 ) { perror ( «recvfrom» ); exit ( 1 ); } if (( ih -> version ) != 4 ) continue; if (( ih -> saddr != dest.sin_addr.s_addr ) continue; if (( ih -> protocol != 6 ) continue; printf ( «Принято %d байт \n \n «, rec ); printf ( «%s \t -> \t « , inet_ntoa ( ih ->saddr )); printf ( «%s \t \n \n «, inet_ntoa ( ih -> daddr )); printf ( «Версия \t \t \t = %d \n», ih -> version ); printf ( «Длина заголовка \t \t = %d \n», ih -> ihl ); printf ( «Длина пакета \t \t= %d \n», ntohs (ih -> tot_len )); printf ( «Идентификатор \t \t = %d \n», ih -> id ); printf ( «Время жизни \t \t = %d \n», ih -> ttl ); printf ( «Протокол \t \t = %d \n», ih -> protocol ); printf ( «Контрольная сумма IP \t= %d \n», ih -> check ); printf ( «Порт источник \t \t = %d \n», ntohs ( th -> source )); printf ( «Порт назначения \t \t = %d \n», ntohs ( th -> dest )); printf ( «Контрольная сумма TCP \t = %d \n», th->check); printf ( «SEQ \t \t \t = %lu \n», ntohl ( th -> seq )); printf ( «ACK-SEQ \t \t \t = %lu \n», ntohl ( th -> ack_seq )); if ( th -> syn == 1 ) printf ( «Флаг SYN установлен \n» ); if ( th -> ack == 1 ) printf ( «Флаг ACK установлен \n» ); if ( th -> fin == 1 ) printf ( «Флаг FIN установлен \n» ); if ( th -> rst == 1 ) printf ( «Флаг RST установлен \n» ); if ( th -> psh == 1 ) printf ( «Флаг PUSH установлен \n» ); if ( th -> urg == 1 ) printf ( «Флаг URG установлен \n» ); if (( th -> syn == 1 )&&(th->ack==1)) printf («Порт %d открыт \n», ntohs (th -> source )); break; } return (1); } #include < linux/types.h > __u16 in_cksum ( __u16 *ptr, int nbytes ) { register __u32 sum; __u16 oddbyte; register __u16 answer; sum = 0; while ( nbytes > 1 ) { sum += *ptr ++; nbytes -= 2; } if ( nbytes == 1 ) { oddbytes = 0; * (( unsigned char *) &oddbyte ) = * (unsigned char *) ptr; sum += oddbyte; } sum = ( sum >> 16 ) + ( sum & 0xFFFF); sum += (sum >> 16 ); answer=~sum; return (answer); } CC = gcc name = scan SCAN = scan.o checksum.o getsock_send.o getsock_recv.o $( name ) : $( SCAN ) $( CC ) -g -o $( name ) $( NAME ) scan.o : scan.c $( CC ) -c scan.c checksum.o : checksum.c $( CC ) -c checksum.c getsock_send.o : getsock_send.c $( CC ) -c getsock_send.c getsock_recv.o : getsock_recv.c $( CC ) -c getsock_recv.c clean: rm -f *.o Всеволод Стахов Программирование сокетов int socket(int domain, int type, int protocol); PF_UNIX или PF_LOCAL Локальная коммуникация для ОС Unix(и подобных) PF_INET IPv4, ip протокол Internet, наиболее распространён сейчас(32-х битный адрес) PF_INET6 IPv6, следующее поколение протокола ip(IPng) - 128 битный адрес PF_IPX IPX - протоколы Novell int connect(int sock_fd, const struct *sockaddr serv_addr, socketlen_t addr_len); struct sockaddr_in{ sa_family_t sin_family; — определяет семейство адресов, всегда должно быть AF_INET u_int16_t sin_port; — порт сокета в сетевом порядке байт struct in_addr sin_addr; — структура, содержащая ip адрес }; Структура, описывающая ip-адрес: struct in_addr{ u_int32_t s_addr; — ip адрес “сокета в сетевом порядке байт }; u_int32_t inet_addr(const char *ip_addr) struct HOSTENT* gethostbyname(const char *host_name) int send(int sockfd, void *data, size_t len, int flags); — отправляет буфер data int recv(int sockfd, void *data, size_t len, int flags); принимает буфер data #include /* Стандартные библиотеки сокетов для Linux */ #include /* Для ОС Windows используйте #include */ #include int main(){ int sockfd = -1; /* Дескриптор сокета */ char buf[128]; /* Указатель на буфер для приёма */ char s[] = "Client ready\n"; /* Строка для передачи серверу */ HOSTENT *h = NULL; /* Структура для получения ip адреса */ sockaddr_in addr; /* Cтруктура tcp/ip протокола */ unsigned short port = 80; /* Заполняем поля структуры: */ addr.sin_family = AF_INET; addr.sin_port = htons(port); sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); /* Создаём сокет */ if(sockfd == -1) /* Создан ли сокет */ return -1; h = gethostbyname("www.myhost.com"); /* Получаем адрес хоста */ if(h == NULL) /* А есть ли такой адрес? */ return -1; addr.sin_addr.s_addr = inet_addr(h->h_addr_list[0]); /* Переводим ip адрес в число */ if(connect(sockfd, (sockaddr*) &addr, sizeof(addr))) /* Пытаемся соединится с удалённым сокетом */ return -1; /* Соединение прошло успешно - продолжаем */ if(send(sockfd, s, sizeof(s), 0) < 0) /* Посылаем удалённому сокету строку s */ return -1; if(recv(sockfd, buf, sizeof(buf), 0) < 0) /* Получаем ответ от удалённого сервера */ return -1; printf("Recieved string was: %s", buf); /* Вывод буфера на стандартный вывод */ close(sockfd); /* Закрываем сокет */ /* Для Windows применяется функция closesocket(s) */ return 0; } int bind(int sockfd, const struct *sockaddr, socklen_t addr_len); int listen(int sockfd, int backlog); int accept(int sockfd, struct *sockaddr, socklen_t addr_len) int main(){ pid_t pid; /* Идентификатор дочернего процесса */ int sockfd = -1; /* Дескриптор сокета для прослушивания */ int s = -1; /* Дескриптор сокета для приёма */ char buf[128]; /* Указатель на буфер для приёма */ char str[] = «Server ready\n»; /* Строка для передачи серверу */ HOSTENT *h = NULL; /* Структура для получения ip адреса */ sockaddr_in addr; /* Cтруктура tcp/ip протокола */ sockaddr_in raddr; unsigned short port = 80; /* Заполняем поля структуры: */ addr.sin_family = AF_INET; addr.sin_port = htons(port); sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); /* Создаём сокет */ if(sockfd == -1) /* Создан ли сокет */ return -1; addr.sin_addr.s_addr = INADDR_ANY; /* Слушаем на всех адресах */ if(bind(sockfd, (sockaddr*) &addr, sizeof(addr))) /* Присваиваем сокету локальный адрес */ return -1; if(listen(sockfd, 1)) /* Начинаем прослушивание */ return -1; s = accept(sockfd, (sockaddr *) &raddr, sizeof(raddr)); /* Принимаем соединение */ pid = fork(); /* порождаем дочерний процесс */ if(pid == 0){ /* Это дочерний процесс */ if(recv(s, buf, sizeof(buf), 0) < 0) /* Посылаем удалённому сокету строку s */ return -1 if(send(s, str, sizeof(str), 0) < 0) /* Получаем ответ от удалённого сервера */ return -1; printf(«Recieved string was: %s», buf); /* Вывод буфера на стандартный вывод */ close(s); /* Закрываем сокет */ return 0; /* Выходим из дочернего процесса */ } close(sockfd); /* Закрываем сокет для прослушивания */ return 0; } WSADATA wsaData; WSAStartup(0x0101, &wsaData); WSACleanup(); pid = fork(); /* Создание первого дочернего процесса */ if (pid <0){ /* Ошибка вызова fork */ printf(«Forking Error : )\n»); exit(-1); }else if (pid !=0 ){ /* Это первый родитель! */ printf(«\nThis is a Father 1\n»); }else{ pid = fork(); /* Работа 1-го родителя завершается */ /* И мы вызываем ещё один дочерний процесс */ if (pid <0){ printf(«Forking error : )\n»); exit(-1); }else if (pid !=0 ){ /* Это второй родитель */ printf(«\nThis is a father 2\n»); }else{ /* А вот это тот самый 2-й дочерний процесс */ /* Переход в «стандартный» режим демона */ setsid(); /* Данный процесс становится главным в группе */ umask(0); /* Стандартная маска файлов */ chdir(«/»); /* Переход в корневой каталог */ daemoncode(); /* Собственно сам код демона */ /* При вызове fork демона появляется потомок-демон */ } } Андрей Филлипович Взаимные функциональные зависимости CREATE VIEW UslFD AS SELECT Pse1.* FROM table1 AS Pse1, table1 AS Pse2 WHERE (Pse1.C= Pse2.C) & (Pse1.A<> Pse2.A) & (Pse1.B<> Pse2.B) WHERE (Pse1.C1= Pse2.C1) &(Pse1.C2= Pse2.C2) &…& (Pse1.Cn= Pse2.Cn) & (Pse1.A<> Pse2.A) & (Pse1.B<> Pse2.B) CREATE ASSERTION UslFD CHECK ( SELECT Pse1.* FROM table1 AS Pse1, table1 AS Pse2 WHERE (Pse1.C= Pse2.C) & (Pse1.A<> Pse2.A) & (Pse1.B<> Pse2.B) ) for i:=1 to n do // цикл по всем ФЗ { m:=m(X[i]); // подсчет количества атрибутов в левой части for j:=1 to m do // цикл по всем атрибутам {Left_Part:= X[i][j]; // выбор одного из атрибутов for k:=1 to n do // цикл по всем ФЗ // если условие выполняется, то возможно наличие кольцевой структуры {if Left_Part == Y[k] then //функция проверяет множество S на наличие ВФЗ //между X[i][j] и Y[i] при условии X[i]- X[i][j] call function_1(Left_Part, Y[i], X[i]- X[i][j]); Restore S, n; //восстановление полного списка ФЗ } } } //функция проверяет множество S на наличие ВФЗ //между Left_Part и Right_Part при условии Usl function_1(Left_Part, Right_Part, Usl) for i:=1 to n do // цикл по всем ФЗ { if (Right_Part I X[i]) then //если правый атрибут вхо дит // в левую часть какой-либо ФЗ { Usl:=Usl+ X[i] - Right_Part; // то условие допол няется другими //атрибутами из ле вой части if (Left_Part == Y[i]) then //если произошло закольцевание { Add «Usl | Left_Part ~ Right_Part» //добавляет ся новая УВФЗ delete X[i]®Y[i]; //данная ФЗ удаляется из S n:=n-1; //количество ФЗ уменьшается } else //иначе осуществляется рекурсивный вызов для дальнейшего поиска { Right_Part := Y[i]; delete X[i]®Y[i]; //данная ФЗ удаляется из S n:=n-1; //количество ФЗ уменьшается function_1(Left_Part, Right_Part, Usl); } } } Елена Ртищева CommerceML - стандарт обмена коммерческой информацией в формате XML Собирательный элемент для всего, что может быть упомянуто в процессе обмена description>Предназначен для передачи «сопроводительной записки» в виде произвольной текстовой информации по документу.