Livro sobre C e Linux
Publicado; abril 12, 2014 Arquivado em: C, programação, rede, sistema | Tags: Grátis, Linguagem C, linux, Livro Deixe um comentárioHoje decidi abrir uma exceção e postar esse link aqui. É um livro que escrevi há 9 anos e nunca foi revisado nem publicado, mas que ainda pode ser útil para muitos novos programadores.
urban terror, udp proxy
Publicado; dezembro 25, 2008 Arquivado em: jogos, programação, python, rede | Tags: linux, python, udp proxy, urban terror 7 ComentáriosA internet é mesmo um lugar maluco. Eu não sou muito de jogar, mas nos últimos meses um amigo me mostrou o urban terror, um jogo no estilo counter strike que é gratuito, baseado na engine do quake3 arena.
Dias depois fui banido de um dos servidores mais populares do negócio, o bashfull, e então desencanei e nunca mais joguei lá. Porém, várias vezes que fui jogar, não havia ninguém nos outros servidores, e lá estava sempre cheio de gente.
Tentei o meio normal da coisa e mandei 2 emails pro admin, nos últimos 20 dias. Como fui ignorado, e meu IP do virtua é fixo, não sobrou outra alternativa a não ser usar um proxy no estilo BNC, tipo os que eu usava a uns 10 anos atrás nas épocas do irc.
Pra terminar, não achei nada que preste pra fazer proxy Nx1 via udp – talvez eu seja burro de mais pra procurar essas bobeiras – e então acabei escrevendo um em python.
Em 20 minutos, fiz tudo e testei em um ubuntu. Ficou bem simples, veja ai:
#!/usr/bin/env python
# coding: utf-8
# 20081225 AF
#
# urban terror asynchronous udp proxy
# requires python 2.5 (linux, bsd, etc)
# configuration
maxclients = 10
proxyport = 27960
ut_server_addr = ‘189.38.63.196’
ut_server_port = 27962
# don’t touch anything below.
import os, sys, time, syslog, socket, select, threading
clients = {}
timeout = 15
pktsize = 4096
infolog = lambda msg: syslog.syslog(syslog.LOG_INFO, msg)
def daemonize():
# double fork, ignore exceptions
pid = os.fork()
if not pid:
os.setsid()
pid = os.fork()
if not pid:
os.chdir(‘/’)
[k.close() for k in sys.stdin, sys.stdout, sys.stderr]
else:
os._exit(0)
else:
os._exit(0)
def cleaner():
# remove inactive slots
while 1:
now = time.time()
for slot in clients.values():
if now – slot.time > timeout:
infolog(‘client %s disconnected’ % str(slot.addr))
del clients[slot.addr]
time.sleep(5.0)
class proxy:
def __init__(self, addr):
self.addr = addr
self.time = time.time()
self.fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.fd.connect((ut_server_addr, ut_server_port))
def send(self, chunk):
self.time = time.time()
return self.fd.send(chunk)
if __name__ == ‘__main__’:
fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
fd.bind((”, proxyport))
daemonize()
syslog.openlog(‘utproxy’, syslog.LOG_PID, syslog.LOG_DAEMON)
threading.Thread(target=cleaner).start()
while 1:
current = [k.fd for k in clients.values()] + [fd]
rr, rw, er = select.select(current, [], [])
if fd in rr:
chunk, addr = fd.recvfrom(pktsize)
if addr in clients.keys(): # from proxy (cli=addr) to server
clients[addr].send(chunk)
else:
if len(clients) < maxclients:
infolog('client %s connected' % str(addr))
clients[addr] = proxy(addr)
clients[addr].send(chunk)
else:
syslog.syslog(syslog.LOG_INFO,
'client %s rejected: proxy is full' % str(addr))
for cli in clients.values():
if cli.fd in rr: # from server to proxy (cli=addr)
chunk = cli.fd.recv(pktsize)
fd.sendto(chunk, cli.addr)[/sourcecode]
Como o proxy não precisa fazer absolutamente nenhum processamento, todo o repasse de pacotes é feito de modo assíncrono, em um único processo, e uma thread verifica as conexões inativas para removê-las da lista.
Até poderia fazer o proxy de outras maneiras, talvez usando asynchat ou mesmo twisted, mas acabei optando pelo modo tradicional e o resultado é que ele não depende de nenhum módulo externo, apenas coisas básicas do python 2.5.
Agora, quando entrar lá, só vou matar o bashfull. Meu nick é /dev/null.
linux fmemopen, bsd funopen
Publicado; dezembro 12, 2008 Arquivado em: C, mac os, programação, sistema | Tags: ansi c, bsd, fmemopen, funopen, linux, mac os x 1 comentárioEnquanto desenvolvia um sistema, me deparei com um problema entre plataformas, relacionado ao uso e manipulação de arquivos temporários em memória.
Ao invés de gravar um arquivo temporário no disco e ir populando com o conteúdo, meu caso exigia que esse arquivo fosse populado em memória para uso posterior, e a API do Linux (via libc) fornece a função fmemopen(3).
Porém, meu ambiente de desenvolvimento é no Mac OS X, e devido ao tipo do software, era inevitátel tanto desenvolver como testar tudo nessa mesma máquina, para então posteriormente colocá-lo em produção em um Linux. O problema é que o OS X herdou a API do BSD, que ao invés de fmemopen, fornece apenas o funopen(3).
Por esse motivo, acabei escrevendo uma versão bem simples do fmemopen do Linux para usar no OS X, usando funopen internamente. O único detalhe, e provavelmente a diferença entre a versão original do fmemopen pra minha, é que a minha simplesmente ignora o modo de acesso ao arquivo (“r”, “w”, etc). O fato é que agora posso continuar desenvolvendo tudo no OS X e depois compilar no Linux obtendo o mesmo resultado.
fmem.h:
/* * fmem.h : fmemopen() on top of BSD's funopen() * 20081017 AF */ #ifndef _FMEM_H #define _FMEM_H #ifndef linux #include <stdio.h> extern FILE *fmemopen(void *buf, size_t size, const char *mode); #else #define _GNU_SOURCE #endif #endif /* fmem.h */
fmem.c:
/* * fmem.c : fmemopen() on top of BSD's funopen() * 20081017 AF */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef linux struct fmem { size_t pos; size_t size; char *buffer; }; typedef struct fmem fmem_t; static int readfn(void *handler, char *buf, int size) { int count = 0; fmem_t *mem = handler; size_t available = mem->size - mem->pos; if(size > available) size = available; for(count=0; count < size; mem->pos++, count++) buf[count] = mem->buffer[mem->pos]; return count; } static int writefn(void *handler, const char *buf, int size) { int count = 0; fmem_t *mem = handler; size_t available = mem->size - mem->pos; if(size > available) size = available; for(count=0; count < size; mem->pos++, count++) mem->buffer[mem->pos] = buf[count]; return count; // ? count : size; } static fpos_t seekfn(void *handler, fpos_t offset, int whence) { size_t pos; fmem_t *mem = handler; switch(whence) { case SEEK_SET: pos = offset; break; case SEEK_CUR: pos = mem->pos + offset; break; case SEEK_END: pos = mem->size + offset; break; default: return -1; } if(pos < 0 || pos > mem->size) return -1; mem->pos = pos; return (fpos_t) pos; } static int closefn(void *handler) { free(handler); return 0; } /* simple, but portable version of fmemopen for OS X / BSD */ FILE *fmemopen(void *buf, size_t size, const char *mode) { fmem_t *mem = (fmem_t *) malloc(sizeof(fmem_t)); memset(mem, 0, sizeof(fmem_t)); mem->size = size, mem->buffer = buf; return funopen(mem, readfn, writefn, seekfn, closefn); } #endif
E finalmente, um programa simples para testar o uso da função, que compila e produz o exato mesmo resultado tanto no Linux como no OS X – não testei em outros BSDs, mas suponho que deva funcionar também.
test.c:
/* * test.c : memory fp test * 20081212 AF */ #include "fmem.h" #include <stdio.h> #include <string.h> int main() { FILE *fp; char buff[128], temp[128]; memset(buff, 0, sizeof buff); fp = fmemopen(buff, sizeof buff, "r+"); fprintf(fp, "hello world"); fseek(fp, 0, SEEK_SET); memset(temp, 0, sizeof buff); fgets(temp, sizeof temp, fp); fclose(fp); fprintf(stdout, "read: [%s]\n", temp); return 0; }
Para compilar, basta o usar o seguinte Makefile:
CC=gcc
RM=rm -f
NAME=test
.SUFFIXES = .o
OBJECTS = test.o fmem.o
.c.o:
$(CC) -Wall -c -o $@ $<
all: $(OBJECTS)
$(CC) -Wall -o $(NAME) $(OBJECTS)
clean:
$(RM) $(NAME) $(OBJECTS)[/sourcecode]
levelhead: o jogo mais 3d !
Publicado; setembro 5, 2008 Arquivado em: jogos | Tags: 3d, jogo, linux Deixe um comentárioSem palavras. Veja o video, acesse o site, compile o fonte.
mac address da placa de rede com python (linux)
Publicado; maio 4, 2008 Arquivado em: programação, python, rede, sistema | Tags: af_packet, ioctl, linux, mac, mac address, python 2 ComentáriosPra pegar o endereço MAC (Media Access Control) de uma placa de rede com python, você precisa primeiro ser root.
Aqui vai um exemplo:
sudo python >>> import socket >>> fd = socket.socket(socket.AF_PACKET, socket.SOCK_RAW) >>> fd.bind(('eth0', 9999)) >>> mac = fd.getsockname()[-1] >>> print ':'.join(['%02x' % ord(n) for n in mac]) 00:16:d3:93:c2:e6
Outros sistemas:
1. Encontrei um cara que faz isso no Windows da maneira mais tosca – interpretando o resultado do ipconfig /all. Acho que deve ter uma maneira melhor que essa. Em todo caso, veja o link.
2. Outros Unix-like tipo BSD não têm AF_PACKET, então isso não funciona. Pra cada um, tem que saber qual é o ioctl que manda pro socket, ai usando o módulo struct do python fica fácil pegar o resultado.
usando find para encontrar arquivos antigos
Publicado; abril 17, 2008 Arquivado em: sistema, unix toolbox | Tags: atime, ctime, find, linux, mtime, unix 1 comentárioA maioria dos administradores de sistemas UNIX provavelmente já fez isso. Se não, ainda vai precisar.
É uma coisa simples, que todo mundo sabe que é possível, mas sempre esquece. Eu mesmo esqueço e por isso vou postar aqui, ai fica mais fácil quando esquecer denovo.
find /tmp -iname \*.jpg -atime +1 -print
Esse comando mostra os arquivos com extensão JPG (case insensitive, -iname) no diretório /tmp, que tenham sido acessados a mais de 1 dia – por isso +N. Pode-se usar -N para datas menores que N: se fosse -1, encontraria arquivos que foram acessados a menos de 1 dia. Quando não há sinal, encontra com exatidão: se fosse -atime 2, encontraria arquivos que foram acessados a exatamente 2 dias.
No manual find(1) há a descrição de todas opções, como -atime, -amin e -anewer. Também, das variantes com -ctime e -mtime (-cmin, etc).
Só pra lembrar:
- Estes dados são armazenados na struct stat, descrita no manual stat(2)
- o atime é atualizado quando há algum tipo de acesso no arquivo – com execve(2), read(2), etc.
- o mtime é atualizado quando há modificação no arquivo – quando novos dados são escritos nele, truncate(2), write(2). No caso de diretórios, o mtime do diretório é atualizado quando arquivos são criados ou removidos nele.
- o ctime é atualizado quando há escrita no arquivo, ou quando suas permissões são alteradas – write(2), chmod(2), chown(2), etc.
ping: partimage is not ghost
Publicado; março 19, 2008 Arquivado em: rede, sistema | Tags: backup, disk, ghost, image, linux, partimage, ping Deixe um comentárioUm sistema ideal para backup e restore offline, que cria imagens de partições do disco. Soa como o ghost, né? Mas, além de várias vantagens sobre o ghost, o PING é totalmente gratuito e distribuído como ISO – que ao gravar em um CD pode ser usado como live-cd para executar as tarefas.
Além disso, as imagens geradas pelo PING podem ser gravadas em CD, DVD, já com sistema de restore automatizado.
Para mais informações, veja o site do PING.
Comentários