Automatizando Build de um programa com Makefile

Bom. faz um bom tempo que não posto algo no Blog pois estive meio ocupado com alguns projetos, provas e trabalhos, pois cá estou  para ensinar uma coisa que pode te salvar vidas com a parte mais chata de um programa.  sua transformação de código-fonte para  código de maquina.

A Maioria deve estar acostumado em clicar no botão “Build”  e depois “Run” e Voilà!  seu programa rodando bonitinho.

mas no Linux  90% dos aplicativos para compilar terá o uso do Makefile, alguns usam CMake que seria uma alternativa ao Make.

Temos esses 3 Arquivos de codigo-fonte em C.

onefile.c
subtracao.h
subtracao.c

precisamos fazer um build na ordem onde onefile.c contem o main()

CC=cc
CFLAGS=-Wall -O2
BIN_NAME =onefile

SRC=$(wildcard *.c)
OBJ=$(SRC:%.c=%.o)

all: $(BIN_NAME)

$(BIN_NAME): $(OBJ)
	$(CC) $(CFLAGS)  $^ -o $@

%.c.o: $(SRC)
	$(CC) -c $^

clean:
	@rm -rf *.o

no começo pode parecer confuso mas vamos por parte o que significa cada coisa

CC=cc cria uma variável para o compilador, não é 100% necessário mas facilita caso precise trocar de compilador pois afeta o script todo

CFLAGS=-Wall -O2 – parâmetros passados para o compilador -Wall apenas mostra todos os warnings, e -O2 é so uma otimizacao na compilação

BIN_NAME =onefile nome do arquivo binário final

SRC=$(wildcard *.c) – lista todos codigos fontes .c na pasta
OBJ=$(SRC:%.c=%.o) – associa todos arquivos codigo-fonte .c mas com extensão .o

%.c.o: $(SRC)
	$(CC) -c $^

este pedaço de codigo automatiza a compilação transformando todo pedaço de codigo em C para arquivo de objeto para ser linkado mais tarde


$(BIN_NAME): $(OBJ)
	$(CC) $(CFLAGS)  $^ -o $@

este pedaço do script pega todos arquivos objetos e linka transformando em um arquivo binário executável
ou ELF

all: $(BIN_NAME)

all e um comando padrão do make para quando a pessoa digita make no bash all é o primeiro a ser chamado
com $(BIN_NAME) invoca o script acima compilando os objetos que acaba  invocando  o outro pedaço do script para compilar os pedaços de codigos

não importando quantos codigos fontes tem na pasta ele lista e compila automaticamente

 Para quem quiser experimentar. baixe : Arquivo para Download

basta extrair e digitar make e ver a ” mágica” acontecer

Tutorial Básico de Como Criar um Módulo de Extensão do Python em C

Olá Meus Amigos. Hoje vou ensina-los a criar um modulo simples em que pode ser importado diretamente pro Python mas usando C Este método tem pontos fortes e pontos fracos. então antes de sair criando módulos por ai vou explicar esses pontos para que possa medir se vale a pena ou não usar estas extensões em seus programas. e também vou explicar as diferenças entre incluir um modulo via importação e via chamada (usando ctypes) que faz parte da biblioteca padrão do Python

Continuar lendo

Escrevendo Arquivo usando Syscall

Boa Tarde Meus Caros. hoje vou ensinar como  escrever um arquivo simples usando open e write
que são syscalls do sistema linux

syscalls são chamadas de baixo nivel  diretamente pelo kernel geralmente são representadas como números no assembly

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>


int main(int argc, char *argv[]){


int fd = open("meuarquivo.txt", O_RDWR | O_CREAT, S_IRWXU );
write(fd, "teste", 6 );
close(fd);


return 0;
}

#include <stdio.h> /* Biblioteca padrão. */
#include <unistd.h> /* para funções como read, write open  */
#include <fcntl.h> /* para O_RDWR, O_CREAT, S_IRWXU */
#include <sys/stat.h> /* struct  stat */

Estas bibliotecas são essenciais para poder usar as funções demonstrada nesse post
lembrando que nao pode funcionar em outros sistemas operacionais como windows

int fd = open("meuarquivo.txt", O_RDWR | O_CREAT, S_IRWXU ); /* fala pro kernel criar um arquivo com a função leitura / escrita e permissão total */
write(fd, "teste", 6 );  /* escreve o texto, lembrando que o ultimo parametro é o tamanho do buffer a ser escrito */ 
close(fd);

fd é o file descriptor, é um numero unico que o kernel identifica o arquivo aberto para leitura ou escrita

write é a função para escrever o dado do buffer no arquivo, o ultimo parametro é o tamanho do buffer a ser escrito. se o tamanho do buffer for maior que o proprio buffer o tamanho extra será preenchido com Zero

fiz um exemplo de uso syscall como é chamado via assembly
me perdoe nao sou nenhum expert no assembly se tiver algo errado me envie uma mensagem

Revisão do codigo:

section .data
  texto       db "teste",10
  texto_len  equ $ - texto

  arq      db "meuarquivo.txt",0
  arq_len  equ $ - arq

  sys_open 	equ 5 ; syscall numero 5
  sys_write	equ 4 ; syscall numero 4
  sys_close     equ 6 ; syscall numero 6




section .text

global _start

_start:
		; estes comandos abaixo e equivalente a
		; int fd = open("meuarquivo.txt", O_RDWR, S_IWRXU);
		; em C

		mov eax, 5 ; syscall da funcao open
		mov ebx, arq ; 2 parametro nome do arquivo
		mov ecx, 100 ; valor do tipo de abertura
		mov edx, 0o777 ; permissao  do usuario
		int 80h 
		xchg eax, esi ; realiza um swap  passando eax pra esi
		
		
		; estes comandos abaixo e equivalente a
		; write(fd, "teste", 5)
		; em C
	
		mov edx, 5 ; tamanho do buffer a ser gravado
		mov ecx, texto ; teexto a ser gravado
		mov ebx, esi ;  file descriptor  do arquivo
		mov eax, 4	;syscall de write()

	
			; estes comandos abaixo e equivalente a
		; close(fd)
		; em C
		mov eax, 6 ; syscall de close()
		;ebx ja esta definido com o file descriptor
		int 80h	
		
		; equivalente a exit(0);
		mov eax, 1 ; syscall  de exit()
		mov ebx, 0 ;  passa  1 parametro 0
		int 80h	



		


             

digamos que voce queira saber qual o file descriptor de um tipo de dado FILE*

basta usar fileno();

  FILE* fp = fopen("meuarquivo.txt","wb");
  int fd = fileno(fp)

agora voce pode usar funcões de write e read diretamente do FILE

Criando um Módulo Simples para o Kernel Linux

Olá meus caros.  todos sabem da flexibilidade que o linux nos oferece. principalmente o fato de poder criar um modulo  e por um lado é bem simples

 

#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>

static int __init mymodule_init(void)
{
 printk ("Hello World!\n");
        return 0;
}

static void __exit mymodule_exit(void)
{
 printk ("Removendo Modulo.\n");
        return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");

Quebrando o Codigo:

 

#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>

Esta são as biliotecas de inicialização. elas contem funç~ioes essenciais para realizar a acoplagem do modulo no kernel

static int __init mymodule_init(void)
{
 printk ("Hello World!\n");
        return 0;
}

static void __exit mymodule_exit(void)
{
 printk ("Removendo Modulo.\n");
        return;
}

Funções de chamada inicial e função de chamada quando o modulo é desativado. onde a chamada deste modulo inicia.
todos ja acoplados ao kernel modulos tem essas duas funções inclusas
deve estar estranhando o printk inves de printf
printk é função nativa do kernel para imprimir no terminal possiveis problemas ou informações
mas ai a questão o printf tambem faz isso.

mas o printk é totalmente independente da libc do linux. o kernel tem que manter o mais independente possível de funções e chamadas das bibliotecas padrão do sistema

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");

estas funções são nativas do kernel elas que registram no kernel as funções de inicio e fim

são esses módulos que nascem os drivers para linux. que na verdade são apenas modulos oferecendo suporte a um hardware específico

Referencias: http://www.linuxchix.org/content/courses/kernel_hacking/lesson8

Criando Callbacks em C

Callbacks são ponteiros de funções que necessita ser associado a um endereço de memoria  de uma outra função  para ser chamado
quase equivalente a um método abstrato de uma classe

Casos De Uso:

  •   Uma estrutura de chamada de comandos
  • Sistema de plugins onde as chamadas do plugin são alocados em um callback

 

#include <stdio.h>

typedef int (*calc)(int a, int b);

int soma(int a, int b){
  return (a+b);
}

int mul(int a, int b){
  return (a*b);
}

int sub (int a, int b){
  return (a-b);
}

int main(int argc, char * argv[]){

   calc c;

   c = &soma;
   printf("SOMA: %d+%d=%d\n",2,2, c(2,2));

   c = &sub;
    printf("SUBTRACAO: %d-%d=%d\n",2,2, c(2,2));

   c = &mul;
   printf("MULTIPLICACAO: %d*%d=%d\n",2,2, c(2,2));

return 0;
}

passando parâmetros como referência em C

Olá meus caros hoje vou ensinar uma técnica Simples de alterar o valor de uma variável por uma função

Casos de uso:

  • Digamos que crie uma função. e  precise alterar um valor em alguma variavel. mas  tambem precisa checar  se a função retorne se esta OK ou não
  • passar uma estrutura para uma função e alterar seus dados
  • alocar memoria a um ponteiro e checar se ele foi ou não criado com sucesso
  • Entre outras  possibilidades

 


#include <stdio.h>

int  changePtr(int** my_val){
if ( (*my_val) != NULL){
(*my_val) =  9001;
printf("Its Over 9000\n");
return 1;
}
return 0;

}

int main(int argc, char * argv[]){

int *p;
p = NULL;

if(changePtr(&p) == 0){
printf("CASO DE FALHA\n");
printf("VALOR DE P: %d\n", p);
}

printf("CASO DE SUCESSO P = 2000 \n");
p = 2000;

changePtr(&p);

printf("Valor de P: %d\n", p);

return 0;
}

 Quebrando o Codigo:


#include <stdio.h>

</pre>
<pre>
int  changePtr(int** my_val){
if ( (*my_val) != NULL){
(*my_val) =  9001;
printf("Its Over 9000\n");
return 1;
}
return 0;

}

esta função recebe um ponteiro de um ponteiro int

verifica se my_val é NULL

SE sim.  a função retorna 0

SE não a função retorna 1 e altera o ponteiro  apontado para esse ponteiro duplo

 

Concluindo:

A variável que passou  para o parametro da função  pode ser editada dentro da mesma
não abuse dessa funcionalidade principalmente para dados sensiveis que requer precisão. o resultado pode ser modificado a qualquer momento  no fluxo do programa comprometendo o resultado esperado.

Adicionar Programas Para Rodar Automaticamente após o login do LXDE

Bom Dia Caros. Digamos que você precisede um programa que inicie junto com  seu LXDE (que é  meu Desktop Environment  favorito)

vá em:


$ cd ~/.config/lxsession/LXDE/

de um ls para checar se o arquivo autostart existe


$ ls | grep  autostart

se não retornar nada   crie um arquivo  novo

$ touch autostart

 

e usando o nano ou vim ou o editor de sua preferência

adicione os executaveis com um @ na frente

ex:

@meuprograma

@meuprograma2

 

Obs: para que isso funcione os programas deve estar na path ou nos diretorios onde se encontram os binarios ex: /bin ou /usr/bin

para que possam ser chamados sem definir caminho

 

caso não esteja na path  vou ensinar como adiciona:

digite usando o seu editor de textos favorito

$  vim $HOME/.bashrc

 

e no final do arquivo adicione uma variavel com o path do seu programa

ex:

MEUPROGRAMA=/home/meusuario/programa/

depois adicione

PATH=$PATH:$MEUPROGRAMA

pronto ja adicionou o programa ao path e essa configuração vai ser permanente (para o seu usuario)

 

Criar um Modulo Para CBIRCMINIBOT

Olá a todos hoje vou ensinar como criar um modulo para o minicbircbot que é um projeto de minha autoria, muito simples de usar

Primeiro baixe o projeto do bitbucket pode ser clonando  repositori


$ git clone https://ryonagana@bitbucket.org/ryonagana/cbircbot.git

entre na pasta minicbircbot/minicbircbot/bot

crie pasta chamada HelloWorld

depois  isso crie um arquivo chamado __init__.py

cole este codigo:


import datetime


from minicbircbot.packages.irc.ircbotinterface import IrcBotInterface


class HelloWorld(IrcBotInterface):
	def __init__(self, irc = None):
		super().__init__(irc)


		self.owner = ["seunick"]
		
		self.module_name = "HelloWorld"

		#registra o comando no modulo onde vai ser gerado o help automaticamente
		#basta ir no PVT do bot e digitar !help HelloWorld
		#e vai mostrar a lista de comandos registrados

		
		#comando !hello do tipo somente PVT 
		self.register_command("!hello", self.doHelloWorld,  self.CMD_TYPE_BOTH, "my description")


	def doHelloWorld(self, handler):

		irc, msghandler = handler # captura 2 handlers que são repassado para todos os modulos
		prefix, command, count = self.args(msghandler.message) #verifica as funções e retorna separadadas
		#prefix é caracter de comando (neste caso  o !)
		#command é o texto do comando que voce digitou no caso ela pertence ao !hello então retorna "hello" sem o !
		#count retorna a quantidade de parametros sem contar  o comando para ter controle

		#irc e a referencia a classe principal do irc
		#msghandler retorna informações da pessoa que ativou o comando
		chans = irc.config.get("chans") #pega os canais que voce definiu no config.json 

		irc.ircSendMessage(chans, "hello world!")


 

volte duas pastas no config.json

na chave Modules adicione HelloWorld

o nome deve ser identico a pasta seguindo as caixas altas e baixas.  o nome da classe dentro do  __init__.py  deve ser o mesmo da pasta

apos isso rode o bot. entre no canal onde o bot esta conectado

e digite !hello

e ele vai responder

sucesso

facil não?

Alterando valor de uma variavel através de ponteiros

Olá meus Caros hoje vou ensinar uma c das coisas que muita gente sofre. assim como eu sofri muito por ser autodidata em C e tenho muito que aprender vou ensinar a alterar o conteudo na memoria atraves de ponteiros.

 


#include <stdio.h>

int main(int argc, char* argv[]){

 int a = 999;
 int *ptr_a = &a;
 int **d = &ptr_a;

 printf("a=%d\n", a);
 printf("*ptr_a=%d\n", *ptr_a);
 printf("**d=%d\n", **d);

**d = 133;

printf("apos mudanca\n\n");
printf("a=%d\n", a);
printf("*ptr_a=%d\n", *ptr_a);
printf("**d=%d\n", **d);

return 0;
}

O Resultado Deste Código

a=999
*ptr_a=999
**d=999
apos mudanca

a=133
*ptr_a=133
**d=133

 

 

como pode ver  alterei apenas o ponteiro  de ponteiro

e ele alterou o valor que ja se encontra na memoria que é o int a

 

não sou nenhum conhecer profundo de C mas acredito que este exemplo seja bem simples

caso tiver sugestões escreve um comentario. se tiver algo para corrigir  tambem. foque a vontade. e até mais

 

 

 

 

Criando um bot simples para IRC em Python

Olá Meus Caros,

hoje vou ensinar como criar um bot simples que se conecta a um servidor irc  (Yet another bot irc)

voou tentar  simplificar ao máximo

vou seguir o padrão do python 2.7x   que na minha opinião é mais didático que o 3.4

 

agradecimento ao mano ctx, que  infelizmente nao tenho mais contato que bolou esse codigo simples e assim que aprendi a criar um sistema mais complexo a partir deste codigo

Continuar lendo