Archives for C category

LibSDL exemplo Fogos de artifício

Posted on fev 25, 2009 under C | 1 Comentário

Pessoal

Quem curte fogos de artifício e programação em C com libsdl, eis aqui um exemplo muito bom para experimentar SDL com OpenGL.
Veja o screenshot:

exemplo SDL fogos de artifício

Características:
- OpenGL
- Reprodução de .wav
- Threads
- Interação do Teclado
- Números Randômicos

Esse exemplo de SDL pode ser modificado para um gerador de partículas, podendo modificar as cores, velocidade, número de partículas e muito mais.

Baseado na lição 19 do site: http://nehe.gamedev.net/
fogos.tar.gz

AVL com Ncurses em C

Posted on jul 17, 2008 under C | 3 Comentários

Olhando os trabalhos que realizei na faculdade. Encontrei uma AVL desenvolvida para a cadeira de estutura de dados. Implementei utilizando como interface gráfica NCURSES, para mostrar a árvore.

Irei compartilhar o código. Com certeza será bastante util para quem está estudando.
Este código tem alguns conceitos interessantes como:

  • Não utiliza variáveis globais
  • Os dados são inseridos na árvore quando ficar desbalanceada é informado e solicitado ao usuário se deseja balancear a árvore
  • Informe como a árvore esta desbalanceada em quatro casos: EE,ED,DD e DE
  • Calcula a altura da árvore
  • Menu em Ncurses
  • Visualização da árvore com Ncurses
/*
 * Nome: Marlon Luis Petry
 * Description: AVL
 compilacao
 gcc       "Avl-Marlon.c"     -o "Avl-Marlon" -g  -lncurses -w
 Data: 20/10/2005

 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include 
#include 
#include 
#include 

#define CENTERX COLS/2
#define CENTERY LINES/2
#define DIST 5

typedef char string[50];

typedef struct t {
	 string info;
	 int alt;
	 struct t *pai;
	 struct t *left;
	 struct t *right;
	 }tree;

int tipoBal = -1;
string bal[4] = {"Caso EE","Caso ED","Caso DD","Caso DE"};	 

tree *bal_esq(tree *aux);
tree *bal_dir(tree *aux);
tree *rotacaoRR(tree *aux);
tree *rotacaoLL(tree *aux);
tree *rotacaoLR(tree *aux);
tree *rotacaoRL(tree *aux);

tree *insere(tree **root, string info, int  h) {

    char ch;
    tree *aux;

    if (*root == NULL)
	 {
		 aux = (tree *) malloc(sizeof(tree));
		 strcpy(aux->info,info);
		 aux->left = NULL;
		 aux->right = NULL;
		 aux->pai = NULL;
		 aux->alt = 0;
		 h = 1;
		 *root = aux;
	 }
	 else
	 {
         if (strcmp(info,(*root)->info) < 0)
		 {
                 insere(&(*root)->left, info, h);
                 //Atualiza PAI do nó inserido
                 if ((*root)->left->pai == NULL)
                     (*root)->left->pai = *root;

             	 if (h)
                     switch((*root)->alt)
					 {
                         //Estava mais alto à direita e inseriur mais um nó à esquerda
                         case -1:
                             (*root)->alt = 0;
                             h = 0; //Não propaga os ajustes nos fatores de balanceamento
                              break;
                         case 0:
                             (*root)->alt = 1; //o lado esquerdo fica maior e os fatores de
                                           //balanceamento acima deverao ser ajustados
                              break;
                         case 1:
							mvprintw(8,10,"Arvore Desbalaceou a esquerda A = %s Y = %s",(*root)->info,info);
                            mvprintw(9,10,"Baleancear (S)im (N)nao: ");
                            scanw("%c",&ch);
						 	if(ch == 'S' || ch == 's')
							{
						 	*root =  bal_esq(*root); //FB == 2 -> retorna a sub-árvore balanceada
                             h = 0; //não propaga a atualização dos fatores de
							}            //balanceamento
                              break;
                     }
		}
        else
		{
             insere(&(*root)->right, info, h);
                 //Atualiza PAI do nó inserido
                 if ((*root)->right->pai != NULL)
				    (*root)->right->pai = *root;

                 if (h)
                     switch ((*root)->alt)
				     {
                         //estava mais alto à esquerda e inseriu mais um nó à direita
                         case 1:
                             (*root)->alt = 0;
                             h = 0; //não propaga os ajustes nos fatores de balanceamneto
                              break;
                         case 0:
                             (*root)->alt = -1; // o lado direito fica maior do que o esquerdo e
                                               // o ajuste deve ser propagado
                              break;
                         case -1:
                             //FB == -2 -> retorna a sub-árvore balanceada
						 	mvprintw(8,10,"Arvore Desbalaceou a direita A = %s Y = %s",(*root)->info,info);
                            refresh();
						 	mvprintw(9,10,"Baleancear (S)im (N)nao: ");
                            scanw("%c",&ch);
						 	if(ch == 'S' || ch == 's')
							{
						 	*root = bal_dir(*root);
                             h = 0; //não propaga a atualização dos fatores de
                            }             //balanceamento
                             break;
                     }
            }
		}
           return(*root);
     }

tree *bal_esq(tree *aux)
{

    tree *p;
     p = aux->left;

     if (p->alt == 1)
	 {		 //sinais iguais e positivo
         tipoBal = 1;

		 aux = rotacaoLL(aux);
	 }
     else
	 {
		 tipoBal = 2;
         aux = rotacaoLR(aux);    //sinais diferentes
	 }
     aux->alt = 0;
 	 return(aux);
}

/*
 *  O novo nó foi inserido à direita. Ocorreu desbalanceamento (fb == 2)
 */
tree *bal_dir(tree *aux)
{

    tree *p;

     p = aux->right;
     if (p->alt == -1)                //Sinais iguais e negativo
	 {
		 tipoBal = 3;
         aux = rotacaoRR(aux);
	 }
     else
	 {
		 tipoBal = 4;
         aux = rotacaoRL(aux);     //Sinais diferentes
	 }
     aux->alt = 0;
     refresh();
     return(aux);
}

//rotacoes
tree *rotacaoRR(tree *aux) {

    tree *p;
     p = aux->right;
     aux->right = p->left;
     if (p->left != NULL)
         p->left->pai = aux;
     p->left = aux;
     p->pai = aux->pai;
     aux->pai = p;
     aux->alt = 0;

     return(p);
 }

tree *rotacaoLL(tree *aux) {

    tree *p;

     p = aux->left;
     aux->left = p->right;
     if (p->right != NULL)
         p->right->pai = aux;
     p->right = aux;
     p->pai = aux->pai;
     aux->pai = p;
     aux->alt = 0;

     return(p);
 }

tree *rotacaoLR(tree *aux) {

    tree *pai;     //ponteiro para depois atualizar o pai após a rotação
    tree *no_left;  //ponteiro para o filho esquerdo para atualizar o FB após a rotação
    tree *novo_no; //ponteiro à ser retornado
     int FB_fright;  //fator de balanceamento do no à direita do filho esquerdo

     pai = aux->pai;
     no_left = aux->left;
     FB_fright = no_left->right->alt;
     aux->left = rotacaoRR(no_left);
     novo_no = rotacaoLL(aux);
     novo_no->pai = pai;
     aux->alt = (FB_fright == 1)?-1:0; //Atualiza FB do nó rotacionado
     no_left->alt = (FB_fright == -1)?1:0; // Atualiza FB do nó à esquerda do nó rotacionado

     return(novo_no);
 }

/*
 *  Atualização do FB e balanceamento para a raíz esquerda
 */
tree *balanceamento_esquerdo(tree *no, int h) {

    tree *f_dir;
     int fb_dir;

     switch (no->alt) {
         case 1:
             no->alt = 0;
             break;
         case 0:
             no->alt = -1;
             h = 1;
             break;
         case -1:
                 f_dir = no->right;
                 fb_dir = f_dir->alt;
                 if (fb_dir <= 0) {
                     f_dir = rotacaoRR(no);
                  if (fb_dir == 0) {
                     no->alt = -1;
                        f_dir->alt = 1;
                        h = 0;
                     }
                     else {
                         no->alt = 0;
                         f_dir->alt = 0;
                     }
                     no = f_dir;
                 }
                 else {
                     no = rotacaoRL(no);
                     no->alt = 0;
                 }
     }
     return(no);
 }

 /*
 *  Atualização do FB e balanceamento para a raiz direita
 */
tree *balanceamento_direito(tree *no, int h) {

    tree *f_esq;
     int alt_esq;

    switch (no->alt) {
         case -1:
             no->alt = 0;
             break;
         case 0:
             no->alt = 1;
             h = 0;
             break;
         case 1:
             f_esq = no->left;
             alt_esq = f_esq->alt;
             if (alt_esq >= 0) {
                 f_esq = rotacaoLL(no);
                 if (alt_esq == 0) {
                     no->alt = 1;
                     f_esq->alt = -1;
                     h = 0;
                 }
                 else {
                     no->alt = 0;
                     f_esq->alt = 0;
                 }
                 no = f_esq;
             }
             else {
                 no = rotacaoLR(no);
                 no->alt = 0;
             }
     }
     return(no);
 }

/*
 *  Busca nó substituto e realizada a remoção (busca o mais à direita do nó esquerdo
 */
tree *busca_remove(tree *no, tree *no_chave, int  h) {

    tree *no_removido;
     if (no->right != NULL) {
         no->right = busca_remove(no->right, no_chave, h);
         if (h)
             no = balanceamento_direito(no, h);
     }
     else {
         strcpy(no_chave->info,no->info);
         no_removido = no;
         no = no->left;
         if (no != NULL)
             no->pai = no_removido->pai;
         h = 1;     //Deve propagar a atualização dos FB
         free(no_removido);
     }
     return(no);
 }

/*
 *  Remoção da Árvore AVL
 */
tree *removeTree(tree **raiz, int info, int h) {

    if (*raiz == NULL) {
         printf("Chave não localizada !");
         h = 0;
     }
     else {
         if (strcmp((*raiz)->info, info) > 0)
		 {
             removeTree(&(*raiz)->left, info, h);
             if (h)
                 *raiz = balanceamento_esquerdo(*raiz, h);
         }
         else if (strcmp((*raiz)->info , info) < 0)
		  {
			  removeTree(&(*raiz)->right, info, h);
              if (h)
                *raiz = balanceamento_direito(*raiz,h);
          }
          else { //Encontrou o elemento a ser removido
                 if ((*raiz)->right == NULL) {
                     if ((*raiz)->left != NULL) //Escolhe o nó à esquerda como substituto
                         (*raiz)->left->pai = (*raiz)->pai;
                     *raiz = (*raiz)->left;
                     h = 1;
                 }
                 else
                     if ((*raiz)->left == NULL) {
                         if ((*raiz)->right != NULL) //Escolhe o nó à direita como substituto
                             (*raiz)->right->pai = (*raiz)->pai;
                         *raiz = (*raiz)->right;
                         h = 1;
                     }
                     else { // Busca o elemento mais à direita do nó esquerdo
                         (*raiz)->left = busca_remove((*raiz)->left, *raiz, h);
                         //Se necessário efetua balanceamento (Esquerdo pois a função
                         //busca_remove foi para o nó esquerdo)
                         if (h)
                             *raiz = balanceamento_esquerdo(*raiz, h);
                     }
             }
     }
     return(raiz);
 } 

tree *rotacaoRL(tree *aux) { 

    tree *pai;     //ponteiro para depois atualizar o pai após a rotação
    tree *no_right;  //ponteiro para o filho direito para atualizar o FB após a rotação
    tree *novo_no; //ponteiro à ser retornado
     int FB_fleft;  //fator de balanceamento do no à esquerda do filho direito

     pai = aux->pai;
     no_right = aux->right;
     FB_fleft = no_right->left->alt;
     aux->right = rotacaoLL(no_right);
     novo_no = rotacaoRR(aux);
     novo_no->pai = pai;
     aux->alt = (FB_fleft == -1)?1:0;      //Atualiza FB do nó rotacionado
     no_right->alt = (FB_fleft == 1)?-1:0;  // Atualiza FB do nó à direita do nó rotacionado
     return(novo_no);
}

int maxDepth(tree *node) {
  if (node==NULL) {
    return(0);
  }
  else {
    int lDepth = maxDepth(node->left);
    int rDepth = maxDepth(node->right);

    if (lDepth > rDepth) return(lDepth+1);
    else return(rDepth+1);
  }
}

//print
int print(tree *r,int x, int y)
{
	int TotalWidth = width(r)*DIST;
	int centerWidth = (x + TotalWidth/2);
	int tamStr;
	int d = 0;
	//int centerWidthLinen= centerWidth +20;
	char t;
	if(r != NULL)
	{
		int leftWidth = width(r->left) * DIST;
		int rigtWidth = width(r->right) * DIST;
		tamStr = strlen(r->info);
	    mvprintw(y + (DIST/20),(centerWidth -1- (tamStr/2)),"%s", r->info);

	 if (r->left != NULL)
	 {
		int leftX = print(r->left, x , y + DIST);
	 }
	 if (r->right != NULL)
	 {
		int rightX = print(r->right, x + leftWidth, y + DIST);
	 }

	}
	return centerWidth;
}

int width(tree *root)
{
	if(root == NULL)
		return 1;
	else if(root->left == NULL && root->right == NULL)
		return 1;
	else
		return width(root->left) + width(root->right);
}

main()
{

	tree *root = NULL;
	char ch;
	string msg;
	string info;
	int opt;
	int d=0;
	initscr();

	bkgd(COLOR_PAIR(4));

	strcpy(msg,"Pressione Qualquer Tecla");
	while(1)
	{
		clear();
		mvprintw(1,10,"%s","(1) - Inserir novo valor ");
		mvprintw(2,10,"%s","(2) - Mostrar");
		mvprintw(3,10,"%s","(3) - Remove");
		mvprintw(4,10,"%s","(4) - Altura");
	        mvprintw(5,10,"%s","(5) - Sair");
	       	mvprintw(6,10,"[ ]");
		move(6,11);

		scanw("%d",&opt);
		refresh();

		switch(opt)
		{
			mvprintw(10,10,"%d",opt);
			case 1:
				mvprintw(7,10,"%s","Informe Valor: ");
				refresh();
				getstr(info);
				insere(&root,info,1);
				break;
			case 2:
				clear();
				print(root,CENTERX,0);
				mvprintw(LINES -2,CENTERX,"%s",bal[tipoBal]);
				tipoBal = -1;
		        mvprintw(LINES -1,CENTERX,"%s",msg);
				getch();
				break;
			case 3:
				mvprintw(7,10,"%s","Informe Valor: ");
				refresh();
				getstr(info);
				removeTree(&root,info,1);
			    break;
			case 4:
				//mvprintw(LINES - 1,CENTERX,"%s","f para sair ");
			       mvprintw(7,10,"%s","Nivel");
				refresh();
                               d = maxDepth(root);

			       mvprintw(8,10,"%d",d);
                               refresh();
                               break;

			case 5:
				//mvprintw(LINES - 1,CENTERX,"%s","f para sair ");
				ch = 'f';
				break;

		}
		refresh();

		if(ch == 'f')
			break;
	}

	endwin();
}

Não se esqueça este código é GPL pode ser usado desde que mantido os direitos autorais.

Assinem os FEEDS é de graça. Só essa semana :lol:

C chat with sockets and thread

Posted on jun 28, 2008 under C, Sem categoria, Tutoriais | 2 Comentários

I developed a chat server in the C language and Python language The chat written in Python is posted here. Now I developed the chat using the C sockets and threads. The code developed in C follows the same principles of the code in Python. In C had to develop a double linked list to store the file descriptor of the socket, user name and nickname. This code was developed to the discipline of Distributed Systems.

#include

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "listaDDE.h"
#define MYPORT 5800    // the port users will be connecting to

#define BACKLOG 10     // how many pending connections queue will hold
#define MAXLINE 1024
#define NUM_THREADS     50
fd_set rmask;
pthread_mutex_t mutexsum;
pthread_mutex_t mutexLogin;
int fd_max;
int maxfds;

int sockfd;
fd_set read_fds;
fd_set master;
nodo *root = NULL;
static int	read_cnt;
static char	*read_ptr;
static char	read_buf[MAXLINE];

static void *sendMensagem(void *arg);
void sigchld_handler(int s);
static void *sendALL(char msg[],int soks);
static void *sendMensagem(void *arg);
static void *newClientConnect(int arg);

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

void *sendALL(char msg[],int soks)
{
	nodo *aux = getFirst();
	while(aux != NULL)
	{
		int soc =aux->socket;

		if(soc != soks)
			{
	      	       		if(write(soc, msg, strlen(msg)) == -1)
		    			perror("send");
				printf("send %s %s\n",msg,aux->nick);

			}
		aux = aux->prox;
	}
}

void *sendMensagem(void *arg)
{
  char *buff;
  int fd = (*(int *) arg);
  int nbytes;
  char tmp[5000];

  printf("\nthread call %d",fd);
  newClientConnect(fd);
  printf("\n entry LOOP\n");
  nodo *cliente = busca(fd);

while(1)
{

     buff = (char *) calloc( MAXLINE,sizeof(char));
     if(FD_ISSET(fd,&master))
     {
         nbytes = recv(fd,buff, MAXLINE -1 , 0);
	 if(nbytes > 1)
	 {

	   if(!tmp)
	   {
		perror("alocation:");
		exit(-1);
	   }
           strcat(tmp, cliente->nick);
	   strcat(tmp, " >> ");
	   strcat(tmp, buff);
           sendALL(tmp,fd);
	 }
	 else
	 {
	       if (nbytes == 0) {
                       printf ("servidor: socket %d desligado\n",  fd);
               } else {
                       perror ("recv");
               }
              close (fd); // BYE!!
              FD_CLR( fd , &master);
	      removi(getFirst(),fd);
	      pthread_exit(NULL);
	  }

     }
     free(buff);

}

}

static void *newClientConnect(int arg)
{
	int fd = arg;
	pthread_t tid;
	struct sockaddr_in their_addr;
	char welcome[] = "Welcome Chat SistDistribuidos 0.1 \n";
	char msg1[] = "Login: ";
	char msg2[] = "NickName: ";
	char nome[100];
	char nick[100];
	int nbytes;
	socklen_t sin_size;

	pthread_mutex_lock (&mutexLogin);

		printf("\naccept \n");
		if (write(fd, welcome, sizeof welcome - 1) != sizeof welcome - 1) {
	   		perror("write:");
			exit(1);
		}		

		printf("write %s \n",welcome);
		usleep(1000);

		if (write(fd, msg1, strlen(msg1)) != strlen(msg1)) {

	   		perror("write:");
			exit(1);
		}

		printf("write %s \n",msg1);
		usleep(1000);
		if ((nbytes = recv(fd, nome, 100,0)) < 0) {
		perror("read:");
	        exit(1);
	   	return;
		}
		nome[nbytes -1] = '\0';
		printf("Read %d %s\n",strlen(nome),nome);
		usleep(1000);
		if (write(fd, msg2, sizeof msg2 - 1) != sizeof msg2 - 1) {
	        	perror("write:");
	   	exit(1);
		}

		if ((nbytes =recv(fd, nick, 100,0)) < 0) {
	  	perror("read:");
		 exit(1);
		}
		nick[nbytes-1]='\0';
		printf("Read %d %s\n",strlen(nick),nick);		

		inseri(&root,fd,nome,nick, inet_ntoa(their_addr.sin_addr));
		FD_SET(fd, &master);		/* listen to this socket too */

	printf("end welcome \n");

	pthread_mutex_unlock (&mutexLogin);

}

int main(void)
{
      // listen on sock_fd, new connection on new_fd
    int j,new_fd;
    struct timeval waitd;
    int nbytes;
    char buf[256];
    int fd_max; //numero maximo de descritores

    struct sockaddr_in my_addr;    // my address information
    struct sockaddr_in their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;

    FD_ZERO(&master);
    FD_ZERO(&read_fds);

    pthread_mutex_init(&mutexsum, NULL);
    pthread_mutex_init(&mutexLogin,NULL);

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    if ( setsockopt ( sockfd , SOL_SOCKET , SO_REUSEADDR , &yes , sizeof ( int ) ) == -1 )
    {
		perror ( " setsockopt " );
		exit ( 1 );
    }

    my_addr.sin_family = AF_INET;         // host byte order
    my_addr.sin_port = htons(MYPORT);     // short, network byte order
    my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
    memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1) {
        perror("bind");
        exit(1);
    }

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    FD_SET(sockfd, &master);

    fd_max = sockfd;	

    int rc =0;	 

    int i = 0;
    int ret;

    int fd;
      waitd.tv_sec = 1;
      waitd.tv_usec = 0;

     while(1)
     {  

        read_fds = master;
        if (select (fd_max+1,  &read_fds, NULL, NULL, NULL)== -1) {
                perror ("select");
                exit(1);
        }

        int addrlen = sizeof (their_addr);
        if (( new_fd = accept(sockfd,(struct sockaddr *)&their_addr,&addrlen)) == -1)  {
            perror ("accept");
        } else {

            FD_SET ( new_fd , &master);

            printf ("server : new connection %s socket %d\n",
                              inet_ntoa (their_addr.sin_addr),new_fd);

	    pthread_t tred;
	    rc = pthread_create( &tred, NULL,sendMensagem, (void *) &new_fd);
       	    if (rc){
        	printf("ERROR; return code from pthread_create() is %d\n", rc);
       		exit(-1);
            }

        }
      } 

pthread_mutex_destroy(&mutexsum);
pthread_mutex_destroy(&mutexLogin);

    return 0;
}

Header Double Linked List name ListaDDE.h

#include 
#include 
#include 

#define MAXBUFFER 2048

typedef struct cel
{
	int socket;
	char nome[50];
	char nick[50];
	char host[50];
	char buff[MAXBUFFER];
	struct cel *ante;
       	struct cel *prox;
}nodo;

nodo *getFirst();
nodo *getLast();
nodo *busca(int key);

void inseri(nodo **root, int socket,char nome[],char nick[],char host[]);

void removi(nodo *root, int socket);
void print (nodo *ini);

Implementation Double Linked List without use global variable

#include 
#include 
#include "listaDDE.h"

nodo *first = NULL, *last = NULL;

nodo *getFirst()
{
	printf("call getFirst()\n");
	return first;
}

nodo *getLast()
{
	return last;
}
void inseri(nodo **root, int socket, char nome[],char nick[],char host[])
{
	nodo *aux;
	//primeira inserção
	if(*root == NULL)
	{
		*root = (nodo *) malloc(sizeof (nodo));
		if(*root == NULL)
		{
			perror("erro de alocação\n");

		}
		(*root)->socket = socket;
		strcpy((*root)->nome , nome);
		strcpy((*root)->nick , nick);
	        strcpy((*root)->host , host);
		(*root)->prox = NULL;
		(*root)->ante = NULL;
		 first = (*root);
		last = first;

	}
	else
	{
		aux = (nodo *) malloc(sizeof (nodo));
		if(aux == NULL)
		{
			perror("erro de alocação\n");

		}
		aux->socket = socket;
		strcpy(aux->nome , nome);
		strcpy(aux->nick , nick);
	        strcpy(aux->host , host);

		aux->ante =last;
            	aux->prox = NULL;

                last->prox = aux;
            	last = aux;
		*root = last;
	}
}

void removi(nodo *primeiro,int dado)
{
   nodo *aux = primeiro;
   while(aux != NULL)
   {
       if(dado == aux->socket && aux == first) //Remove first element
      {

	 if(aux->prox != NULL)
	 {
		printf("!= null\n");
		aux->prox->ante = NULL;
	        first = aux->prox;
	 }
	 else
	 {
		printf("null\n");
		free(first);

		break;
	 }

      }
      else if(dado == aux->socket && aux->prox == NULL) //remove last
      {
      	 aux->ante->prox = NULL;
         last = aux->ante;
         free(aux);
         break;
      }
      else if(dado == aux->socket &&  aux->prox != NULL && aux->ante !=NULL) //remove middle
      {
      	aux->ante->prox = aux->prox;
         aux->prox->ante = aux->ante;
         free(aux);
         break;
      }

      aux = aux->prox;
   }
}

void print (nodo *ini)
{
   nodo *p = first;
   while(p != NULL)
   {   printf ("socket %d cliente %s\n", p->socket,p->nome);
	p = p->prox;    

   }
}

nodo *busca (int key)
{
   nodo *p = getFirst();
   int flag = 0;
   while(p != NULL)
   {
   	if(p->socket == key)
	{
		return p;
	}
	p = p->prox;    

   }
   return NULL;
}

In order to compile this code together use the follow command gcc -o chatserver server.c listaDDE.c -lpthread
Using On the server
./chatserver

On the client telnet ipServer 5800

Digg if you like it: Development of a chat with the C sockets and Threads

UPDATE: This code is avaible in http://github.com/petryx/

Ponteiros para Funções

Posted on jun 23, 2008 under C, Sem categoria | 1 Comentário

Ponteiros para funções é algo extremamente interessante, eficiente e elegante. Pode ser usado para substituir switch-case, definir em tempo de execução qual função deve ser chamada ou implementar callbacks.

Ponteiros para funções são na realidade ponteiros que apontam para o endereço de uma função. Uma função possui um endereço de memória. Quando o programa é executado todo seu conteúdo é colocado na memória, então uma função é como um variável do tipo inteira, nada mais que um endereço de memória.

Então para demonstrar esse conceito, desenvolvi um código em C ANSI , que tem a função de uma calculadora de 4 operações, onde o usuário informa o primeiro valor, o operador + – * ou /, e o segundo valor, e o programa em tempo de execução escolhe a função a ser chamada.

Este pequeno exemplo de código mostra como é possível substituir o switch-case e chamar funções em tempo de execução.

#include 
#include 

float adicao(float a, float b) {return a+b;};
float subtracao(float a, float b) {return a-b;};
float multiplicacao(float a, float b) {return a*b;};
float divisao(float a, float b) {return a/b;};

int main()
{
   float(*pt2Func[4])(float, float) = {NULL};
   float(*Func)(float, float) = NULL;

   pt2Func['+'] = &adicao;
   pt2Func['-'] = &subtracao;
   pt2Func['/'] = &divisao;
   pt2Func['*'] = &multiplicacao;

   float a;
   float b;
   char operator;

    while(1)
    {
           printf("Informe a: ");
           scanf("%f",&a);

           printf("\nInforme operador: ");
           scanf(" %c",&operator);

           printf("\nInforme b: ");
           scanf(" %f",&b);

           if(operator != '-' && operator != '+' && operator != '*' && operator != '/' )
           {
                    printf("Operação não implementada");
                    exit(-1);
           }

           Func = pt2Func[operator];
           printf("\nResultado: %f\n", Func(a,b));
           printf("\nDeseja Continuar (y/n):");
           scanf(" %c",&operator);

           if(operator == 'n' || operator == 'N')
             break;
           Func = NULL;

    }
    exit(0);
}

Como funciona

A partir da linha 3 até a linha 7 definimos as funções que irão realizar a adição, multiplicação, divisão e subtração note que todas as funções possuem o mesmo protótipo.

Na linha 11 declaramos um ponteiro array que também possui o mesmo protótipo das funções. Esse é uma detalhe importante. O nosso array de ponteiros tem 4 posições onde iremos informar o valor de cada posição e o endereço da função que é feito nas linhas 14,15,16 e 17. Definimos como posição os símbolos da operações matemáticas então quando o usuário escolher uma soma informa o símbolo + e o programa por sua vez aponta para a função desejada isso acontece na linha 40.

O restante do programa é um loop onde após cada cálculo é solicitado ao usuário se deseja continuar ou não.

Este programa foi compilado com o gcc no linux.

Caso tenha dúvida sobre o funcionamento deixe um comentário.

Para saber mais: O livro C completo e Total é muito bom vale a pena ter esse livro na estante.

UPDATE: Este código está disponível no repositório git http://github.com/petryx/

Segurança Linux Dicas básicas – Permissão Arquivos – parte 1

Posted on mai 18, 2008 under C, Dicas Linux, Segurança | 6 Comentários

Tenho a intenção de fazer uma série de artigos sobre dicas básicas de segurança em Linux. Muitas coisas passam despercebidas, às vezes nos preocupamos com as regras do firewall, os serviços que estão rodando mas nos esquecemos do básico.

Você já deve ter ouvido falar sobre SUID (Set User ID) Bit), SGID (Set Group ID). Mas qual a função destes atributos especiais ?

SUID

Quando executamos um programa o sistema operacional aloca recursos baseado no usuário que está executando o processo. Quando o SUID bit, é setado por exemplo para o usuário “root” o sistema irá permitir que um usuário comum execute funções não autorizadas. Muitos buffer overflow exploits são o resultado de programas SUID.

Arquivos com SUID: -rwsr-xr-x

SGID

Este atributo define as permissões para o grupo, funciona do mesmo modo que o SUID, mas a diferença é que as permissões tem efeito em diretórios. Então todos os arquivos e programas que estão dentro do diretório, quando executados ou editados por um usuário comum o sistema irá executar ou editar como se fosse o dono do arquivo.

Exemplo de exploit escrito em C

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

int main()
{
setgid(0); setuid(0);
execl("/bin/sh","sh",0);
}

Com este código acima com SUID habilitado é possível conseguir acesso de root.


root@localhost ~ # gcc -o exploit exploit.c
root@localhost ~ # chown root exploit
root@localhost ~ # chmod u+s exploit
root@localhost ~ # exit
marlon@localhost ~ $ ./exploit
sh-3.2# id
uid=0(root) gid=0(root) grupos=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
sh-3.2#


!!! Não me responsabilizo por uso indevido deste código, a divulgação é somente para conhecimento e prevenção!!!

Com o comando abaixo todos os programas com SUID e SGID são escritos no arquivo suidfile.txt

# /usr/bin/find / -type f \( -perm -004000 -o -perm -002000 \)  -exec ls -lg {} \; 2>/dev/null >suidfiles.txt

Executando o comando acima no gentoo retorna a seguinte lista.


#  less suidfiles.txt

/bin/su
/bin/ping
/bin/mount
/bin/umount
/var/qmail/bin/qmail-queue
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/crontab
/usr/bin/chage
/usr/bin/expiry
/usr/bin/sperl5.6.1
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/procmail
/usr/bin/suidperl
/usr/lib/misc/pt_chown
/usr/sbin/unix_chkpwd
/usr/sbin/traceroute
/usr/sbin/pwdb_chkpwd

Para remover o SUID executa-se o comando chmod -s em cada arquivo.

Eu removi quase todos deixando somente o necessário: su, gpasswd, qmail-queue, unix_chkpwd, pwdb_chkpwd.

Se estiver usando X, a lista com certeza será maior pois necessita de acesso mais elevado.

Referências:

http://tldp.org/HOWTO/Security-HOWTO/file-security.html

http://www.gentoo.org/doc/pt_br/security/security-handbook.xml?part=1&chap=6

http://www.homepage.montana.edu/~unixuser/051602/SUID.html

http://www.hoobie.net/security/exploits/index.html

Comentem, Incentivem !!!!!!!!!

Transfêrencia de arquivos pela porta Serial em C

Posted on mai 17, 2008 under C | 4 Comentários

Desenvolvi um protocolo de transferência de arquivos em C linux, utilizando a porta serial. Este protocolo tem as seguintes características:

  • Cabeçalhos de Controle
  • Controle de Següência;
  • Controle de CRC 16 Bits;
  • Caso o pacote chegue no receptor com erro de CRC é solicitado o reenvio do pacote;
  • Mostra um barra de progresso sobre a transferência de arquivo.

Para compilar:

gcc -o protocol protocol-1.2.5.c

Executar transmissor:

./protocol -d /dev/ttyS0 -t

No receptor

./protocol -d /dev/ttyS0 -r

protocol-15>>>Código Fonte<<

Desenvolvido por:
Marlon Petry
Gerson Tomas Schmitt

HeapSort C

Posted on mai 17, 2008 under C | No Comment

Implementação do algortimo Heapsort, mostrando o pior caso, melhor caso e caso médio e o número de trocas.

heapdebug2

Compactando arquivos com C

Posted on mai 17, 2008 under C | No Comment

O Algortimo de Huffman tem a função de comprimir arquivos baseados em caracteres, a compressão é feita através de uma árvore binária onde são adicionados os caracteres encontrados no texto, o caracter que mais aparecer no texto recebe o menor código e o que aparecer menos vezes recebe o código maior. Os códigos atribuídos a cada caracter numca podem passar de 1 byte.

Em anexo um exemplo do algoritmo de Huffman utilizando uma árvore binária estática.

Desenvolvido em Linux, gcc. Dentro do arquivo mostra como compilar

huff_marlon