Sie sind auf Seite 1von 136

198

Programando em C para Linux, Unix e Windows

21.6 Funo sleep


Sintaxe:
unsigned int sleep(unsigned int seconds);

A funo sleep deixa o processo suspenso durante a quantidade de segundos


informada no parmetro. Este tempo que o processo permanece parado, devido ao escalonamento do kernel, pode ser um pouco maior que o informado
no parmetro.
Caso o processo receba um sinal enquanto esteja suspenso pela funo sleep,
o processo volta a rodar e realizada a execuo da funo signal handler
correspondente ao sinal ocorrido. No trmino da funo, caso a mesma no
termine o processo, a funo sleep termina, devolvendo em seu parmetro a
quantidade de segundos ainda restantes no despertador.
Veja o exemplo:
#include
#include
#include
#include

<stdio.h>
<time.h>
<stdlib.h>
<unistd.h>

int main (void)


{
time_t hora;

Para armazenar a quantidade de segundos.


Pegando o nmero de segundos a partir do
retorno da funo.

hora = time(NULL);
printf ("Numero de segundos antes
printf ("Dormindo 5 segundos\n");
sleep(5);

: %d\n", hora);

A funo sleep dorme em segundos.

time(&hora);

Pegando o nmero de segundos a partir como


parmetro (ponteiro) para a funo.

printf ("Numero de segundos depois : %d\n", hora);


exit(0);
}

Programa 21.4
Resultado do Programa 21.4
Numero de segundos antes : 1116856612
Dormindo 5 segundos
Numero de segundos depois : 1116856617

Tratamento de Sinais em Linux e Unix

199

21.7 Cuidados com algumas funes (funes


reentrantes)
O processamento de uma funo signal handler ocorre de maneira assncrona e a interrupo no fluxo de execuo pode acontecer durante a execuo
de alguma funo do prprio kernel, portanto, pode-se ter problemas de reentrncia caso a prpria funo signal handler execute a mesma funo do
kernel que foi interrompida e a mesma faa uso de alguma varivel esttica
para controle interno. Por exemplo, a funo signal handler foi executada
durante um comando strcpy e a funo signal handler executa outro comando strcpy.
Ento, deve-se sempre verificar se a situao descrita no ocorre e se as funes no reentrantes no so utilizadas dentro de funes signal handler.
Segue uma relao de funes que podem ser usadas dentro de funes signal handlers sem problemas, pois possuem a caracterstica de reentrncia necessria.
_exit(), access(), alarm(), chdir(), chmod(), chown(), close(),
creat(), dup(), dup2(), execle(), execve(), exit(), fcntl(), fork(),
fstat(), getegid(), geteuid(), getgid(), getpid(), getppid(),
getuid(), kill(), link(), lseek(), mkdir(), mkfifo(), open(),
pause(), pipe(), read(), rename(0, rmdir(0, setuid(), setgid(),
sleep(), stat(), sysconf(), time(), times(), umask(), uname(),
unlink(), utime(), wait(), waitpid(), write().



Eu viverei para sempre ou morrerei tentando.
Spider Robinson, escritor canadense

22.1 Conceito de daemon


Em vrias situaes preciso que um processo fique rodando continuamente
(eternamente) em uma mquina. A estes processos d-se o nome de daemons
(ou servios no Windows).
Os daemons apresentam as seguintes caractersticas:
Geralmente so programas que devem ser iniciados assim que o siste-

ma operacional entra no ar. Coloca-se a chamada dos mesmos nos arquivos de configurao para que eles entrem no ar automaticamente
durante o processo de boot do sistema.
Um daemon s deve ser cancelado quando o sistema operacional est
encerrando o seu processamento. O daemon fica rodando enquanto o
sistema estiver no ar.
So processos que rodam em background e no devem ter um terminal
associado a eles.

22.2 Regras para codificao de um daemon


Para se codificar um daemon deve-se realizar uma srie de tarefas e chamadas
de funes para que o processo se comporte como um daemon.

Daemons (Servios) em Linux e Unix

201

Por questo de facilidade de programao e buscando a modularidade, esses


passos so geralmente colocados em uma funo chamada daemon_init criada
dentro do programa e chamada no incio do programa na funo main.
Os passos a serem realizados so:
A primeira coisa a fazer no processo chamar a funo fork para duplicar o processo atual e terminar o processo pai. Esta duplicao causa
uma srie de efeitos colaterais desejveis em um daemon. Inicialmente,
o trmino do processo pai libera o shell, pois o mesmo acha que o comando terminou. Segundo, o processo filho herda o Process Group ID
do pai mas cria um novo Process ID, garantindo que este processo
no ser um processo lder de grupo.
Deve-se chamar a funo setsid para criar uma nova sesso. Com a
criao de uma nova sesso, o processo filho torna-se o lder da sesso,
torna-se o lder do grupo de processos e no ir possuir um terminal de
controle.
Deve-se trocar o diretrio atual para o diretrio raiz ou para um diretrio especfico. Este diretrio preferencialmente no deve ser um diretrio montado depois do processo de boot.
Deve-se mudar a mscara de criao do processo para 0 usando a funo umask. Isto possibilita o processo daemon criar arquivos com a permisso desejada. Caso no se chame esta funo, pode ser que o processo daemon herde alguma mscara que esteja desabilitando alguma
permisso necessria para o funcionamento do daemon.
Todos os descritores de arquivos que no sero utilizados pelo processo daemon devem ser fechados. Isto previne que o daemon segure algum descritor herdado aberto. O processo daemon deve selecionar
quais descritores devem ser fechados de acordo com a lgica do mesmo. Geralmente o daemon fecha todos os descritores antes de abrir
qualquer arquivo, garantindo assim que somente os arquivos necessrios ficaro abertos durante o tempo de vida do daemon.
Caso, durante a vida do processo daemon, ele precise ler algum arquivo de configurao ou mudar sua configurao interna, deve-se instalar um signal handler para o sinal SIGHUP, pois como o processo est
desconectado de qualquer terminal, ele naturalmente nunca receber
este sinal do sistema operacional.

202

Programando em C para Linux, Unix e Windows

22.3 Funo setsid


Sintaxe:
pid_t setsid(void);

Cada processo possui um Process ID que identifica unicamente o mesmo no


sistema. Adicionalmente, um processo possui um Process Group ID que indica
a qual grupo de processo ele pertence.
Um grupo de processos uma coleo de um ou mais processos com um nico
Process Group ID . Cada grupo de processo possui um processo chamado de
processo lder. O processo lder identificado como sendo o processo que possui o Process ID igual ao Process Group ID. Por exemplo, todos os processos
ligados por um pipeline iro pertencer ao mesmo grupo de processos.
Pode-se agrupar um ou mais grupos de processos em uma sesso. Tipicamente
todos os processos iniciados durante uma sesso de um shell iro pertencer
mesma sesso de processos.
O conceito de grupo de processo pode ser usado na funo signal, que permite que se mande um sinal para todos os processos pertencentes a um grupo e
na funo waitpid que permite que o processo pai receba o cdigo de retorno
de qualquer processo filho pertencendo a um grupo de processos.
A funo setsid, quando chamada de um processo, ir realizar a seguinte tarefa em relao sesso e ao grupo de processos:
criada uma nova sesso de processos. O processo que chamou a funo o nico integrante desta sesso. O processo, portanto, se torna
lder da sesso.
O processo torna-se tambm lder do grupo de processos. O Process
Group ID do grupo fica sendo o Process ID do processo.
O processo no ter um terminal de controle associado a ele. Esta caracterstica importante para o processo daemon.
Veja o exemplo:
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<errno.h>
<strings.h>

Daemons (Servios) em Linux e Unix


#include
#include
#include
#include

<sys/types.h>
<sys/stat.h>
<fcntl.h>
<unistd.h>

Headers ou includes Necessrios


para o daemon

Rotina usada para transformar o processo


em um processo daemon. O nome
daemon_init uma conveno adotada, sua
funo pode ter qualquer nome.

int daemon_init (void)


{
pid_t iPid;
long iMaxFd;
int i;
if ((iPid = fork()) < 0)
return -1;
if (iPid != 0)
exit(0);
setsid();

1 Passo Duplicar o processo


usando fork. O processo pai
encerrado.

2 Passo Chamar a funo setsid para criar uma nova


sesso de processo, ficando o processo filho como lder da
sesso e sem um terminal de controle associado ao processo.

3 Passo Troca-se o diretrio atual para o diretrio


raiz (root) ou para um diretrio prprio do daemon.

chdir ("/");

umask (0);

203

4 Passo Inicializa a mscara padro de criao de arquivos

iMaxFd = sysconf (_SC_OPEN_MAX);


for (i=0; i < iMaxFd; i++)
close (i);
return 0;

5 Passo Fechando todos os descritores


existentes no sistema. Utiliza-se a informao
de nmero mximo de descritores configurado
no sistema e obtido com a funo sysconf.
Para outras opes da funo sysconf , veja
o manual on-line do sistema.

}
void main (int argc, char *argv[])
{
int
iFd;
char
szBuffer[100];
int
i;
Chamando a funo para transformar o
processo em daemon.

if (daemon_init () < 0)
{
perror (argv[0]);
exit (errno);
}

204

Programando em C para Linux, Unix e Windows

sprintf (szBuffer, "/tmp/daemon%d.arq", getpid());


iFd = open (szBuffer, O_CREAT | O_WRONLY, 0700);
i = 1;
Para fins de testes, o programa abre um arquivo e
while (1)
de 3 em 3 segundos grava uma linha no arquivo.
{
sleep(3);
sprintf(szBuffer, "Esta eh a linha de numero %04d\n", i++);
write(iFd, szBuffer, strlen (szBuffer));
}
exit (0);
}

Programa 22.1
Resultados obtidos aps a execuo do Programa 22.1
Resultado do comando ps fu laureano :
UID
laureano
laureano
laureano
laureano
laureano

PID
42576
162230
175160
293142
246908

PPID
C STIME
162230 0 07:41:28
488506 0 15:16:51
164140 0 07:45:43
42576 11 08:04:45
1 0 07:44:06

O pai do daemon o
processo init do

TTY
pts/18
pts/18
pts/5
pts/18

TIME
0:00
0:00
0:00
0:00
0:00

CMD
bash
-ksh
vi p22_1.c
ps fu laureano
p22_1
Nenhum terminal de controle
associado ao daemon.

sistema operacional.

Arquivo gerado:
$> ls -l /tmp/daemon246908.arq
-rwx------ 1 laureano prof 527 May 17 07:44 /tmp/daemon246908.arq

Trecho do arquivo gerado:


$> cat /tmp/daemon246908.arq
Esta eh a linha de numero 0001
Esta eh a linha de numero 0002
Esta eh a linha de numero 0003
Esta eh a linha de numero 0004
Esta eh a linha de numero 0005
Esta eh a linha de numero 0006

Daemons (Servios) em Linux e Unix

205

22.4 Registrando erros com a funo syslog


Sintaxe:
int syslog(int priority, const char *msg, ...);

A funo syslog entrega uma mensagem para o programa syslogd instalado


no sistema. A mensagem ser entregue conforme a sua prioridade e a configurao do arquivo /etc/syslog.conf. Antes de utilizar esta funo, consulte a
documentao do sistema para entender o funcionamento e a configurao
do syslogd (man syslog e man syslog.conf).
Como um processo daemon no possui um terminal associado a ele (por necessidade do prprio daemon), as mensagens de erro que o daemon emitir devem
ser gravadas por outros mecanismos, sendo a funo syslog uma alternativa.
O primeiro parmetro da funo indica o tipo da mensagem (destino) e a prioridade. Devem ser usadas as seguintes constantes:

LOG_KERN
LOG_USER
LOG_MAIL
LOG_DAEMON
LOG_AUTH
LOG_SYSLOG
LOG_LPR
LOG_NEWS
LOG_UUCP
LOG_CRON
LOG_LOCAL0LOG_LOCAL7

LOG_EMERG
LOG_ALERT
LOG_CRIT
LOG_ERR
LOG_WARNING
LOG_NOTICE
LOG_INFO
LOG_DEBUG

A combinao para a utilizao destas constantes se d atravs do OU binrio


(|). Por exemplo, uma mensagem informativa para uso local poderia ser syslog( LOG_LOCAL0 | LOG_INFO, teste).

206

Programando em C para Linux, Unix e Windows

Os demais parmetros da funo possuem a mesma caracterstica dos parmetros da funo printf, ou seja, coloca-se um formato de mensagem seguido
de campos com os valores a serem utilizados neste formato.
O formato aceita a notao % seguido de uma letra da mesma maneira que
a funo printf. Adicionalmente aos formatos da printf, a funo syslog
aceita o formato %m representando diretamente a mensagem de erro acontecida no processo (Similar a perror).
Veja o exemplo:
#include <stdio.h>
#include <syslog.h>
void main(void)
{
char szmensagem[200];
sprintf(szmensagem, "O usuario %s executou o programa do syslog.", getlogin() );
Pegando o nome do usurio que executou o
programa.

syslog(LOG_LOCAL5 | LOG_INFO, szmensagem);


Mensagem informativa para a
posio local de nmero 5.

Programa 22.2
Resultado do programa 22.2
O arquivo /etc/syslog.conf foi alterado para incluir a seguinte linha:
local5.*
/var/log/teste.log
Aps alterar o arquivo /etc/syslog.conf, necessrio reiniciar o servio
do syslog; uma forma enviar um sinal para o processo do syslogd pe-

dindo a reconfigurao.
$> kill HUP <pid_syslogd>
O arquivo /var/log/teste.log, aps a execuo do programa, conter a

seguinte linha:
May 17 22:48:49 guest p22_2: O usuario root executou o programa do
syslog.
A primeira parte da mensagem no syslog

caracteriza o horrio do recebimento da


mensagem, o nome da mquina (guest) e o nome
do programa que gerou a mensagem (p22-2)...

...depois vem a mensagem


gerada pelo programa.


Quem no se comunica se trumbica.
Chacrinha, apresentador brasileiro

23.1 Funo socket


Sintaxe:
int socket(int domain, int type, int protocol);

A funo socket cria um ponto de comunicao e retorna um descritor para


um arquivo ou 1 se houve algum erro (como as funes creat e open).
Deve-se passar o domnio da comunicao (tipo da comunicao). Normalmente, para comunicaes TCP/IP utiliza-se AF_INET neste campo. O tipo da comunicao (TCP ou UDP), para comunicao TCP utiliza-se SOCK_STREAM e para
UDP SOCK_DGRAM. O campo protocolo identifica um protocolo em particular
que se deseja utilizar. Normalmente passado 0 (zero) neste campo.
Os tipos e domnios de comunicao esto descritos em sys/types.h e
sys/socket.h.
Veja o exemplo:
#include
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<errno.h>
<sys/types.h>
<sys/socket.h>

208

Programando em C para Linux, Unix e Windows

void main(void)
Criao do ponto de
{
comunicao...
int iSock;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
}

Programa 23.1

23.2 Estrutura sockaddr


Para a programao socket, foram definidas estruturas padro com os parmetros que devem ser repassados para as demais funes. Para programas
TCP/IP utiliza-se a estrutura sockaddr_in. Definida da seguinte forma:

struct sockaddr_in {
Famlia do endereo.
short int sin_family;
Nmero da porta.
unsigned short int sin_port;
struct in_addr sin_addr;
Endereo TCP/IP.
unsigned char sin_zero[8];
};

Complemento da estrutura
sockaddr.

Veja o exemplo:
#include
#include
#include
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
Porta de comunicao, normalmente
}
acima de 1024.
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);

Programao para Rede


my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
}

209

Preenche com o endereo local.


Preenchendo com 0 os bytes no
utilizados da estrutura.

Programa 23.2

23.3 Funes htonl, htons, ntohl, ntohs


Sintaxe:
uint32_t
uint16_t
uint32_t
uint16_t

htonl(uint32_t
htons(uint16_t
ntohl(uint32_t
ntohs(uint16_t

hostlong);
hostshort);
netlong);
netshort);

As funes convertem e retornam um endereo passado como parmetro para


um ordenamento de byte significativo. Sendo que as funes htons e htonl retornam o valor na ordem de bytes da rede e as funes ntohs e ntohl retornam o valor na ordem de bytes de um host.
htons Host to Network Short
htonl Host to Network Long
ntohs Network to Host Short
ntohl Network to Host Long
Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);

210

Programando em C para Linux, Unix e Windows

my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
}

Programa 23.3

23.4 Funo bind


Sintaxe:
int bind(int sockfd, const struct sockaddr *my_addr,
socklen_t addrlen );

A funo bind associa o socket criado porta local do sistema operacional.


Nesta associao verificado se a porta j no est sendo utilizada por algum
outro processo. Ser atravs desta associao (porta) que o programa ir receber dados (bytes) de outros programas. passada para a funo a estrutura
criada anteriormente, assim como o socket criado. A funo bind retorna 0
(zero) em caso de sucesso e 1 em caso de erro. Normalmente, a funo bind
utilizada no lado server da aplicao. Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if( bind(iSock, (struct sockaddr *)&my_addr, sizeof(struct
sockaddr)) == -1)
{
perror("bind:");
exit(1);

Programao para Rede

211

}
}

Programa 23.4

23.5 Funes inet_aton, inet_addr e inet_ntoa


Sintaxe:
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
char *inet_ntoa(struct in_addr in);

A funo inet_aton converte o endereo passado (inclusive com pontos) para


uma estrutura de endereos (binrio) vlido. Retorna um valor maior que 0
(zero) se a converso ocorreu ou 0 (zero) se houve algum erro.
A funo inet_addr converte o endereo passado (inclusive com pontos) para
um valor binrio (ordenado) em bytes.
A funo inet_ntoa realiza a operao inversa de inet_aton. A partir de um
valor binrio (estrutura) ela retorna o endereo em formato string (inclusive
com pontos). Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>

void main(void)
{
int iSock;
struct sockaddr_in dest_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(4950);
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(dest_addr.sin_zero), 8);
}

Programa 23.5

Converte o
endereo destino
passado para o
formato ordenado
de bytes (binrio).

212

Programando em C para Linux, Unix e Windows

23.6 Funo connect


Sintaxe:
int connect(int
socklen_t addrlen);

sockfd,

const

struct

sockaddr

*serv_addr,

A funo connect inicia uma conexo socket do lado do cliente, no sendo necessrio associar uma parte no cliente. Na estrutura passada so fornecidas as
informaes relacionadas ao servidor (destino). A funo retorna 0 (zero) se a
conexo foi bem sucedida ou 1 se houve erro. Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>

void main(void)
{
int iSock;
struct sockaddr_in dest_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(4950);
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(dest_addr.sin_zero), 8);
if( connect (iSock,(struct sockaddr *)&dest_addr, sizeof(struct
sockaddr)) < 0)
Tenta a conexo no servidor.
{
perror("connect:");
exit(1);
}
}

Programa 23.6

Programao para Rede

213

23.7 Funo listen


Sintaxe:

int listen(int s, int backlog);


Aps o socket (funo socket) ter sido criado e uma porta associada (funo
bind) necessrio habilitar o socket para receber as conexes. A funo listen faz justamente este papel, ou seja, habilita que o programa servidor receba conexes de um programa cliente. Deve-se passar o descritor do socket aberto e a quantidade de conexes que podem ficar pendentes at que o
programa trate todas as conexes anteriores. A funo retorna 0 (zero) em caso de sucesso e 1 em caso de erro. Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if( bind(iSock, (struct
sockaddr)) == -1)
{
perror("bind:");
exit(1);
}
if( listen( iSock, 10 ) < 0)
{
perror("listen:");
exit(1);

sockaddr

*)&my_addr,

sizeof(struct

Habilita o servidor para receber conexes.


O valor 10 indica que podem existir at 10
requisies conexes na fila de espera.

214

Programando em C para Linux, Unix e Windows

}
}

Programa 23.7

23.8 Funo accept


Sintaxe:
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);

Aps ter utilizado a funo listen para habilitar as conexes, necessrio aceitar as conexes. A funo accept aceita as conexes efetuadas pelos clientes. Deve ser passado para a funo o socket abertos a estrutura que ir receber os dados do cliente e o tamanho do endereo. A funo ir retornar um
descritor para a conexo aceita ou 1 se houve erro. Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if( bind(iSock, (struct
sockaddr)) == -1)
{
perror("bind:");
exit(1);
}
if( listen( iSock, 10 ) < 0)

sockaddr

*)&my_addr,

sizeof(struct

Programao para Rede

215

{
perror("listen:");
exit(1);
}

Aceita conexes eternamente.

while(1)
Estrutura que ter as informaes do
{
programa cliente.
int iFd;
struct sockaddr_in client_addr;
socklen_t sin_size;
Tamanho do endereo.
sin_size = sizeof(struct sockaddr_in);
if( (iFd = accept(iSock, (struct sockaddr *) &client_addr,
&sin_size)) < 0)
Aceitando conexes...
{
perror("accept:");
exit(1);
}
}
}

Programa 23.8

23.9 Funo send


Sintaxe:
ssize_t send(int s, const void *buf, size_t len int flags);

A funo send utilizada para enviar uma mensagem para outro socket. Para
o envio de mensagens, tambm pode ser utilizada a funo write (o mesmo
que passar o valor 0 em flags da funo send). A funo retorna o nmero de
bytes enviados ou 1 se houve erro.
A funo send utilizada em conexes TCP (stream) ou orientada conexo.
Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>

216

Programando em C para Linux, Unix e Windows

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if( bind(iSock, (struct
sockaddr)) == -1)
{
perror("bind:");
exit(1);
}

sockaddr

*)&my_addr,

sizeof(struct

if( listen( iSock, 10 ) < 0)


{
perror("listen:");
exit(1);
}
while(1)
{
int iFd;
struct sockaddr_in client_addr;
socklen_t sin_size;
char szMensagem[100];
sin_size = sizeof(struct sockaddr_in);
if( (iFd = accept(iSock, (struct sockaddr *) &client_addr,
&sin_size)) < 0)
{
perror("accept:");
exit(1);
}
printf("\nServidor recebeu conexao de %s",
inet_ntoa(client_addr.sin_addr));
memset(szMensagem, 0, sizeof(szMensagem));
strcpy(szMensagem, "Ola cliente\n");

Indentifica a origem
da conexo.

Programao para Rede

217

if( send( iFd, szMensagem, strlen(szMensagem),0) < 0)


{
Envia uma mensagem para
perror("send:");
o cliente.
exit(1);
}
}

Programa 23.9

23.10 Funo recv


Sintaxe:
ssize_t recv(int s, void *buf, size_t len);

A funo recv utilizada para receber (ler) uma mensagem de um socket. Para leitura de mensagens, tambm pode ser utilizada a funo read. A funo
retorna o nmero de bytes lidos ou 1 se houve erro.
A funo recv utilizada em conexes TCP (stream) ou orientada conexo.
Veja o exemplo:
#include
#include
#include
#include
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>

void main(void)
{
int iSock;
int iBytes;
struct sockaddr_in dest_addr;
char buffer[100];
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(4950);

218

Programando em C para Linux, Unix e Windows

dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(dest_addr.sin_zero), 8);
if( connect(iSock, (struct sockaddr *)&dest_addr, sizeof(struct
sockaddr)) < 0)
{
perror("connect:");
exit(1);
Recebe dados do servidor.
}
if ((iBytes=recv(iSock, buffer, 100, 0)) < 0 )
{
perror("recv");
exit(1);
Acrescenta o \0 para garantir um
}
trmino nulo para a string.
buffer[iBytes] = '\0';
printf("Recebido: %s",buffer);
}

Programa 23.10

23.11 Funes sendto e recvfrom


Sintaxe:
ssize_t sendto(int s, const void *buf, size_t len int flags,
const struct sockaddr *to, socklen_t tolen);
ssize_t recvfrom(int s, void *buf, size_t len int flags,
struct sockaddr *from, socklen_t *fromlen);

As funes sendto e recvfrom tm a mesma funo e retorno das funes send


e recv, exceto que so utilizadas para comunicao no orientada a conexes
(UDP).

23.12 Funes close e shutdown


Sintaxe:
int close(int fd);
int shutdown(int s, int how);

A funo close finalizada uma conexo socket. A funo shutdown finaliza toda ou parte de uma conexo full-duplex. As funes retornam 0 (zero) em caso
de sucesso ou 1 se houve algum erro. Veja o exemplo:
#include
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>

Programao para Rede

219

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void main(void)
{
int iSock;
int iBytes;
struct sockaddr_in dest_addr;
char buffer[100];
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(4950);
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(dest_addr.sin_zero), 8);
if( connect(iSock, (struct sockaddr *)&dest_addr, sizeof(struct
sockaddr)) < 0)
{
perror("connect:");
exit(1);
}
if ((iBytes=recv(iSock, buffer, 100, 0)) < 0 )
{
perror("recv");
exit(1);
}
buffer[iBytes] = '\0';
printf("Recebido: %s",buffer);
close(iSock);

Finaliza a conexo.

Programa 23.11

23.13 Funo getpeername


Sintaxe:
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);

A funo getpeername retorna o nome de um cliente que se conectou ao servidor. A funo retorna 0 (zero) em caso de sucesso ou 1 se houve algum erro.

220

Programando em C para Linux, Unix e Windows

23.14 Funo gethostbyname


Sintaxe:
struct hostent *gethostbyname(const char *name);

A funo gethostbyname retorna, a partir de um nome passado, o endereo IP associado ao nome. A funo realiza o papel de um DNS Domain Name Server. Ela retorna um ponteiro para uma estrutura ou NULL em caso de erro. Veja o exemplo:

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

<stdio.h>
<stdlib.h>
<errno.h>
<netdb.h>
<sys/types.h>
<netinet/in.h>
<arpa/inet.h>

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


{
struct hostent *h;
if (argc != 2)
{
printf("Deve-se passar nome da maquina");
exit(1);
}
if ((h=gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname:");
exit(1);
}
printf("Nome do Host: %s\n", h->h_name);
printf("Endereco IP : %s\n", inet_ntoa(*((struct in_addr *)h>h_addr)));
return 0;
}

Programa 23.12

Programao para Rede

221

23.15 Diagrama de servidor/cliente TCP bsico

222

Programando em C para Linux, Unix e Windows

23.16 Exemplo completo de um servidor TCP


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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
<unistd.h>

void main(void)
{
int iSock;
struct sockaddr_in my_addr;
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if( bind(iSock, (struct sockaddr *)&my_addr, sizeof(struct
sockaddr)) == -1)
{
perror("bind:");
exit(1);
}
if( listen( iSock, 10 ) < 0)
{
perror("listen:");
exit(1);
}
while(1)
{
int iFd;
struct sockaddr_in client_addr;
socklen_t sin_size;
char szMensagem[100];
sin_size = sizeof(struct sockaddr_in);
if( (iFd = accept(iSock, (struct sockaddr *) &client_addr,
&sin_size)) < 0)

Programao para Rede


{
perror("accept:");
exit(1);
}
printf("\nServidor recebeu conexao de %s",
inet_ntoa(client_addr.sin_addr));
memset(szMensagem, 0, sizeof(szMensagem));
strcpy(szMensagem, "Ola cliente\n");
if( send( iFd, szMensagem, strlen(szMensagem),0) < 0)
{
perror("send:");
exit(1);
}
close(iFd);
}
}

Programa 23.13

23.17 Exemplo completo de um cliente TCP


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

<stdio.h>
<stdlib.h>
<strings.h>
<errno.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
<unistd.h>

void main(void)
{
int iSock;
int iBytes;
struct sockaddr_in dest_addr;
char buffer[100];
iSock = socket(AF_INET, SOCK_STREAM, 0);
if( iSock == -1)
{
perror("socket:");
exit(1);
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(4950);
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(dest_addr.sin_zero), 8);

223

224

Programando em C para Linux, Unix e Windows

if( connect(iSock, (struct sockaddr *)&dest_addr, sizeof(struct


sockaddr)) < 0){
perror("connect:");
exit(1);
}
if ((iBytes=recv(iSock, buffer, 100, 0)) < 0 ){
perror("recv");
exit(1);
}
buffer[iBytes] = '\0';
printf("Recebido: %s",buffer);
close(iSock);
}

Programa 23.14

23.18 Diagrama de servidor/cliente UDP bsico

socket()

bind()

socket()

sendto()

recvfrom()

sendto()

recvfrom()

close()

close()

Programao para Rede

225

23.19 Exemplo completo de um servidor UDP


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

<stdio.h>
<stdlib.h>
<errno.h>
<string.h>
<sys/types.h>
<netinet/in.h>
<sys/socket.h>
<sys/wait.h>
<unistd.h>
<strings.h>
<arpa/inet.h>

int main(void)
{
int iSock;
struct sockaddr_in my_addr;
struct sockaddr_in client_addr;
socklen_t addr_len;
int numbytes;
char buffer[100];
if ((iSock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4950);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if (bind(iSock, (struct sockaddr *)&my_addr, sizeof(struct
sockaddr)) < 0 )
{
perror("bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
if ((numbytes=recvfrom(iSock, buffer, 100, 0,
(struct sockaddr *)&client_addr, &addr_len)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("Recebendo pacotes de %s\n",inet_ntoa(client_addr.sin_addr));
printf("o pacote tem %d bytes\n",numbytes);

226

Programando em C para Linux, Unix e Windows

buffer[numbytes] = '\0';
printf("O conteudo do pacote eh %s\n",buffer);
close(iSock);
}

Programa 23.15

23.20 Exemplo completo de um cliente UDP


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

<stdio.h>
<stdlib.h>
<errno.h>
<string.h>
<sys/types.h>
<netinet/in.h>
<netdb.h>
<sys/socket.h>
<sys/wait.h>
<unistd.h>
<strings.h>
<arpa/inet.h>

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


{
int iSock;
struct sockaddr_in server_addr;
struct hostent *he;
int numbytes;
if (argc != 3)
{
printf("Passe o nome do servidor e a mensagem");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname");
exit(1);
}
if ((iSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
{
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4950);
server_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(server_addr.sin_zero), 8);

Programao para Rede

227

if ((numbytes=sendto(iSock, argv[2], strlen(argv[2]), 0,


(struct sockaddr *)&server_addr, sizeof(struct sockaddr))) < 0)
{
perror("sendto");
exit(1);
}
printf("enviado %d bytes para
%s\n",numbytes,inet_ntoa(server_addr.sin_addr));
close(iSock);
}

Programa 23.16





melhor corrigir os nossos prprios erros do que os dos outros.
Demcrito, filsofo grego

tualmente, um software deve primar pela qualidade extrema, no somente no que diz respeito ao aspecto visual, funcionalidade e preciso nos resultados, mas igualmente importante a capacidade deste software ser entendido e interpretado por outras pessoas e no somente o autor.
Atravs de tcnicas simples, este trabalho visa mostrar como obter maior qualidade no desenvolvimento de software, agilidade na depurao, software auto-documentvel e de fcil execuo.
Depurar um programa ou "debugar" como mais conhecido pelos programadores tornou-se uma tarefa mais fcil em funo das milhares de ferramentas existentes, fora as que so disponibilizadas junto com as linguagens.
Entretanto, no possvel depurar um programa se este no obedece a determinadas regras de programao, que facilitam a depurao e o prprio entendimento do programa. No basta documentar os programas entupindo-os
de comentrios entre as milhares de linhas de cdigo; deve-se programar de
forma simples e objetiva, evitando-se utilizar o ltimo recurso disponvel da
linguagem principalmente se o programador no possui total domnio sobre
este novo recurso, embora, tomando-me como exemplo, sempre fiquemos tentados a utilizar esta nova funcionalidade para satisfazer nossa "curiosidade", e
se funcionar, timo, se no, fazemos do jeito tradicional mesmo.

Tcnicas de Programao para Facilitar a Depurao, Documentao...

229

Quando me refiro a programar de forma simples e objetiva, falo em no agrupar muitas operaes matemticas numa mesma linha de cdigo, a colocar
mltiplas condies numa clusula de IF ou WHILE, entre outras situaes, que
dificultam e muito o entendimento do cdigo no momento da manuteno
por outros programadores, e at mesmo pelo prprio autor, no momento de
uma depurao "emergencial".
Pretendo mostrar, atravs de exemplos "errados" de programao, analisando
estes cdigos e mostrando uma alternativa mais simples de codificao, que
julgo ser muito importante e que facilita tanto o trabalho de manuteno como depurao do cdigo.
Utilizarei nos meus exemplos a linguagem C, padro ANSI; todos os exemplos
foram compilados e executados numa mquina com sistema operacional UNIX
(HP-UX). Comearei falando das tradicionais regras para declarao de variveis nos cdigos dos programas.
A declarao correta de uma varivel a parte mais importante de um programa. Uma varivel declarada de forma errada pode causar srios transtornos, desde um resultado totalmente maluco num clculo matemtico at o
travamento total da mquina e sistema operacional (se voc estiver utilizando
uma linguagem como C ou Assembler).
Tenha como premissa somente declarar as variveis onde voc for utiliz-las,
no declare uma varivel como global se ela somente for utilizada naquela
funo bem escondida para somar 2 + 2; alm de ocupar memria desnecessariamente, pode ocasionar resultados inesperados.
A maioria das linguagens de programao modernas permite que voc crie
uma varivel em qualquer ponto do programa; utilize-a descartando-a em seguida. Observe o seguinte cdigo:

#include <stdio.h>
void main(void)
{
int a = 10;
int b = 20;
int c;
/* mostrar as variveis com os valores originais */
printf( \nValor de A = %d, a );
printf( \nValor de B = %d, b );
/* trocando os valores entre as variveis */
c = a;
a = b;
b = c;
/* mostrar as variveis com os valores trocados */

230

Programando em C para Linux, Unix e Windows

printf( \nValor de A = %d, a );


printf( \nValor de B = %d, b );
}

Programa 24.1
O exemplo anterior o clssico programa para permuta de contedos de variveis, declarando-se duas variveis com os valores que devem ser permutados
e uma varivel auxiliar para realizar a troca. O programa funciona sem problema algum, mas se fosse um programa mais complexo ou se fossem executadas vrias instrues antes da troca, a varivel que foi declarada para auxiliar
a troca de informaes ficaria alocada durante toda a execuo do programa,
ocasionando um consumo de memria. Observe o exemplo a seguir:
#include <stdio.h>
void main(void)
{
int a = 10;
int b = 20;
/* mostrar as variveis com os valores originais */
printf( \nValor de A = %d, a );
printf( \nValor de B = %d, b );
/* quero trocar o contedo entre as variveis */
{ /* abro um novo bloco de instrues */
int c; /* declaro uma varivel auxiliar aqui */
c = a;
a = b;
b = c;
} /* ao ser fechado, todas as variveis declaradas dentro deste
bloco so limpas da memria */
/* mostrar as variveis com os valores trocados */
printf( \nValor de A = %d, a );
printf( \nValor de B = %d, b );
}

Programa 24.2
Repare que, no exemplo anterior, a varivel auxiliar declarada no momento
da sua utilizao e logo aps limpa da memria. Esta uma tcnica simples e
funcional para declarao de variveis que so utilizadas somente em alguns
pontos do cdigo.
Ao declarar variveis, to importante quanto definir o escopo e abrangncia
da varivel utilizao pblica, local, esttica etc. a nomenclatura da declarao de variveis. No existe uma regra universal para declarao de variveis, mas importante existir um padro de declaraes, de forma que a simples visualizao da varivel no meio do cdigo do programa identifique o
tipo e a abrangncia desta varivel.

Tcnicas de Programao para Facilitar a Depurao, Documentao...

231

Atravs de convenes e a experincia de alguns anos como programador e


analista de sistemas, cheguei a esta tabela, derivada da notao hngara:

No meu objetivo que voc utilize esta tabela como regra imutvel de codificao, ela uma sugesto para auxiliar o programador novato e at mesmo o
experiente a adotar um padro. possvel criar uma tabela para cada linguagem
de programao, bastando identificar os tipos de dados possveis nesta linguagem. Torno a frisar que o importante voc ter um padro de declarao de variveis, qualquer que seja, e que este padro seja comum ao seu local de trabalho e que esteja disponvel a todos que iro trabalhar com o cdigo fonte.
Outro item importante a ser observado como dito anteriormente no agrupar uma frmula matemtica complexa em somente uma linha de programa. Tomemos como exemplo uma frmula hipottica qualquer:
A = ((B*C)/100)*(F*(3/D))
Caso esta frmula esteja trazendo um valor diferente do esperado, como fazer
para descobrir qual parte da frmula est errada? Voc pode depurar o programa, capturar o contedo de cada varivel verificando se foram inicializadas com os valores corretos e realizar o clculo manualmente. E se, mesmo
assim, o resultado achado manualmente for diferente do que o programa est
calculando supondo que o clculo manual esteja correto ser um erro de
arredondamento? Fica muito mais fcil a depurao deste cdigo e conseqentemente a manuteno, se ele fosse declarado da seguinte forma:
Y = (B*C)
X = Y/100
Z = (3/D)
W=F*Z
A = X * W
Repare que, matematicamente, as frmulas so idnticas.

232

Programando em C para Linux, Unix e Windows

Acredito que neste momento estou levantando uma polmica entre os programadores que defendem a codificao da frmula anterior em somente uma
linha de programa, alegando que o programa executaria mais rpido em
funo de utilizar menos linhas e consumiria menos memria em funo de
no haver a necessidade de se criarem variveis auxiliares.
Para desmentir os programadores que acreditam que o programa rode mais
rapidamente em funo de utilizar somente uma linha de cdigo, irei demonstrar como o compilador interpreta a frmula A = ((B*C)/100)*(F*(3/D)):
Passo 1 = B*C
Passo 2 = Passo 1/100
Passo 3 = 3/D
Passo 4 = F * Passo 3
Passo 5 = Passo 4 * Passo 2
Ou seja, em vez de voc codificar as instrues, quebrando e declarando as variveis auxiliares, o compilador, no momento da execuo, realiza este trabalho, alocando memria, de acordo com o necessrio e liberando em seguida.
Caso se codifique somente em uma linha, este cdigo fonte torna-se menor,
mas em compensao o cdigo pr-compilado (cdigo que ser utilizado para
a gerao do executvel) ficar maior. Caso contrrio, voc ter um cdigo
fonte e um cdigo pr-compilado similares. Repare que, em ambos os casos, o
tamanho do seu cdigo executvel ser similar.
E para aplacar a ira dos programadores que julgam estar gastando memria
desnecessariamente ao criar variveis auxiliares, peo para que olhem o exemplo a seguir, onde demonstro como criar variveis auxiliares e economizando
memria do sistema.
No caso, o programa para realizar o clculo seguindo as premissas de quebrar a frmula matemtica em vrias subfrmulas, ficaria assim:
#include <stdio.h>
void main(void)
{
float A,B,C, D, F;
B = 10.23;
C = 17.87;
D = 89.34;
F = 115.01;
{
float Y, X, Z, W;
Y = (B*C);
X = Y/ 100;
Z = (3/D);

Tcnicas de Programao para Facilitar a Depurao, Documentao...

233

W = F * Z;
A = X * W;
}
/* neste momento, as variveis auxiliares j no esto mais na
memria */
printf( A = %f, A);
}

Programa 24.3
E para provar que o tempo de processamento fica similar, foi executado o cdigo 24.4 descrito a seguir e o cdigo 24.3 e comparado o tempo de execuo entre ambos foi utilizado o comando time do UNIX para comparar as
execues.

#include <stdio.h>
void main(void)
{
float A,B,C,D, F;
B = 10.23;
C = 17.87;
D = 89.34;
F = 115.01;
A = ((B*C)/100)*(F*(3/D));
printf( "A = %f", A);
}

Programa 24.4
O resultado mostrado na tabela de comparao:

Repare que o tamanho do cdigo 24.3 com a frmula matemtica quebrada


em vrias subfrmulas possui um pequeno e insignificante acrscimo de tamanho no arquivo fonte e no arquivo executvel, mas em compensao o
tempo de execuo tempo utilizado pelo processador do computador (CPU)
para executar as instrues foram as mesmas, e principalmente, o resultado
final no se alterou. Ou seja, tivemos um pequeno prejuzo no tamanho final
da aplicao, no perdemos em tempo de processamento, tivemos um grande
ganho no tempo de entendimento, manuteno, depurao do cdigo fonte e
conseguimos o mesmo resultado matemtico.

234

Programando em C para Linux, Unix e Windows

A partir deste momento, os exemplos iro seguir o padro de declarao de


variveis que eu sugeri anteriormente.
Outro tpico importante sobre o trabalho com variveis o agrupamento destas em estruturas de dados, de forma a auxiliar a identificar qual a sua finalidade dentro do cdigo fonte. Uma estrutura de dados similar a um registro
de uma tabela qualquer independentemente do banco de dados utilizado
a nica diferena entre eles que a estrutura de dados fica armazenada na
memria do computador durante a execuo do programa. Observe o cdigo
24.5:

#include <stdio.h>
void main(void)
{
float fSalario;
char szNomeFuncionario[40];
int iNivelCargo;
char szNomeDepartamento[40];
fSalario = 7500.00; /* ainda chego l */
strcpy( szNomeFuncionario, Marcos Aurelio Pchek Laureano);
iNivelCargo = 21;
strcpy( szNomeDepartamento, INBR TSV COM );
printf(\nFuncionario = %s, szNomeFuncionario);
printf(\nSalario = %f, fSalario );
printf(\nNivel Cargo = %d, iNivelCargo );
printf(\nDepartamento = %s, szNomeDepartamento );
}

Programa 24.5
Observando o cdigo 24.5, voc consegue perceber que se trata de um programa para manipular dados de funcionrios da empresa. Imagine-se depurando um programa que manipula as informaes de funcionrios e que este
programa trabalhe com vrios tipos de informaes documentao, dados de
endereo, dados de filiao etc. e se, num dado momento, a execuo deste
programa interrompida. Ser necessrio depurar o cdigo para localizar a
causa do erro. Imagine-se verificando o contedo de cada varivel, uma a uma.
Percebeu o tempo perdido? Observe o cdigo 24.6:

#include <stdio.h>
struct ST_FUNCIONARIO
{
float fSalario;
char szNomeFuncionario[40];
int iNivelCargo;
char szNomeDepartamento[40];
};

Tcnicas de Programao para Facilitar a Depurao, Documentao...

235

void main(void)
{
struct ST_FUNCIONARIO stFuncionario;
stFuncionario.fSalario = 7500.00; /* sonhar no paga imposto */
strcpy(stFuncionario.szNomeFuncionario, Marcos Aurelio Pchek
Laureano);
stFuncionario.iNivelCargo = 21;
strcpy(stFuncionario.szNomeDepartamento, INBR TSV COM );
printf(\nFuncionario = %s, stFuncionario.szNomeFuncionario);
printf(\nSalario = %f, stFuncionario.fSalario );
printf(\nNivel Cargo = %d, stFuncionario.iNivelCargo );
printf(\nDepartamento = %s, stFuncionario.szNomeDepartamento );
}

Programa 24.6
O objetivo do cdigo 24.6 mostrar a utilizao de estruturas de dados para
agrupar as informaes. Voc verifica a vantagem na utilizao da estrutura
de dados no momento de uma manuteno e depurao do programa. No se
perde tempo identificando cada varivel e qual a sua finalidade e, principalmente, voc consegue ver todo o contedo da estrutura de uma vez s. Observe a tabela:

Como voc pode verificar, o tamanho do cdigo executvel praticamente o


mesmo, e o tempo de execuo de ambos os programas igual. Fica evidente
que, desta forma, voc mantm um cdigo fonte autodocumentvel ao ter
mais agilidade na identificao da varivel e no perde em tempo de processamento.
Para finalizar este trabalho, vou comentar o aninhamento de mltiplas condies em clusulas de IF e WHILE.
Observe o cdigo 24.7:

#include <stdio.h>
int main( int iArgc, char ** pszArgv )
{
int iA, iB, iC;
if( iArgc < 3 )
{

236

Programando em C para Linux, Unix e Windows


printf(\nEntre com 2 valores de dados );
exit(1);

}
iA
iB
iC
if

= iArgc * 10;
= atoi( pszArgv[1] ) + iA;
= atoi( pszArgv[2] ) * iB;
( iA > iB && iC > iA || iC < iB )
printf(\nOi);
else
printf(\nTchau);
return(0);
}

Programa 24.7
Afinal, o programa deveria imprimir Oi quando iA > iB e iC > iA ou iC < iB?
Ou deveria imprimir Oi quando iA > iB e iC > iA ou iC < iB? Confuso? Vou reformular a pergunta. O programa deveria imprimir Oi se somente iA > iB ou
quando iC > iA ou iC > iB, ou se iA > iB e iC > iA ou quando iC < iB. Realmente,
no fcil entender o que o programador queria fazer neste caso. Tudo o que
sabemos que o operador && (E) tem precedncia sobre o || (OU), e neste caso
a condio ficaria igual a (iA > iB && iC > iA) || iC < iB. Este exemplo demonstra
a necessidade imperiosa de identificar o que voc realmente quer fazer, e no
contar simplesmente com a ajuda do compilador. Para tal existem os delimitadores de expresses, que so os mesmos que voc utiliza para separar uma
frmula matemtica.
A = B*C+10
A = (B*C)+10
Repare que estas frmulas so idnticas matematicamente falando, mas a segunda frmula bem mais fcil de ser compreendida. No leva algum a se
perguntar se o programador queria primeiro somar 10 a C e depois multiplicar
por B ou multiplicar B por C e somar 10 ao resultado.
Pode parecer exagero comentar situaes como a anterior, mas aps dar manuteno a diversos programas, construdos nas mais variadas linguagens de
programao, vocs no imaginam a quantidade de ocasies nas quais me deparei com este tipo de situao.
Observe os cdigos 24.8 e 24.9:

#include <stdio.h>
void main( int iArgc, char ** pszArgv )
{
int iA[5];
int iContador;
int iB;

Tcnicas de Programao para Facilitar a Depurao, Documentao...

237

iB = atoi(pszArgv[1]);
iA[0]=2;
iA[1]=7;
iA[2]=3;
iA[3]=10;
iA[4]=15;
for( iContador = 0; iContador < 5 && iA[iContador]!= iB; iContador ++ );
if( iContador < 5 )
printf(\nAchei);
else
printf(\nNao achei);
}

Programa 24.8

#include <stdio.h>
void main( int iArgc, char ** pszArgv )
{
int iA[5];
int iContador;
int iB;
iB = atoi(pszArgv[1]);
iA[0]=2;
iA[1]=7;
iA[2]=3;
iA[3]=10;
iA[4]=15;
for( iContador = 0; iContador < 5; iContador ++ )
if(iA[iContador] == iB ) break;
if( iContador < 5 )
printf(\nAchei);
else
printf(\nNao achei);
}

Programa 24.9
Os dois programas fazem a mesma coisa, ou seja, procuram num vetor um elemento qualquer de forma seqencial, interrompendo to logo o elemento
seja encontrado. Qual dos programas mais fcil de se entender? A meu ver, o
cdigo 24.9 muito mais simples de entender, embora o cdigo 24.8 demonstre um determinado refinamento na sua concepo.
Nestes momentos cruciais, devemos decidir qual a forma de programao que
iremos adotar: o mtodo mais simples, tanto na concepo como na facilidade
de entendimento e mais bvio para a grande maioria dos programadores, ou
o mtodo mais refinado, mais trabalhado, que demonstra o domnio do programador sobre os recursos da linguagem utilizada, mas que tambm requer
um maior tempo para anlise e compreenso da condio. Observe a tabela:

238

Programando em C para Linux, Unix e Windows

O cdigo 24.8 mais refinado e trabalhado melhor em tudo, seja no tamanho do cdigo fonte, seja no tamanho do cdigo executvel e no tempo de
processamento, mas leva mais tempo para o entendimento do programa no
momento de uma depurao emergencial, este tempo a mais pode ser crucial
para o negcio da empresa e conseqentemente mais rpido no processamento. O cdigo 24.9 mais simples e comum ocupa mais espao para armazenamento do cdigo fonte e do cdigo executvel, leva mais tempo para ser
executado, mas mais simples de se entender.
Concluindo, pode parecer um despropsito ter realizado todos os comentrios
anteriores, afinal, todos ns aprendemos na faculdade pelo menos eu aprendi que os melhores programas so os que carregam menos variveis na
memria, que fazem as mesmas coisas em menos linhas, que ocupam menos
processamento de mquina etc. Concordo com todos estes ensinamentos, mas
acredito que na maioria dos casos deve-se avaliar cada situao pode e deve ser escrito um programa mais legvel e fcil de se manter ou depurar em detrimento de um cdigo mais refinado e bonito de se ver.


Eu posso explicar isso para eles, mas eu no posso entender isso por eles.
Dan Rather, reprter americano

A.1 Recursividade
Na linguagem C, as funes podem chamar a si mesmas. A funo recursiva
se um comando no corpo da funo a chama. Recurso a habilidade que
uma funo tem de chamar a si mesma, ou seja, a tcnica que consiste simplesmente em aplicar uma funo como parte da definio dessa mesma funo.
Para uma linguagem de computador ser recursiva, uma funo deve poder
chamar a si mesma. Um exemplo simples a funo fatorial, que calcula o
fatorial de um inteiro. O fatorial de um nmero N o produto de todos os
nmeros inteiros entre 1 e N. Por exemplo, 3 fatorial (ou 3!) 1 * 2 *3 = 6.
Veja os exemplos:

int fatorialc( int n )


{
int t, f;
f = 1;
for( t = 1; t<=n; t++ )
f = f * t
return f;
}

Verso iterativa.

Programa A.1

240

Programando em C para Linux, Unix e Windows

int fatorialr( int n)


{
int t, f;
if( n == 1) return 1;
f = fatorialr(n-1)*n;
return f;
}

Verso recursiva.
Chamada da funo.

Programa A.2
A verso no-recursiva de fatorial deve ser clara. Ela usa um lao que executado de 1 a n e multiplica progressivamente cada nmero pelo produto mvel.
A operao de fatorial recursiva um pouco mais complexa. Quando fatorialr chamada com um argumento de 1, a funo devolve 1. Caso contrrio,
ela devolve o produto de fatorialr(n-1)*n. Para avaliar essa expresso, fatorialr chamada com n-1 . Isso acontece at que n se iguale a 1 e as chamadas funo comecem a retornar.
Calculando o fatorial de 2, a primeira chamada a fatorialr provoca uma segunda chamada com o argumento 1. Essa chamada retorna 1, que , ento,
multiplicado por 2 (o valor original e n). A resposta ento 2.
Quando uma funo chama a si mesma, novos parmetros e variveis locais
so alocados na pilha e o cdigo da funo executado com essas novas variveis. Uma chamada recursiva no faz uma nova cpia da funo; apenas os argumentos so novos. Quando cada funo recursiva retorna, as variveis locais
e os parmetros so removidos da pilha e a execuo recomea do ponto da
chamada funo dentro da funo.
A maioria das funes recursivas no minimiza significativamente o tamanho
do cdigo ou melhora a utilizao da memria. Alm disso, as verses recursivas da maioria das rotinas podem ser executadas um pouco mais lentamente
que suas equivalentes iterativas devido s repetidas chamadas funo. De fato, muitas chamadas recursivas a uma funo podem provocar um estouro da
pilha. Como o armazenamento para os parmetros da funo e variveis locais
est na pilha e cada nova chamada cria uma nova cpia dessas variveis, a pilha pode provavelmente escrever sobre outra memria de dados ou de programa. Contudo, no necessrio se preocupar com isso, a menos que uma
funo recursiva seja executada de forma desenfreada.
A principal vantagem das funes recursivas ser possvel utiliz-las para criar
verses mais claras e simples de vrios algoritmos.
Ao escrever funes recursivas, deve-se ter um comando if em algum lugar
para forar a funo a retornar sem que a chamada recursiva seja executada.

Programas Avanados

241

Se no existir, a funo nunca retornar quando chamada (equivalente a um


loop infinito). Omitir o comando if um erro comum ao escrever funes recursivas.

A.2 Ordenao
A.2.1 Bolha
A ordenao mais conhecida (e mais difamada) a ordenao bolha. Sua popularidade vem do seu nome fcil e de sua simplicidade. Porm, uma das piores ordenaes j concebidas.
A ordeno bolha uma ordenao por trocas. Ela envolve repetidas comparaes e, se necessrio, a troca de dois elementos adjacentes.
Veja a verso mais simples do algoritmo bolha:

Ponteiro para uma matriz de

caracteres a ser ordenada.

void bubble( char * item, int count )


{
register int a,b;
Nmero de elementos da matriz
register char t;
a ser ordenada.
for(a=1;a<count;a++)
for(b=count-1;b>=a;b--)
{
if(item[b-1] > item[b])
{
t = item[b-1];
Processo de troca
item[b-1] = item[b];
(ordenao).
item[b] = t;
}
}
}

Programa A.3
A ordenao bolha dirigida por dois loops. Dados que existem count elementos na matriz, o loop mais externo faz a matriz ser varrida count-1 vezes.
Isso garante, na pior hiptese, que todo elemento estar na posio correta
quando a funo terminar. O loop mais interno faz as comparaes e as trocas.
Essa verso da ordenao bolha pode ser utilizada para ordenar uma matriz de
caracteres em ordem ascendente. Por exemplo, o programa seguinte ordena
uma string.

242

Programando em C para Linux, Unix e Windows

#include <stdio.h>
#include <string.h>
void bubble( char * item, int count );
void main(void)
{
char vetorb[]="3490bn09685lnv 3-49580bgojfog39458=9ugkj n098=526yh";
printf("\nAntes = [%s]", vetorb);
bubble(vetorb,strlen(vetorb)-1);
printf("\nDepois = [%s]", vetorb);
}

Programa A.4
Resultado do Programa A.4
Antes = [3490bn09685lnv 3-49580bgojfog39458=9ugkj n098=526yh]
Depois = [ -000023334445555668888999999==bbfggghjjklnnnoouvy]

A.2.2 Quicksort
A Quicksort, inventada e denomina por C.A.R. Hoare, considerada o melhor
algoritmo de ordenao de propsito geral atualmente disponvel. baseada
no mtodo de ordenao por trocas (mas muito superior em termos de desempenho ordeno bolha).
A Quicksort baseada na idia de parties. O procedimento geral selecionar um valor, chamado de comparando, e, ento, fazer a partio da matriz em
duas sees, com todos os elementos maiores ou iguais ao valor da partio de
um lado e os menores do outro. Este processo repetido para cada seo restante at que a matriz esteja ordenada. Por exemplo, dada a matriz fedacb e
usando o valor d para a partio, o primeiro passo da Quicksort rearranja a
matriz como segue:

Incio
Passo 1

f e d a c b
b c a d e f

Esse processo , ento, repetido para cada seo isso , bca e def. Assim, o
processo essencialmente recursivo por natureza e, certamente, as implementaes mais claras da Quicksort so algoritmos recursivos.
O comparando central pode ser selecionado de duas formas. Escolh-lo aleatoriamente ou selecion-lo fazendo a mdia de um pequeno conjunto de valores da matriz. Para uma ordenao tima, deveria ser selecionado um valor

Programas Avanados

243

que estivesse precisamente no centro da faixa de valores. Porm, isso no fcil para a maioria dos conjuntos de dados. No pior caso, o valor escolhido est
em uma extremidade e, mesmo nesse caso, o algoritmo Quicksort ainda tem
um bom rendimento. A verso seguinte seleciona o elemento central da matriz. Embora isso nem sempre resulte numa boa escolha, a ordenao ainda
efetuada corretamente.

void qs( char *item, int left, int right)


{
register int i,j;
char x,y;
i = left;
j = right;
x = item [ (left+right)/2 ];
do
{
while(item[i]<x && i<right) i++;
while(x<item[j] && j>left) j--;
if(i<=j)
{
y = item[i];
item[i] = item[j];
Processo de troca
item[j] = y;
(ordenao).
i++;
j--;
}
} while (i<=j);
if( left<j) qs(item, left, j);
Chamada recursiva...
if( i<right) qs(item, i, right);
}

Programa A.5
O prximo programa realiza a chamada da funo para ordenao.

#include <stdio.h>
#include <string.h>
void qs( char *item, int left, int right);
void main(void)
{
char vetorq[]="3490bn09685lnv 3-49580bgojfog39458=9ugkj n098=526yh";
printf("\nAntes = [%s]", vetorq);
qs(vetorq,0,strlen(vetorq)-1);
printf("\nDepois = [%s]", vetorq);
}

Programa A.6

Na primeira chamada, os parmetros


iniciais so os extremos da matriz.

244

Programando em C para Linux, Unix e Windows

Resultado do Programa A.6


Antes = [3490bn09685lnv 3-49580bgojfog39458=9ugkj n098=526yh]
Depois = [ -000023334445555668888999999==bbfggghjjklnnnoouvy]

A.3 Pesquisa
Bancos de dados existem para que, de tempos em tempos, um usurio possa
localizar o dado de um registro simplesmente digitando sua chave. H apenas
um mtodo para se encontrarem informaes em um arquivo (matriz) desordenado e um outro para um arquivo (matriz) ordenado.
Encontrar informaes em uma matriz desordenada requer uma pesquisa seqencial comeando no primeiro elemento e parando quando o elemento
procurado ou o final da matriz encontrado. Esse mtodo deve ser usado em
dados desordenados, mas tambm pode ser aplicado a dados ordenados. Se os
dados foram ordenados, pode ser utilizada uma pesquisa binria, o que ajuda
a localizar o dado mais rapidamente.

A.3.1 Pesquisa Seqencial


A pesquisa seqencial fcil de ser codificada. A funo a seguir faz uma pesquisa em uma matriz de caracteres de comprimento conhecido at que seja
encontrado, a partir de uma chave especfica, o elemento procurado:

int sequential_search( char * item, int count, char key )


{
Procura do 1 elemento da matriz at
register int t;
o ltimo....
for( t = 0; t<count; t++)
if( key == item[t] )
return t;
...at encontrar o elemento.
return -1;
No encontrou...
}

Programa A.7
Essa funo devolve o ndice da entrada encontrada se existir alguma; caso
contrrio, ela devolve 1.

A.3.2 Pesquisa Binria


Se o dado a ser encontrado se encontrar de forma ordenada, pode ser utilizado um mtodo muito superior para encontrar o elemento procurado. Esse mtodo a pesquisa binria que utiliza a abordagem dividir e conquistar. Ele
primeiro verifica o elemento central. Se esse elemento maior que a chave,
ele testa o elemento central da primeira metade; caso contrrio, ele testa o

Programas Avanados

245

elemento central da segunda metade. Esse procedimento repetido at que o


elemento seja encontrado ou que no haja mais elementos a testar.
Por exemplo, para encontrar o nmero 4 na matriz 1 2 3 4 5 6 7 8 9, uma
pesquisa binria primeiro testa o elemento mdio, nesse caso 5. Visto que
maior que 4, a pesquisa continua com a primeira metade ou 1 2 3 4 5. O elemento central agora 3, que menor que 4, ento, a primeira metade
descartada. A pesquisa continua com 4 5. Nesse momento o elemento encontrado.
A seguir, demonstrada uma pesquisa binria para matrizes de caracteres.
int binary( char * item, int count, char key)
{
int low, high, mid;
low = 0;
high = count 1;
while( low <= high )
Dividir para conquistar.
{
mid = (low+high)/2;
if( key<item[mid])
high = mid 1;
else if( key>item[mid])
Vai procurando nas metades at encontrar
o elemento.
low = mid + 1;
else
return mid;
}
return -1;
}

Programa A.8
Este programa pode ser adaptado para realizar pesquisas em qualquer tipo de
matriz (inteiros ou estruturas, por exemplo). Exemplo de utilizao das funes.

#include <stdio.h>
#include <string.h>
int binary( char * item, int count, char key);
int sequential_search( char * item, int count, char key );
void qs( char *item, int left, int right);
void main(void)
{
int pos;
char vetors[]=".,/~2r=-dfx-950]gojftg394a8@ugkj n#26yh";
char vetorb[]=".,/~2r=-dfx-950]gojftg394a8@ugkj n#26yh";

246

Programando em C para Linux, Unix e Windows

printf("\nMatriz desordenada [%s]", vetors );


printf("\nProcurando = sequencialmente");
pos = sequential_search(vetors, strlen(vetors),'=');
printf("\n= encontrado na posicao %d", pos );
A pesquisa binria exige que
printf("\nOrganizando a matriz.");
a matriz esteja ordenada.
qs(vetorb, 0,strlen(vetorb)-1);
printf("\nMatriz ordenada [%s]", vetorb);

printf("\nProcurando = binariamente");
pos = binary(vetorb, strlen(vetorb),'=');
printf("\n= encontrado na posicao %d\n", pos );
}

Programa A.9
Resultado do Programa A.9
Matriz desordenada [.,/~2r=-dfx-950]gojftg394a8@ugkj n#26yh]
Procurando = sequencialmente
= encontrado na posicao 6
Organizando a matriz.
Matriz ordenada [ #,--./0223456899=@]adffggghjjknortuxy~]
Procurando = binariamente
= encontrado na posicao 17

No desanimes. Freqentemente a ltima chave


do molho que abre a fechadura.
(Annimo)

B.1 Obtendo ajuda no Linux e Unix


O comando man a maneira mais rpida de obter informaes sobre um determinado comando. Para visualizar o help on-line de todas as funes da linguagem C no ambiente Linux e Unix, basta utilizar este comando para realizar
a consulta.
Exemplos:
Para ver as opes de compilao do gcc: man gcc
Para ver como funciona a funo fopen do C: man fopen
Para ver como funciona o comando man: man man

B.2 Sees do Manual


Toda a documentao do sistema Linux e Unix est dividida em sees. Cada
seo responsvel pela documentao de assuntos correlatos. Segue uma
breve descrio das sees mais importantes:
Seo 1 Contm os comandos destinados para o usurio comum. So
a maioria dos comandos existentes no Linux e Unix.

248

Programando em C para Linux, Unix e Windows


Seo 2 O sistema Linux e Unix oferece um conjunto de funes que

podem ser chamadas dentro de programas C. Esta seo descreve cada


uma destas funes disponibilizadas para o programador C.
Seo 3 a parte do manual que contm a documentao da biblioteca de funes disponibilizadas pelo compilador C padro da mquina.
claro que existem outras sees. Atualmente, devido grande quantidade de
softwares e pacotes disponveis, existem vrias sees.

B.3 Diviso da Documentao


Cada documentao de um comando dividida em partes. De todas elas podemos destacar como as mais importantes:
NAME (NOME) Contm o nome do comando e uma breve descrio
da funo do mesmo.
SYNOPSIS (SINOPSE) Contm todas as sintaxes aceitas pelo comando,
bem como as opes aceitas e os argumentos esperados.
DESCRIPTION (DESCRIO) Contm a descrio da funo do comando, de forma detalhada. Inclui tambm a descrio de cada opo e
argumento esperado pelo comando.
RETURN VALUE (VALOR DE RETORNO) Indica o cdigo de retorno (ou
retornos) de um comando.
ERRORS (ERROS) Esta parte relata as possveis mensagens de erro que
o comando pode emitir durante a sua execuo. Pode sugerir correes
ou verificaes a serem feitas para sanar o problema.
SEE ALSO (VEJA TAMBM) Na grande maioria dos casos, um comando est ligado execuo de diversos outros comandos. Nesta parte do
manual so colocados todos os comandos citados no texto anterior ou
que tm alguma relao com o comando.

B.4 Exemplo de Utilizao


As funes da linguagem C esto todas documentadas no sistema, bastando
utilizar o comando man para ver o funcionamento das funes. Mas antes
preciso fazer algumas consideraes. Utilizando a funo open como exemplo:

$> man open

Obtm-se o seguinte trecho (aqui, modificado e comentado) na documentao


no sistema Linux:

Ajuda

OPEN(2)

249

Seo do manual. No caso, a funo open considerada


uma chamada de sistema (system call).

System calls

NAME
open, creat open and possibly create a file or device
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

Os arquivos necessrios (includes) para


a funo funcionar.

int open(const char *pathname, int flags);


int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
Prottipo da funo. Quais os parmetros que a
funo recebe e o valor que ela retorna.

DESCRIPTION
The open() system call is used to convert a pathname into a file
descriptor (a small, non-negative integer for use in subsequent I/O
as with read, write, etc.). When the call is successful, the file
descriptor returned will be the lowest file descriptor not currently
open for the process. This call creates a new open file, not shared
with any other process. (But shared open files may arise via the
fork(2) system call.) The new file descriptor is set to remain open
across exec functions (see fcntl(2)). The file offset is set to the
beginning of the file.
Descrio detalhada a respeito do
funcionamento da funo.
Descrio detalhada sobre o retorno da funo.

RETURN VALUE
open and creat return the new file descriptor, or -1 if an
error occurred (in which case, errno is set appropri
ately).
Note that open can open device special files, but creat cannot create them use mknod(2) instead.
On NFS file systems with UID mapping enabled, open may
return a file descriptor but e.g. read(2) requests are denied with
EACCES.
This is because the client performs open by checking the
permissions, but UID mapping is performed by the server upon read
and write requests.

250

Programando em C para Linux, Unix e Windows

If the file is newly created, its atime, ctime, mtime fields


are set to the current time, and so are the ctime and
mtime
fields of the parent directory. Otherwise, if the file is modified
because of the O_TRUNC flag, its ctime
and mtime fields are
set to the current time.
Descrio detalhada sobre os erros ocorridos e dicas de como
resolver o problema.

ERRORS
EEXIST pathname already exists and O_CREAT and O_EXCL were used.
EISDIR pathname refers to a directory and the access requested involved writing (that is, O_WRONLY or O_RDWR is set).
Outras funes relacionadas com esta. No caso, como foi consultada a
funo open (que trata de abertura de arquivos), o comando man
apresenta outras funes que tambm manipulam arquivos (o nmero
entre parnteses indica o nmero da seo do manual).

SEE ALSO
read(2),
write(2),
fcntl(2),
mknod(2),
mount(2),
stat(2), umask(2),
fopen(3), fifo(4)

close(2),
unlink(2),

link(2),
socket(2),


No importante que voc entenda o que eu estou
fazendo ou por que voc est me pagando tanto dinheiro.
O importante que voc continue a fazer assim.
(Annimo)

ompilar transformar um arquivo legvel para o homem (chamado de cdigo-fonte, source file em ingls) para um arquivo legvel para a mquina
(binrio, binary). Quem faz esse trabalho o compilador.
O compilador C/C++ padro no Linux o gcc. Muitas distribuies vm com o
gcc includo. O gcc um dos compiladores mais versteis e avanados existentes. O gcc suporta todos os padres modernos do C atualmente usados, como
o padro ANSI C, assim como muitas extenses especficas do prprio gcc. Utilizar o gcc simples. Vejamos alguns exemplos:
Compila o programa hello.c e cria o binrio hello (opo o do gcc )
$> gcc hello.c o hello
Compila dois programas (prog1.c e prog2.c ) e cria o binrio programa.
$> gcc prog1.c prog2.c oprograma
Compila o programa fat.c, gera o binrio fat e indica para o compilador
linkeditar a biblioteca matemtica junto com binrio (opo l do gcc).
$> gcc fat.c o fat lm
Compila o programa def.c, gera o binrio def e cria a diretiva PLATAFORMA (opo D do gcc) com o valor Linux (veja o funcionamento no

captulo de Pr-compilao).
$> gcc def.c DPLATAFORMA=Linux odef

252

Programando em C para Linux, Unix e Windows


Compila o programa inc.c, gera o binrio inc . A opo I indica o

caminho para os includes (headers) do especficos do projeto e a opo


L indica o caminho das bibliotecas especficas do projeto.
$> gcc inc.c I../includes L../libs lmylib o../bin/inc
Compila o progr1.c e gera o binrio progr1. A opo O para otimi-

zao do cdigo gerado.


$> gcc O oprogr1 progr1.c

O libc (glibc) uma biblioteca usada por quase todos os programas do Linux;
o libjpeg uma biblioteca usada em todos os programas que trabalham com
o formato JPEG; e assim por diante. No sistema Linux essas bibliotecas so divididas em dois pacotes: um para ser usado por programas j compilados
(glibc e libjpeg, por exemplo), e um para ser usado na compilao de programas que dependem dele (glibc-devel e libjpeg-devel, por exemplo).
Portanto, para compilar programas mais complexos, ser necessrio ter esses
dois pacotes instalados.
Se o programa constitudo por vrios arquivos, e normalmente usam bibliotecas e header-files externos, ser necessrio compilar todos eles e junt-los
(link) corretamente. Para automatizar esse procedimento, usa-se o comando
make. Este comando l um arquivo chamado Makefile, onde estar o "roteiro"
necessrio para a compilao do programa. O objetivo bsico do make permitir que seja construdo um programa em pequenas etapas. Se muitos arquivos
fontes compuserem o executvel final, ser possvel alterar um arquivo e reconstruir o executvel sem ter a necessidade de compilar os demais programas.
Para tal, necessrio criar um arquivo chamado Makefile.
O make pode ser composto de vrias linhas, cada um indicando como o
executvel deve ser construdo. Normalmente, existem dependncias entre
as linhas, indicando a ordem de execuo das linhas. A disposio das linhas
(entradas) dentro do arquivo Makefile no importa, pois o make ir descobrir qual a ordem correta. O make exige alguns cuidados para a criao do
arquivo:
Sempre colocar uma tabulao no comeo de um comando, nunca espaos. No deve ser utilizada uma tabulao antes de qualquer outra
linha.
O smbolo # (sustenido, tralha, cerquilha ou jogo da velha) indica um
comentrio na linha.
Uma barra invertida no final de uma linha indica que ela ir prosseguir
na prxima linha. timo para comandos longos.

Compilando no Linux

Vejamos um exemplo:

253

Para executar os comandos do sistema


operacional, necessrio verificar a
precedncia all ...

install: all
mv manipconfig /usr/local
mv delbinario /usr/local
all: manipconfig delbinario

...que indica que estes arquivos binrios


devem existir.

Para o binrio manipconfig ser criado....

... necessrio que os arquivos


objetos existam.

manipconfig: cria.o altera.o exclui.o consulta.o editor.o \


manipula.o principal.o
gcc L/home/laureano/libs o cria.o altera.o exclui.o \
consulta.o editor.o manipula.o principal.o
delbinario: del.c main.c
gcc o del.o main.o

Indica que o comando continua


na prxima linha.

cria.o: cria.c
gcc c cria.c
altera.o: altera.o
gcc c altera.c

Para o objeto ser gerado, necessrio compilar o


programa antes. A opo c do gcc indica que
somente para compilar (gerar o arquivo .o ).

exclui.o: exclui.c
gcc c exclui.c

consulta.o: cosulta.c
gcc c consulta.c
editor.o: editor.c
gcc c editor.c
manipula.o: manipula.c
gcc c manipula.c
principal.o: principal.c
gcc c principal
del.o: del.c
gcc c del.c
main.o: main.c
gcc c main.c

Aqui sempre deve vir precedido de uma tabulao (TAB).

254

Programando em C para Linux, Unix e Windows

Os comandos do arquivo Makefile anterior seriam equivalentes aos seguintes


comandos (se todos fossem digitados):

$> gcc c main.c


$> gcc c del.c
$> gcc c principal
$> gcc c manipula.c
$> gcc c editor.c
$> gcc c consulta.c
$> gcc c exclui.c
$> gcc c altera.c
$> gcc c cria.c
$> gcc del.o main.o o delbinario
$> gcc L/home/laureano/libs cria.o altera.o exclui.o consulta.o
editor.o manipula.o principal.o o manipconfig
$> mv manipconfig /usr/local
$> mv delbinario /usr/local

Para maiores informaes sobre a utilizao e opes dos comandos gcc e


make, veja o manual on-line (help) do sistema Linux.


Quem pode faz. Quem no pode ensina. Quem no sabe ensinar vira chefe.
(Annimo)

LCC-Win32 um compilador C para Windows desenvolvido por Jacob Navia, que por sua vez foi baseado no compilador C desenvolvido por Dave
Hanson e Chris Fraser.

D.1 Instalao
Ele pode ser baixado gratuitamente em http://www.cs.virginia.edu/~lcc-win32/.
Sua instalao simples e rpida, bastando dar um duplo clique no executvel
lccwin32.exe. Os prximos passos iro auxili-lo a realizar a instalao.
1 Passo Clicar (duplo clique) no executvel do LCC-Win32 ( lccwin32.exe).

256

Programando em C para Linux, Unix e Windows

2 Passo Confirmar a instalao. Basta clicar com o mouse no boto Sim ou


Yes (depende da lngua utilizada no sistema operacional).

3 Passo A instalao do LCC-Win32 do tipo NNF (next, next and finish).


Basta clicar com o mouse no boto Next.

Utilizando o LCC-Win32

257

4 Passo Licena de uso. A licena diz que o software pode ser utilizado para
fins pessoais ou didticos. Clique em Yes (Sim) para aceitar os termos de uso e
continuar com a instalao.

5 Passo O instalador avisa os procedimentos que sero realizados a seguir.


Clique em Next.

258

Programando em C para Linux, Unix e Windows

6 Passo O diretrio padro para instalao c:\lcc. Se quiser escolher outro


diretrio ou disco rgido (D:, por exemplo) para instalao, basta selecionar no
browser apresentado. O programa de instalao indica qual o espao necessrio
para a instalao. Aps a escolher o local da instalao, clique em Next.

7 Passo Selecionar em qual grupo do Windows o programa ser includo. A


sugesto do programa criar um grupo novo ( lcc-win32). Ser este grupo
que ir aparecer no menu do Windows.

Utilizando o LCC-Win32

259

8 Passo Aps a configurao da instalao (conforme passos anteriores), a


instalao ir realmente ocorrer aps voc clicar em Install.

9 Passo Processo de instalao. Dependendo do seu computador, esta operao pode demorar at 5 minutos... basta aguardar o trmino...

260

Programando em C para Linux, Unix e Windows

10 Passo Continuando o processo de instalao. O programa est criando as


bibliotecas do sistema.... basta aguardar o trmino da operao.

11 Passo Notificao do trmino da gerao das bibliotecas. Clicar em OK.

Utilizando o LCC-Win32

261

12 Passo Programa instalado! Basta clicar em Finish para finalizar o programa.

Agora voc j pode utilizar o programa para criar, compilar e executar os seus
programas.

D.2 Criando Projetos no LCC-Win32


O que vem a ser um projeto em C? Voc provavelmente j deve saber que um
compilador um programa que transforma um arquivo contendo um programa (arquivo fonte) escrito em uma linguagem de alto nvel, como o C, para
uma linguagem que a mquina capaz de "entender", ou programa executvel.
A linguagem C permite que um programa seja decomposto em diversos mdulos, onde cada mdulo pode ficar armazenado em arquivos diferentes. Isso
permite que, principalmente em projetos grandes, um programa possa ser desenvolvido por uma equipe de programadores, cada um trabalhando em um
mdulo diferente do programa. O compilador deve aceitar, portanto, diversos
arquivos de entrada para gerar um arquivo executvel. comum combinar
mdulos segundo alguma funcionalidade, criando-se bibliotecas de funes,
para que possam ser reutilizados em outros programas. Uma biblioteca do C
que vai ser freqentemente utilizada a stdio.h, que contm vrias funes
para a entrada e sada de dados.

262

Programando em C para Linux, Unix e Windows

Com a utilizao de diversos arquivos (vrias centenas ou mais para projetos


muito grandes) que podem conter dependncias mtuas (partes de um mdulo
que chamam partes de outro mdulo e vice-versa), o compilador deve ser instrudo sobre quais arquivos fontes ele deve compilar, em que ordem, qual o nome
dos executveis a serem gerados etc. Essa informao tipicamente armazenada
em outro arquivo, chamado Makefile. Makefiles possuem uma sintaxe bem restrita e podem se tornar bastante complicados. Para simplificar esse processo, o
ambiente do LCC-Win32 (o WEdit) oferece uma forma mais intuitiva de manter
a informao necessria para compilar um programa, que so os projetos.
Toda vez que voc for escrever um novo programa no LCC-Win32 , voc dever
criar um novo projeto. Nesse projeto voc poder incluir arquivos, modificar
propriedades da aplicao e at controlar a verso do seu programa, que o ajuda a manter uma documentao sobre as mudanas ocorridas ao longo do desenvolvimento do projeto. Veja o manual do LCC-Win32 para maiores detalhes.
Agora que voc sabe o que significa um projeto, voc dever entender melhor
o procedimento exigido para a criao de um programa no LCC-Win32.

D.2.1 Criando um projeto


1 Passo No item Project do menu do LCC-Win32 selecione a opo Create...

Utilizando o LCC-Win32

263

2 Passo Especifique o nome do projeto e o local onde ele vai ficar armazenado. Depois clique em Create. Para fins de aprendizado, vamos trabalhar
somente com aplicaes de console (Console Aplication), ou seja, que iro
em uma tela parecida com a do sistema DOS.

3 Passo O LCC-Win32 pode criar um esqueleto bsico para voc de vrias aplicaes, bastando s complementar as rotinas e funes. No nosso caso, clique em No.

264

Programando em C para Linux, Unix e Windows

4 Passo Agora temos que selecionar um arquivo que conter o nosso programa-fonte. Se voc no tiver criado este arquivo ainda, clique em Cancelar. Este tutorial assume que voc ainda no tem um programa pronto.

5 Passo O LCC-Win32 ir demonstrar uma tela de administrao de arquivos


do seu projeto. Nesta tela voc poder incluir ou excluir arquivos do projeto.
Como ainda no temos um arquivo, clique em Cancel.

Utilizando o LCC-Win32

265

6 Passo O LCC-Win32 pergunta se voc tem certeza que quer gerar um projeto vazio (sem arquivos fontes). Confirme a operao clicando em Sim.

7 Passo Agora vamos configurar alguns itens da compilao do programa.


Esta a tela onde voc ir definir os #defines da aplicao em tempo de execuo. Clique em Avanar.

266

Programando em C para Linux, Unix e Windows

8 Passo Nesta tela voc configura onde ser gerado o seu programa executvel e
eventuais arquivos que devem ser linkados ao seu programa. Clique em Avanar.

9 Passo Aqui voc configura a fonte das aplicaes e os parmetros que sero passados ao seu programas (recebidos na funo main, normalmente como
argv e argc). Clique em Concluir.

Parabns. O seu projeto est concludo. Agora temos que criar um programa
para incluir no projeto, compilar e executar.

Utilizando o LCC-Win32

267

D.3 Criando um Programa e Compilando


1 Passo Na opo File do menu, selecione New e depois File para criar
um novo programa-fonte em C.

2 Passo Informe o nome do programa. No nosso caso ser o hello.c.


IMPORTANTE: Lembre-se sempre de colocar a extenso .c nos arquivos-fontes.

268

Programando em C para Linux, Unix e Windows

3 Passo Salve o seu programa. Voc pode pressionar CTRL+S ou ir at a opo File do menu e depois em Save.

4 Passo Agora temos que incluir o novo programa no projeto criado anteriormente. V at a opo Project do menu e selecione Add/Delete files...

Utilizando o LCC-Win32

269

5 Passo Selecione o arquivo correspondente ao seu programa e clique em


Abrir.

6 Passo O LCC-Win32 ir demonstrar uma tela de administrao de arquivos


do seu projeto. Nesta tela voc poder incluir ou excluir arquivos do projeto.
Clique em OK para confirmar o novo arquivo no projeto.

270

Programando em C para Linux, Unix e Windows

7 Passo Agora s compilar o programa e, se estiver tudo certo, execut-lo.


Para compilar, voc pode pressionar F9 ou ir at a opo Compiler do menu
e selecione Make. Para executar o programa pressione CTRL+F5 ou v at a
opo Compiler do menu e selecione Execute. Se o seu programa contiver
algum erro de sintaxe, ir aparecer em uma janela abaixo a linha e o erro causado.

8 Passo O seu programa est executando. Parabns...



Autodidata: ignorante por conta prpria.
Mrio Quintana, poeta brasileiro

linguagem de programao C possui um enorme conjunto de funes.


Muitas das funes disponveis so especficas de um fabricante ou de um
sistema operacional. Este guia apresenta a referncia das funes mais utilizadas nos sistemas Linux e Unix (montada a partir do manual do sistema). Ela
traz o prottipo da funo (sua assinatura) com seus parmetros, os arquivos
cabealhos necessrios para o funcionamento e o retorno da funo. A finalidade desta seo listar as funes existentes (e seu significado) para facilitar
a busca do programador. Para obter maiores informaes referentes s funes (forma de uso, exemplos etc.) necessrio consultar o manual do sistema
(man).
Para a montagem deste apndice foram consultados os manuais do sistema
Unix AIX (IBM) e Linux (Fedora). Algumas chamadas podem ser diferentes de
sistema para sistema. Nas pesquisas realizadas foi detectado que algumas
chamadas tm a mesma funo mas a forma diferente (alguns casos foram listados duplicados). Recomenda-se sempre consultar o manual on-line do seu
sistema (sistemas Linux so independentes da distribuio, assim como sistemas Unix tambm o so).
Sempre que uma funo resultar em erro, verifique a varivel errno.

272

Programando em C para Linux, Unix e Windows

Notaes utilizadas nesta seo:


> Maior que
< Menor que
Igual
!= Diferente de
# Quantidade
_exit


void _exit(int status);

#include <unistd.h>


abort


void abort(void);

#include <stdlib.h>
SIGABRT

abs


int abs(int num);

#include <stdlib.h>


int accept(int s, struct sockaddr *addr, socklen_t
*addrlen);

#include <sys/types.h>

#include
<sys/socket.h>

accept


int access(const char *pathname, int mode);

#include <unistd.h>

access

acos


double acos(double num);
#include <math.h>

num11

Guia de Referncia das Funes


alarm

273


unsigned int alarm(unsigned int seconds);
nsegundos #include <unistd.h>

alloca


char *alloca(int size);
#include <stdlib.h>
NULL

free

asctime

char *asctime(const struct tm *tm);

#include <time.h>


struct tm
asin


double asin(double num);

#include <math.h>

num11

assert


void assert (int expression);

#include <assert.h>

atan


double atan(double num);

#include <math.h>

atexit


int atexit(void (*function)(void));

#include <stdlib.h>

274

Programando em C para Linux, Unix e Windows

atof


double atof(const char *str);

#include <stdlib.h>
double

atoi


int atoi(const char *str);

#include <stdlib.h>
int

atol


long atol(const char *str);

#include <stdlib.h>
long

atoll


long long atoll(const char *nptr);

#include <stdlib.h>
long long


basename
char *basename(char *path);

#include <libgen.h>

bind


int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);

#include <sys/types.h>
#include

<sys/socket.h>


bsearch
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size, int (*compar)(const void
*, const void *));

#include <stdlib.h>
NULL
keynmemb
base
size

Guia de Referncia das Funes

275

calloc


void *calloc(size_t nmemb, size_t size);
#include <stdlib.h>
NULL

cbrt


double cbrt( double x );

#include <math.h>

ceil


double ceil(double num);


num

ceil(1.03)2.0

chdir


int chdir(const char *path);

#include <unistd.h>


chmod
int chmod(const char *path, mode_t mode);

#include <sys/types.h>
#include <sys/stat.h>


chown

int chown(const char *path, uid_t owner, gid_t group);

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


int chroot(const char *path);

#include <unistd.h>

chroot

clearerr

void clearerr(FILE *stream);

#include <stdio.h>

276

Programando em C para Linux, Unix e Windows

clearenv

int clearenv(void);

#include <stdlib.h>


clock


clock_t clock(void);
#include <time.h>
clock_t


CLOCKS_PER_SEC

close


int close(int fd);

#include <unistd.h>

fdopen


closedir
int closedir(DIR *dir);

#include <sys/types.h>
#include <dirent.h>

opendir

closelog
void closelog(void);

#include <syslog.h>
syslog
connect

connect(int
sockfd,
const struct sockaddr
int
*serv_addr, socklen_t addrlen);

#include <sys/types.h>
#include

<sys/socket.h>


copysign
double copysign(double x, double y);

x
y

Guia de Referncia das Funes

277

cos


double cos(double num);

#include <math.h>

creat


int creat(const char *pathname, mode_t

#include
#include

#include

crypt

mode);
<sys/types.h>
<sys/stat.h>
<fcntl.h>


char *crypt(const char *key, const char *salt);

#include <unistd.h>

ctermid

char *ctermid(char *s);

#include <stdio.h>

ctime


char *ctime(const time_t *timep);


#include <time.h>

cuserid

char *cuserid(char *string);

#include <stdio.h>


daemon
int daemon (int nochdir, int noclose);

#include <unistd.h>

daemon

difftime
double difftime(time_t time1, time_t time0);

#include <time.h>
time1time0

278

Programando em C para Linux, Unix e Windows

dirname

char *dirname(char *path);

#include <libgen.h>

div


div_t div(int numer, int denom);
div_t #include <stdlib.h>

dup


int dup(int oldfd);

#include <unistd.h>

dup2


int dup2(int oldfd, int newfd);

#include <unistd.h>

newfd

endgrent
void endgrent(void);

endpwent
void endpwent(void);

#include <sys/types.h>
#include <grp.h>
/etc/group

#include <sys/types.h>
#include <pwd.h>
/etc/passwd

execl


int execl(const char *path, const char *arg, ...);
int
#include <unistd.h>

Guia de Referncia das Funes

279

execle


int execle(const char *path, const char *arg ,
..., char * const envp[]);
int
#include <unistd.h>

execlp


int execlp(const char *file, const char *arg, ...);
int
#include <unistd.h>

execv


int execv(const char *path, char *const argv[]);
int
#include <unistd.h>

execve

execve(const
char
*filename,
char
*const
int
argv [], char *const envp[]);
int
#include <unistd.h>

execvp

int execvp(const char *file, char *const argv[]);
int
#include <unistd.h>

exit


void exit(int status);

#include <stdlib.h>

atexit

280

Programando em C para Linux, Unix e Windows

exp


double exp(double num);

#include <math.h>
e

fabs


double fabs(double num);

#include <math.h>

fchdir


int fchdir(int fd);

#include <unistd.h>

chdir

fchmod

int fchmod(int fildes, mode_t mode);

#include <sys/types.h>
#include <sys/stat.h>

chmod

fchown

int fchown(int fd, uid_t owner, gid_t group);

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

chown

fclose


int fclose(FILE *stream);

#include <stdio.h>
EOF

fcntl


int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);

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

cmd

Guia de Referncia das Funes

281

fdopen

FILE * fdopen (int FileDescriptor, const char *type)

#include <stdio.h>
NULL

FILE
feof


int feof(FILE *stream);
#include <stdio.h>

ferror


int ferror(FILE *stream);

#include <stdio.h>

fflush


int fflush(FILE *stream);

#include <stdio.h>
EOF

fgetc


int fgetc(FILE *stream);

#include <stdio.h>
EOF


fgetgrent
struct group *fgetgrent(FILE *stream);

#include <stdio.h>
#include <sys/types.h>
NULL
#include <grp.h>

/etc/group

282

Programando em C para Linux, Unix e Windows

fgetpwen

struct passwd *fgetpwent(FILE *stream);

#include <stdio.h>
#include <sys/types.h>
NULL
#include <pwd.h>

/etc/passwd

fgetpos
int fgetpos(FILE *stream, fpos_t *pos);

#include <stdio.h>

ftell
fgets


char *fgets(char *s, int size, FILE *stream);
NULL
#include <stdio.h>

fileno


int fileno(FILE *stream);
int
#include <stdio.h>
stream

stream

flock


int flock(int fd, int operation);

#include <sys/file.h>

floor


Double floor(double num);

#include <math.h>
num

floor(1.4)1.0

fopen


FILE * fopen(const char *path, const char *type)
FILE
#include <stdio.h>
NULL
streamFILE

Guia de Referncia das Funes

283

fopen64

FILE * fopen64(const char *path, const char *type)
FILE
#include <stdio.h>
NULL
streamFILE

fork


pid_t fork(void);
PID
#include <sys/types.h>
#include <unistd.h>

fpathconf

long fpathconf(int filedes, int name);

#include <unistd.h>

name

fprintf


int fprintf (FILE *stream, const char *format,
[value, . . .])

#include <stdio.h>

stream

fputc


int fputc(int c, FILE *stream);

#include <stdio.h>
EOF

fputs


int fputs(const char *s, FILE *stream);

#include <stdio.h>
EOF

fread


size_t fread ( (const void *) pointer, size_t size,
size_t NumberOfItems, FILE * stream)

#include <stdio.h>
(size * NumberOfItems)

284
free

Programando em C para Linux, Unix e Windows



void free(void *ptr)

#include <stdlib.h>
mallocrealloccalloc


freopen
FILE * freopen ( const char *path, const char *type,
FILE * stream)
FILE
#include <stdio.h>
NULL
streamFILE


freopen64
FILE * freopen64 ( const char *path, const char
*type, FILE * stream)
FILE
#include <stdio.h>
NULL
streamFILE


int fscanf(FILE *stream, const char *format, ...);

#include <stdio.h>
EOF

scanf

fscanf

fseek


int fseek(FILE *stream, long offset, int whence);

#include <stdio.h>


fsetpos
int fsetpos(FILE *stream, fpos_t *pos);

#include <stdio.h>

fseek
SEEK_SET

Guia de Referncia das Funes

285

fstat


int fstat(int filedes, struct stat *buf);

#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>

fsync


int fsync(int fd);

#include <unistd.h>

ftell


long ftell(FILE *stream);

#include <stdio.h>

long

ftime


int ftime(struct timeb *tp);

#include <sys/timeb.h>


ftruncate
int ftruncate(int fd, off_t length);

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



size_t fwrite(const void pointer, size_t size,
size_t NumberOfItems, FILE * stream)

#include <stdio.h>

fwrite

getc


int getc(FILE *stream);

#include <stdio.h>
EOF

fgetc

286

Programando em C para Linux, Unix e Windows

getchar

int getchar(void);

#include <stdio.h>
EOF



getcwd
char *getcwd(char *buf, size_t size);

#include <unistd.h>



getdate
struct tm *getdate (const char *string);

#include <time.h>
NULL
tm
getegid

gid_t getegid (void);

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


getenv
char *getenv(const char *name;)
#include <stdlib.h>
NULL


geteuid
uid_t geteuid(void);

getgid
gid_t getgid (void);

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

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

Guia de Referncia das Funes

287

getgrent

struct group *getgrent(void);

#include <sys/types.h>
#include <grp.h>
/etc/group


getgrgid
struct group *getgrgid(gid_t GID)

#include <sys/types.h>
#include <grp.h>
NULL


/etc/group

getgrnam
struct group *getgrnam(const char * name)

#include <sys/types.h>
#include <grp.h>
NULL


/etc/group

getgroups
int getgroups(int ngroups, gid_t GIDSet)

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

GIDsGIDSet


gethostid

#include <unistd.h>


gethostname
int gethostname(char * name, int length)

#include <unistd.h>

length

288

Programando em C para Linux, Unix e Windows

getlogin

char *getlogin (void)

#include <sys/types.h>
#include <unistd.h>
NULL
#include <limits.h>


getlogin_r
int getlogin_r(char * name, size_t length);

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

#include <limits.h>


getmsg
int getmsg (int fd, struct strbuf *ctlptr, struct
strbuf *dataptr, int *flags);

#include <stropts.h>



getopt
int getopt(int argc, char * const argv[], const char
*optstring);

#include <unistd.h>
:



getpeername
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);

#include
<sys/socket.h>

getpgid

pid_t getpgid(pid_t pid);

#include <unistd.h>

Guia de Referncia das Funes

289

getpgrp

pid_t getpgrp (void);
GID
#include <unistd.h>
GID
getpid
pid_t getpid(void);

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

3
getpmsg
int getpmsg (int fd, struct strbuf *ctlptr, struct
strbuf *dataptr, int *bandp, int *flags);

#include <stropts.h>

getmsg


getppid
pid_t getppid (void);

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

getpwent

struct passwd *getpwent (void);

#include <sys/types.h>
#include <pwd.h>
NULL


/etc/passwd
getpwnam

struct passwd *getpwnam(char *name)

#include <sys/types.h>
#include <pwd.h>
NULL
name
/etc/passwd

290

Programando em C para Linux, Unix e Windows

getpwuid

struct passwd *getpwuid(uid_t uid);

#include <sys/types.h>
#include <pwd.h>
NULL
uid
/etc/passwd
gets


char *gets(char * string)

#include <stdio.h>

NULL

stdin

getsid


pid_t getsid(pid_t pid);

#include <unistd.h>


getsockname
int getsockname(int s, struct sockaddr *
socklen_t * namelen);

#include
<sys/socket.h>

name,


gmtime
struct tm *gmtime(time_t *time)

#include <time.h>

long

gettimeofday
int gettimeofday(struct timeval *tv, struct timezone *tz);

#include <sys/time.h>


getuid
uid_t getuid(void);

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

Guia de Referncia das Funes

291

getumask

mode_t getumask(void);

#include <sys/types.h>
#include <sys/stat.h>


initgroups
int initgroups(char *user, int GID)

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



getgrentgetpwent

isalnum
int isalnum(int ch);
ch
#include <ctype.h>
ch
ch



isalpha
int isalpha(int ch);

#include <ctype.h>

iscntrl


int iscntrl(int ch)
#include <ctype.h>

00x1F
0x7FDEL

isdigit


int isdigit(int ch);

#include <ctype.h>

292

Programando em C para Linux, Unix e Windows

isgraph

int isgraph(int ch);

#include <ctype.h>


islower
int islower

#include <ctype.h>



int isprint(int ch);

#include <ctype.h>

isprint


ispunct
int ispunct(int ch);

#include <ctype.h>



isspace
int isspace(int ch);

#include <ctype.h>

isupper

int isupper(int ch);

#include <ctype.h>


isxdigit

int isxdigit(int ch);

#include <ctype.h>

Guia de Referncia das Funes

293

kill


int kill(int process, int signal);

#include <sys/types.h>
#include <signal.h>

killpg


int killpg(int pgrp, int sig);

#include <signal.h>


pgrp

labs


long labs(long num);

#include <stdlib.h>

llabs


long long int llabs(long long int j);

#include <stdlib.h>


lchown
int lchown (const char *path, uid_t owner, gid_t
group);

#include <unistd.h>


chown
link


int link(const char *path1, const char *path2);

#include <unistd.h>

listen


int listen(int s, int backlog);

#include
<sys/socket.h>

294

Programando em C para Linux, Unix e Windows

localtime

Struct tm *localtime(const time_t * time);

#include <time.h>

long
log


Double log(double num);

#include <math.h>

log10


Double log10(double num);
num
#include <math.h>

login


void login(const struct utmp *ut);

#include <utmp.h>


int logout(const char *ut_line);

#include <utmp.h>

logout

lseek


off_t lseek (int fd, off_t offset, int whence)

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


fseek


lseek64
off64_t lseek64 (int fd, off64_t offset, int whence)

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


fseek

Guia de Referncia das Funes


lstat

295


int lstat(const char *path, Buffer)

#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>

3
void *malloc(size_t size);
#include <stdlib.h>
NULL

malloc


memchr
void *memchr(const void *s, int c, size_t n);

#include <string.h>

NULL

memcmp

int memcmp(const void *s1, const void *s2, size_t n);

#include <string.h>


memcpy
void *memcpy(void *dest, const void *src, size_t n);
dest
#include <string.h>
n

memmove

void *memmove(void *dest, const void *src, size_t n);
dest
#include <string.h>
n


memset
void *memset(void *s, int c, size_t n);
s
#include <string.h>
n

296

Programando em C para Linux, Unix e Windows

mkdtemp

char *mkdtemp(char *template);

#include <stdlib.h>
NULL

mkdir


int mkdir(const char *path, mode_t mode)

#include <sys/stat.h>
#include <sys/types.h>


mkfifo
int mkfifo (const char *path, mode_t mode)

#include <sys/types.h>
#include <sys/stat.h>


mknod
int mknod(const char *pathname, mode_t mode, dev_t
dev);

#include <sys/types.h>
#include <sys/stat.h>

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


mkstemp
int mkstemp(char *template);

#include <stdlib.h>


mktemp

char *mktemp(char *template);

#include <stdlib.h>
NULL


mktime
time_t mktime(struct tm *timeptr)
long
#include <time.h>

Guia de Referncia das Funes

297

mmap


caddr_t *mmap(void *addr, size_t len, int prot, int
flags, int fildes, off_t off);
void *mmap(void *addr, size_t len, int prot, int
flags, int fildes, off_t off);
#include <sys/types.h>

#include <sys/mman.h>

mount

int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags, const void *data);

#include <sys/mount.h>


mremap

void * mremap(void *old_address, size_t old_size ,
size_t new_size, unsigned long flags);

#include <unistd.h>

#include <sys/mman.h>


msync


int msync(const void *start, size_t length, int
flags);


mmap


munmap
int munmap(void *start, size_t length);

#include <sys/mman.h>


nice


int nice(int inc);

#include <unistd.h>

298
open

Programando em C para Linux, Unix e Windows



int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>


opendir
DIR *opendir(const char *name);

#include <sys/types.h>
#include <dirent.h>
NULL


openlog
void openlog( char *ident, int option, int facility);

#include <syslog.h>

syslog
pause


int pause(void);

#include <unistd.h>


pathconf
long pathconf(char *path, int name);

#include <unistd.h>

name


int pclose(FILE *stream);

#include <stdio.h>

pclose

perror


void perror(const char *s);

#include <stdio.h>
errno

Guia de Referncia das Funes


pipe

299


int pipe(int filedes[2]);

#include <unistd.h>

inode
pipe filedes filedes[0]
filedes[1]

popen


FILE *popen(const char *command, const char *type);

#include <stdio.h>
NULL
pipe

pow


double pow(double base, double exp);
exp
base
#include <math.h>

printf


int printf(const char *format, [Value, ...]);

#include <stdio.h>


psignal
void psignal(int sig, const char *s);

#include <signal.h>

ptrace

long ptrace(enum __ptrace_request request, pid_t
pid, void *addr);
#include
<sys/ptrace.h>


strace
putc


int putc(int c, FILE *stream);

#include <stdio.h>

300

Programando em C para Linux, Unix e Windows

putchar

int putchar(int c);

#include <stdio.h>


putenv
int putenv(const char *string);

#include <stdlib.h>



putgrent
int putgrent(const struct group *grp, FILE *fp);

#include <grp.h>


/etc/group

putpwent
int putpwent(const struct passwd *p, FILE *stream);

#include <pwd.h>
#include <stdio.h>

#include <sys/types.h>

/etc/passwd
puts


int puts(const char *s);

#include <stdio.h>
EOF

qsort


void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));

#include <stdlib.h>

raise


int raise (int sig);

#include <signal.h>

Guia de Referncia das Funes

301

rand


int rand(void);

#include <stdlib.h>

intRAND_MAX

read


ssize_t read(int fd, void *buf, size_t count);

#include <unistd.h>

readv


int readv(int filedes, const struct iovec *vector,
size_t count);

#include <sys/uio.h>


void *realloc(void *ptr, size_t);

#include <stdlib.h>

realloc


readdir
struct dirent *readdir(DIR *dp);

#include <sys/types.h>
#include <dirent.h>
NULL


readlink

int readlink(const char *path, char *buf, size_t
bufsize);

#include <unistd.h>



recvfrom
ssize_t recvfrom(int s, void *buf, size_t len int
flags, struct sockaddr *from, socklen_t *fromlen

#include <sys/types.h>
#include

<sys/socket.h>

302

Programando em C para Linux, Unix e Windows

remove

int remove(const char *pathname);

#include <stdio.h>


rename

rename(const
char
*oldpath,
const
char
int
*newpath);

#include <stdio.h>



rewind
void rewind( FILE *stream);

#include <stdio.h>

rewinddir

void rewinddir(DIR *dir);

#include <sys/types.h>
#include <dirent.h>

rmdir


int rmdir(const char *pathname);

#include <unistd.h>

scanf


int scanf(const char *format, ...);

#include <stdio.h>
EOF

intfloatstring


seekdir
void seekdir(DIR *dir, off_t offset);

#include <dirent.h>

Guia de Referncia das Funes

303

select


int select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);

#include <sys/time.h>
#include <sys/types.h>

#include <unistd.h>


int semctl(int semid, int semnum, int cmd);

#include <sys/types.h>
#include <sys/ipc.h>

#include <sys/sem.h>

semctl


semget
int semget(key_t key, int nsems, int semflg);

#include <sys/types.h>
#include <sys/ipc.h>

#include <sys/sem.h>


semop
int semop(int semid, struct sembuf *sops, unsigned
nsops);

#include <sys/types.h>
#include <sys/ipc.h>

#include <sys/sem.h>

send


ssize_t send(int s, const void *buf, size_t len int
flags);

#include <sys/types.h>
#include

<sys/socket.h>


sendto
ssize_t sendto(int s, const void *buf, size_t len int
flags, const struct sockaddr *to, socklen_t tolen);

#include <sys/types.h>
#include

<sys/socket.h>

304

Programando em C para Linux, Unix e Windows

setbuf


void setbuf(FILE *stream, char *buf);

#include <stdio.h>

setbuffer

void setbuffer(FILE *stream, char *buf, size_tsize);

#include <stdio.h>


int setenv(const char *name, const char *value, int
overwrite);

#include <stdlib.h>

putenv

setenv


seteuid
int seteuid(uid_t euid);

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


setegid

int setegid(gid_t egid);

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


setgid


int setgid(gid_t gid);

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

setgrent
void setgrent(void);

#include <grp.h>
#include <sys/types.h>
/etc/group

Guia de Referncia das Funes

305

setgroups

int setgroups(size_t size, const gid_t *list);

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


sethostid
int sethostid(long hostid);

#include <unistd.h>

/etc/hostid

sethostname
int sethostname(const char *name, size_t len);

#include <unistd.h>


setlinebuf
void setlinebuf(FILE *stream);

#include <stdio.h>


setlocale
char *setlocale(int category, const char * locale);

#include <locale.h>
NULL


setpgid
int setpgid(pid_t pid, pid_t pgid);

#include <unistd.h>



setpgrp
int setpgrp(void);

#include <unistd.h>


setpgid(0,0)

306

Programando em C para Linux, Unix e Windows

setpwent
void setpwent(void);

#include <sys/types.h>
#include <pwd.h>


settimeofday
int settimeofday(const struct timeval *tv , const
struct timezone *tz);

#include <sys/time.h>


setsid


pid_t setsid(void);

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


int setuid(uid_t uid);

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

setuid


setvbuf
int setvbuf(FILE *stream, char *buf, int mode
size_t size);

#include <stdio.h>


shutdown
int shutdown(int s, int how);

#include
<sys/socket.h>


siginterrupt
int siginterrupt(int sig, int flag);

#include <signal.h>

Guia de Referncia das Funes


sleep

307


unsigned int sleep(unsigned int seconds);

#include <unistd.h>

signal


typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

#include <signal.h>
SIG_ERR

sin


double sin(double num);
num
#include <math.h>


socket
int socket(int domain, int type, int protocol);

#include <sys/types.h>
#include

<sys/socket.h>

sprintf


int sprintf(char *string, const char * format,
[Value, ]);

#include <stdio.h>

string

sqrt


double sqrt(double num);

#include <math.h>

srand


void srand(int seed);

#include <stdlib.h>

rand

308
stat

Programando em C para Linux, Unix e Windows



int stat(const char *file_name, struct

#include
#include

#include

stat *buf);
<sys/types.h>
<sys/stat.h>
<unistd.h>


int stime(time_t *t);

#include <time.h>

stime


strcasecmp
int strcasecmp(const char *s1, const char *s2);

#include <string.h>


strcat


char *strcat(char *dest, const char *src);

#include <string.h>

strchr


char *strchr(const char *s, int c);

#include <string.h>
NULL



int strcmp(const char *s1, const char *s2);

#include <string.h>

strcmp

strcoll


int strcoll(const char *s1, const char *s2);

#include <string.h>


setlocale

Guia de Referncia das Funes

309

strcpy


char *strcpy(char *dest, const char *src);

#include <string.h>
destino
srcdest

char *strdup(const char *s);

#include <string.h>

strdup


strerror
char *strerror(int errnum);

#include <string.h>


strftime
size_t strftime(char *s, size_t max, const char
*format const struct tm *tm);
#include <time.h>

strlen


size_t strlen (const char *string)
string
#include <string.h>
string\0NULL


strncasecmp
int strncasecmp(const char *s1, const char *s2,
size_t n);

#include <string.h>

strncat

char *strncat(char *dest, const char *src, size_t
n);

#include <string.h>
n

310

Programando em C para Linux, Unix e Windows

strncmp

int strncmp(const char *s1, const char *s2, size_t
n);

#include <string.h>


strncpy
char *strncpy(char *dest, const char *src, size_t
n);

#include <string.h>
destino
n
srcdest

strnlen
size_t strnlen (const char *s, size_t maxlen);

#include <string.h>


strpbrk
char *strpbrk(const char *s, const char *accept);

#include <string.h>
NULL
accepts

strptime
char *strptime(const char *s, const char *formato,
struct tm *tm);

#include <time.h>
NULL

tm

char *strrchr(const char *s, int c);

#include <string.h>
NULL

strrchr

Guia de Referncia das Funes

311

strstr


char *strstr(const char *haystack, const char *needle);

#include <string.h>
NULL

strtok


char *strtok(char *s, const char *delim);
#include <string.h>

NULL



int sscanf(const char *str, const char *format,
...);

#include <stdio.h>
EOF

scanf

sscanf

symlink

int symlink(const char *oldpath, const char *newpath);

#include <unistd.h>

sync


int sync(void);

#include <unistd.h>

sysconf

long sysconf(int name);

#include <unistd.h>


void syslog( int priority, char *format, ...);

#include <syslog.h>

syslog

312
sysctl

Programando em C para Linux, Unix e Windows



int sysctl(struct __sysctl_args *args);

#include <unistd.h>
#include

<linux/unistd.h>
#include
<linux/sysctl.h>


system
int system (const char * string);

#include <stdlib.h>


tan


double tan(double num);
num
#include <math.h>

telldir


off_t telldir(DIR *dir);

#include <dirent.h>


tempnam
char *tempnam(const char *dir, const char *pfx);

#include <stdio.h>

time


time_t time(time_t *t);

#include <time.h>

times


clock_t times(struct tms *buf);

#include <sys/times.h>

buf

Guia de Referncia das Funes

313

tmpfile

FILE *tmpfile (void);

#include <stdio.h>
NULL


tmpnam
char *tmpnam(char *s);

#include <stdio.h>
NULL


int toascii (int c);

#include <ctype.h>

toascii

toupper

int toupper (int c);

#include <ctype.h>


tolower
int tolower (int c);

#include <ctype.h>

trunc


double trunc(double x);

#include <math.h>


truncate
int truncate(const char *path, off_t length);

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



umask
mode_t umask(mode_t mask);

#include <sys/types.h>
#include <sys/stat.h>

314

Programando em C para Linux, Unix e Windows

umount

int umount(const char *target);
int umount2(const char *target, int flags);

#include <sys/mount.h>

mount

uname
int uname(struct utsname *buf);

#include
<sys/utsname.h>



int unlink(const char *pathname);

#include <unistd.h>

unlink


unsetenv
void unsetenv(const char *name);

#include <stdlib.h>


void usleep(unsigned long usec);

#include <unistd.h>

usleep

utime


int utime(const char *filename, struct utimbuf
*buf);

#include <sys/types.h>
#include <utime.h>


va_end
void va_end( va_list ap);

#include <stdarg.h>

Guia de Referncia das Funes

315

va_copy

void va_copy(va_list dest, va_list src);

#include <stdarg.h>


va_start
void va_start( va_list ap, last);

#include <stdarg.h>

wait


pid_t wait(int *status);

#include <sys/types.h>
#include <sys/wait.h>

waitpid

pid_t waitpid(pid_t pid, int *status, int options);

#include <sys/types.h>
#include <sys/wait.h>

write


ssize_t write(int fd, const void *buf, size_t
count);

#include <unistd.h>



int writev(int filedes, const struct iovec *vector,
size_t count);

#include <sys/uio.h>

writev


Advanced Programming in the Unix Environment. Stevens, W. Richard. Editora
Addison Wesley Pub.
C Completo e Total. Schildt, Hebert. Editora Makron Books.
Guia Completo ao Teste de Software. Hetzel, William. Editora Campus.
Unix Networking Programming Networking Apis-Sockets and XTI. Stevens,
W. Richard. Editora Prentice Hall.
Unix Networking Programming Interprocess Communications. Stevens, W.
Richard. Editora Prentice Hall.


Bolha 241
break 42

#
#define 58
#else 59
#endif 59
#error 65
#if 59
#ifdef 62
#ifndef 62
#include 57
#undef 63

C
C ANSI 4
C ISO 4
C99 5
calloc 116
Case Sensitive 10
clearerr 110
close 155, 218
connect 212
Constantes 6
continue 43
creat 154
Criao de processos 178
ctime 131

?
? 35

A
accept 214
access 171
Ajuda 247
ANSI 95
asctime 131
atexit 54

D
daemon 200
do...while 41

errno 138
Erros 138, 205

bind 210

320

Programando em C para Linux, Unix e Windows

Estruturas 120
execl 185
exit 45
extern 52

F
fclose 98
feof 104
ferror 110
fflush 108
fopen 96
for 39
fork 179
fprintf 105
fread 99
free 115
fscanf 106
fseek 103
ftell 109
Funes 47, 48, 271
_exit Erro! Indicador no definido.
abort Erro! Indicador no definido.
abs Erro! Indicador no definido.
accept Erro! Indicador no definido.
access Erro! Indicador no definido.
acos Erro! Indicador no definido.
alarm Erro! Indicador no definido.
alloca Erro! Indicador no definido.
asctime Erro! Indicador no definido.
asin Erro! Indicador no definido.
assert Erro! Indicador no definido.
atan Erro! Indicador no definido.
atexit Erro! Indicador no definido.
atof Erro! Indicador no definido.
atoi Erro! Indicador no definido.
atol Erro! Indicador no definido.
atoll Erro! Indicador no definido.
basename Erro! Indicador no
definido.
bind Erro! Indicador no definido.
bsearch Erro! Indicador no definido.
calloc Erro! Indicador no definido.
cbrt Erro! Indicador no definido.
ceil Erro! Indicador no definido.
chdir Erro! Indicador no definido.
chmod Erro! Indicador no definido.
chown Erro! Indicador no definido.

chroot Erro! Indicador no definido.


clearerr Erro! Indicador no definido.
clearenv Erro! Indicador no
definido.
clock Erro! Indicador no definido.
close Erro! Indicador no definido.
closedir Erro! Indicador no definido.
closelog Erro! Indicador no
definido.
connect Erro! Indicador no
definido.
copysign Erro! Indicador no
definido.
cos Erro! Indicador no definido.
creat Erro! Indicador no definido.
crypt Erro! Indicador no definido.
ctermid Erro! Indicador no definido.
ctime Erro! Indicador no definido.
cuserid Erro! Indicador no definido.
daemon Erro! Indicador no
definido.
difftime Erro! Indicador no
definido.
dirname Erro! Indicador no
definido.
div Erro! Indicador no definido.
dup Erro! Indicador no definido.
dup2 Erro! Indicador no definido.
endgrent Erro! Indicador no
definido.
endpwent Erro! Indicador no
definido.
execl Erro! Indicador no definido.
execle Erro! Indicador no definido.
execlp Erro! Indicador no definido.
execv Erro! Indicador no definido.
execve Erro! Indicador no definido.
execvp Erro! Indicador no definido.
exit Erro! Indicador no definido.
exp Erro! Indicador no definido.
fabs Erro! Indicador no definido.
fchdir Erro! Indicador no definido.
fchmod Erro! Indicador no definido.
fchown Erro! Indicador no definido.
fclose Erro! Indicador no definido.
fcntl Erro! Indicador no definido.
fdopen Erro! Indicador no definido.
feof Erro! Indicador no definido.
ferror Erro! Indicador no definido.

ndice Remissivo
fflush Erro! Indicador no definido.
fgetc Erro! Indicador no definido.
fgetgrent Erro! Indicador no
definido.
fgetpwen Erro! Indicador no
definido.
fgetpos Erro! Indicador no definido.
fgets Erro! Indicador no definido.
fileno Erro! Indicador no definido.
flock Erro! Indicador no definido.
floor Erro! Indicador no definido.
fopen Erro! Indicador no definido.
fopen64 Erro! Indicador no
definido.
fork Erro! Indicador no definido.
fpathconf Erro! Indicador no
definido.
fprintf Erro! Indicador no definido.
fputc Erro! Indicador no definido.
fputs Erro! Indicador no definido.
fread Erro! Indicador no definido.
free Erro! Indicador no definido.
freopen Erro! Indicador no
definido.
freopen64 Erro! Indicador no
definido.
fscanf Erro! Indicador no definido.
fseek Erro! Indicador no definido.
fsetpos Erro! Indicador no definido.
fstat Erro! Indicador no definido.
fsync Erro! Indicador no definido.
ftell Erro! Indicador no definido.
ftime Erro! Indicador no definido.
ftruncate Erro! Indicador no
definido.
fwrite Erro! Indicador no definido.
getc Erro! Indicador no definido.
getchar Erro! Indicador no definido.
getcwd Erro! Indicador no definido.
getdate Erro! Indicador no
definido.
getegid Erro! Indicador no
definido.
getenv Erro! Indicador no definido.
geteuid Erro! Indicador no
definido.
getgid Erro! Indicador no definido.
getgrent Erro! Indicador no
definido.

321

getgrgid Erro! Indicador no


definido.
getgrnam Erro! Indicador no
definido.
getgroups Erro! Indicador no
definido.
gethostid Erro! Indicador no
definido.
gethostname Erro! Indicador no
definido.
getlogin Erro! Indicador no
definido.
getlogin_r Erro! Indicador no
definido.
getmsg Erro! Indicador no definido.
getopt Erro! Indicador no definido.
getpeername Erro! Indicador no
definido.
getpgid Erro! Indicador no
definido.
getpgrp Erro! Indicador no
definido.
getpid Erro! Indicador no definido.
getpmsg Erro! Indicador no
definido.
getppid Erro! Indicador no
definido.
getpwent Erro! Indicador no
definido.
getpwnam Erro! Indicador no
definido.
getpwuid Erro! Indicador no
definido.
gets Erro! Indicador no definido.
getsid Erro! Indicador no definido.
getsockname Erro! Indicador no
definido.
gmtime Erro! Indicador no
definido.
gettimeofday Erro! Indicador no
definido.
getuid Erro! Indicador no definido.
getumask Erro! Indicador no
definido.
initgroups Erro! Indicador no
definido.
isalnum Erro! Indicador no
definido.
isalpha Erro! Indicador no definido.

322

Programando em C para Linux, Unix e Windows

iscntrl Erro! Indicador no definido.


isdigit Erro! Indicador no definido.
isgraph Erro! Indicador no definido.
islower Erro! Indicador no definido.
isprint Erro! Indicador no definido.
ispunct Erro! Indicador no definido.
isspace Erro! Indicador no definido.
isupper Erro! Indicador no definido.
isxdigit Erro! Indicador no definido.
kill Erro! Indicador no definido.
killpg Erro! Indicador no definido.
labs Erro! Indicador no definido.
llabs Erro! Indicador no definido.
lchown Erro! Indicador no definido.
link Erro! Indicador no definido.
listen Erro! Indicador no definido.
localtime Erro! Indicador no
definido.
log Erro! Indicador no definido.
log10 Erro! Indicador no definido.
login Erro! Indicador no definido.
logout Erro! Indicador no definido.
lseek Erro! Indicador no definido.
lseek64 Erro! Indicador no definido.
lstat Erro! Indicador no definido.
malloc Erro! Indicador no definido.
memchr Erro! Indicador no
definido.
memcmp Erro! Indicador no
definido.
memcpy Erro! Indicador no
definido.
memmove Erro! Indicador no
definido.
memset Erro! Indicador no
definido.
mkdtemp Erro! Indicador no
definido.
mkdir Erro! Indicador no definido.
mkfifo Erro! Indicador no definido.
mknod Erro! Indicador no definido.
mkstemp Erro! Indicador no
definido.
mktemp Erro! Indicador no
definido.
mktime Erro! Indicador no definido.
mmap Erro! Indicador no definido.
mount Erro! Indicador no definido.

mremap Erro! Indicador no


definido.
msync Erro! Indicador no definido.
munmap Erro! Indicador no
definido.
nice Erro! Indicador no definido.
open Erro! Indicador no definido.
opendir Erro! Indicador no
definido.
openlog Erro! Indicador no
definido.
pause Erro! Indicador no definido.
pathconf Erro! Indicador no
definido.
pclose Erro! Indicador no definido.
perror Erro! Indicador no definido.
pipe Erro! Indicador no definido.
popen Erro! Indicador no definido.
pow Erro! Indicador no definido.
printf Erro! Indicador no definido.
psignal Erro! Indicador no definido.
ptrace Erro! Indicador no definido.
putc Erro! Indicador no definido.
putchar Erro! Indicador no
definido.
putenv Erro! Indicador no definido.
putgrent Erro! Indicador no
definido.
putpwent Erro! Indicador no
definido.
puts Erro! Indicador no definido.
qsort Erro! Indicador no definido.
raise Erro! Indicador no definido.
rand Erro! Indicador no definido.
read Erro! Indicador no definido.
readv Erro! Indicador no definido.
realloc Erro! Indicador no definido.
readdir Erro! Indicador no definido.
readlink Erro! Indicador no
definido.
recvfrom Erro! Indicador no
definido.
remove Erro! Indicador no definido.
rename Erro! Indicador no definido.
rewind Erro! Indicador no definido.
rewinddir Erro! Indicador no
definido.
rmdir Erro! Indicador no definido.
scanf Erro! Indicador no definido.

ndice Remissivo
seekdir Erro! Indicador no definido.
select Erro! Indicador no definido.
semctl Erro! Indicador no definido.
semget Erro! Indicador no definido.
semop Erro! Indicador no definido.
send Erro! Indicador no definido.
sendto Erro! Indicador no definido.
setbuf Erro! Indicador no definido.
setbuffer Erro! Indicador no
definido.
setenv Erro! Indicador no definido.
seteuid Erro! Indicador no definido.
setegid Erro! Indicador no definido.
setgid Erro! Indicador no definido.
setgrent Erro! Indicador no
definido.
setgroups Erro! Indicador no
definido.
sethostid Erro! Indicador no
definido.
sethostname Erro! Indicador no
definido.
setlinebuf Erro! Indicador no
definido.
setlocale Erro! Indicador no
definido.
setpgid Erro! Indicador no definido.
setpgrp Erro! Indicador no definido.
setpwent Erro! Indicador no
definido.
settimeofday Erro! Indicador no
definido.
setsid Erro! Indicador no definido.
setuid Erro! Indicador no definido.
setvbuf Erro! Indicador no definido.
shutdown Erro! Indicador no
definido.
siginterrupt Erro! Indicador no
definido.
sleep Erro! Indicador no definido.
signal Erro! Indicador no definido.
sin Erro! Indicador no definido.
socket Erro! Indicador no definido.
sprintf Erro! Indicador no definido.
sqrt Erro! Indicador no definido.
srand Erro! Indicador no definido.
stat Erro! Indicador no definido.
stime Erro! Indicador no definido.

323

strcasecmp Erro! Indicador no


definido.
strcat Erro! Indicador no definido.
strchr Erro! Indicador no definido.
strcmp Erro! Indicador no definido.
strcoll Erro! Indicador no definido.
strcpy Erro! Indicador no definido.
strdup Erro! Indicador no definido.
strerror Erro! Indicador no definido.
strftime Erro! Indicador no
definido.
strlen Erro! Indicador no definido.
strncasecmp Erro! Indicador no
definido.
strncat Erro! Indicador no definido.
strncmp Erro! Indicador no
definido.
strncpy Erro! Indicador no definido.
strnlen Erro! Indicador no definido.
strpbrk Erro! Indicador no definido.
strptime Erro! Indicador no
definido.
strrchr Erro! Indicador no definido.
strstr Erro! Indicador no definido.
strtok Erro! Indicador no definido.
sscanf Erro! Indicador no definido.
symlink Erro! Indicador no definido.
sync Erro! Indicador no definido.
sysconf Erro! Indicador no definido.
syslog Erro! Indicador no definido.
sysctl Erro! Indicador no definido.
system Erro! Indicador no definido.
tan Erro! Indicador no definido.
telldir Erro! Indicador no definido.
tempnam Erro! Indicador no
definido.
time Erro! Indicador no definido.
times Erro! Indicador no definido.
tmpfile Erro! Indicador no definido.
tmpnam Erro! Indicador no
definido.
toascii Erro! Indicador no definido.
toupper Erro! Indicador no
definido.
tolower Erro! Indicador no
definido.
trunc Erro! Indicador no definido.
truncate Erro! Indicador no
definido.

324

Programando em C para Linux, Unix e Windows

umask Erro! Indicador no definido.


umount Erro! Indicador no
definido.
uname Erro! Indicador no definido.
unlink Erro! Indicador no definido.
unsetenv Erro! Indicador no
definido.
usleep Erro! Indicador no definido.
utime Erro! Indicador no definido.
va_end Erro! Indicador no definido.
va_copy Erro! Indicador no
definido.
va_start Erro! Indicador no
definido.
wait Erro! Indicador no definido.
waitpid Erro! Indicador no definido.
write Erro! Indicador no definido.
writev Erro! Indicador no definido.
fwrite 100

G
getchar 25
geteuid 168
gethostbyname 220
getpeername 219
getpid 166
getppid 166
getuid 168
gmtime 132
goto 44

K
K&R 4
kill 193

L
LCC-Win32 255
Linux 166, 188, 247
listen 213
localtime 132
lseek 159

M
main 9
malloc 114
Matrizes 70, 72, 89, 126
Memria 113
memset 118
mktime 134

N
ntohl 209
ntohs 209

O
open 149
Ordenao 241

H
htonl 209
htons 209

I
if 33
if...else... 34
inet_addr 211
inet_aton 211
inet_ntoa 211

P
Palavras Reservadas 11
perror 140
Pesquisa 244
Pointer Member 127
Ponteiros 32, 86, 127
Pr-Compilao 56
printf 20
Prottipo 47
putchar 24

ndice Remissivo

Q
Quicksort 242

R
raise 196
read 156
realloc 117
Recursividade 239
recv 217
recvfrom 218
remove 161
rename 164
return 49

strerror 139
Strings 75, 90
strlen 78
strncat 83
strncmp 85
strncpy 84
strstr 92
strtok 93
switch...case 36
syslog 205
system 187

T
TCP 221, 222, 223
time 129
typedef 17, 123

S
scanf 24
send 215
sendto 218
setsid 202
sfrtime 135
shutdown 218
signal 191
Sinais 188
sizeof 18
sleep 198
sockaddr 208
socket 207
sprintf 82
sscanf 82
stat 172
static 53
strcat 79
strcmp 80
strcpy 80
Streams 111

U
UDP 224, 225, 226
umask 176
uname 169
Unies 142
Unix 148, 166, 188, 247
unlink 162

V
Variveis 14, 50
Vetores 69

W
wait 181
waitpid 183
while 40
write 158

325


Introduo..................................................................................................1
1. Informaes Bsicas...............................................................................3
............................................................................................................ 3
........................................................................................................ 4
.............................................................................................. 4
................................................................................................................. 5
................................................................................................... 6
................................................................................... 6
.......................................................................................... 7
............................................................................. 8
................................................................................................... 9
.................................................................................... 10
............................................................................... 10
......................................................................... 11

2. Tipos de Dados ....................................................................................12


............................................................................................... 12
.......................................................... 13
.......................................................................... 14
.................................................................................. 16
................................................................................... 16
.............................................................................. 16
..................................................................................... 17
....................................................................................... 17
............................................................................................ 18

Programando em C para Linux, Unix e Windows

3. Entrada e Sada....................................................................................20
................................................................................................. 20
................................................................................ 21
................................................................................... 21
............................................................................................. 24
................................................................................................ 24
............................................................................................. 25

4. Operadores ..........................................................................................26
................................................................................ 26
..................................................................................... 26
............................................................................. 27
............................................................................... 28
................................................................................ 28
..................................................................................... 29
......................................................................... 30
...................................................... 31
..................................................................... 32

5. Comandos de Seleo..........................................................................33
................................................................................................... 33
....................................................................................... 34
.................................................................................................. 35
................................................................................ 36

6. Comandos de Repetio ......................................................................39


................................................................................................. 39
............................................................................................. 40
...................................................................................... 41
............................................................................................ 42
....................................................................................... 43
.............................................................................................. 44
................................................................................................ 45

7. Definies de Funes .........................................................................47


..................................................................................... 47
.................................................. 47
........................................................................................ 48
............................................................................................ 49
..................................................................................... 50
.......................................................................................... 50
........................................................................................... 51
............................................................................................ 52
............................................................................................. 53
.............................................................................................. 54

Sumrio

XI

8. Pr-Compilao ....................................................................................56
............................................................................ 56
........................................................................................... 57
............................................................................................. 58
.......................................................................... 59
............................................................................... 62
............................................................................................. 63
............................................................................................... 65
.................................................................................. 66

9. Vetores e Matrizes...............................................................................69
......................................................................................... 69
........................................................................................ 70
.............................................................................. 71
................................................................................... 72
........................................................................... 73

10. Strings ................................................................................................75


.......................................................................... 75
........................................................................... 76
....................................................................................... 77
.............................................................................................. 78
.............................................................................................. 79
............................................................................................. 80
............................................................................................ 80
............................................................................................. 82
............................................................................................ 82
.......................................................................................... 83
......................................................................................... 84
........................................................................................ 85

11. Ponteiros ............................................................................................86


.......................................................................................... 86
............................................................................... 86
........................................................................................ 87
.................................................................................. 88
.......................................................................... 89
................................................................................... 89
..................................................................................... 90
.............................................................................. 91
............................................................................................... 92
............................................................................................ 93

XII

Programando em C para Linux, Unix e Windows

12. Manipulao de Arquivos (padro ANSI) .........................................95


................................................................................ 95
............................................................................... 96
.............................................................................................. 96
............................................................................................. 98
............................................................................................... 99
............................................................................................ 100
............................................................................................. 101
............................................................................................ 103
............................................................................................... 104
.......................................................................................... 105
......................................................................................... 106
.......................................................................................... 108
............................................................................................. 109
.......................................................................... 110
...................................................................................... 111

13. Alocao de Memria......................................................................113


........................................................................ 113
.......................................................................................... 114
............................................................................................... 115
........................................................................................... 116
.......................................................................................... 117
........................................................................................ 118

14. Estruturas .........................................................................................120


............................................................................ 120
............................................................................ 121
........................................................................ 122
.............................................................................. 123
............................................................................... 124
................................................................................ 126
.............................................................................. 127
........................................................................................ 127

15. Data e Hora ......................................................................................129


.............................................................................................. 129
............................................................................ 130
.......................................................................... 131
..................................................................... 132
......................................................................................... 134
.......................................................................................... 135

Sumrio

XIII

16. Tratamento de Erros........................................................................138


........................................................................................... 138
......................................................................................... 139
........................................................................................... 140

17. Definies Avanadas......................................................................142


................................................................................. 142
................................................................................. 142
...................................................................................... 143
..................................................................................... 144
................................................................................. 145
............................................................................... 146
................................................................. 147

18. Manipulao de Arquivos (padro Linux e Unix)...........................148


.............................................................. 148
......................................................................... 149
............................................................................................. 149
............................................................................................. 154
............................................................................................ 155
.............................................................................................. 156
............................................................................................. 158
............................................................................................ 159
......................................................................................... 161
......................................................................................... 162
...................................................................................... 164

19. Buscando Algumas Informaes no Linux e Unix ..........................166


......................................................................... 166
......................................................................... 168
.......................................................................................... 169
......................................................................................... 171
............................................................................................... 172
.......................................................................................... 176

20. Criando Processos no Linux e Unix .................................................178


......................................... 178
............................................................................................... 179
.............................................................................................. 181
......................................................................................... 183
............................................................................................ 185
......................................................................................... 187

XIV

Programando em C para Linux, Unix e Windows

21. Tratamento de Sinais em Linux e Unix ...........................................188


.............................................................. 188
............................................................................................ 190
........................................................................................... 191
................................................................................................. 193
............................................................................................. 196
............................................................................................ 198
........................... 199

22. Daemons (Servios) em Linux e Unix..............................................200


................................................................................ 200
..................................................... 200
........................................................................................... 202
................................................... 205

23. Programao para Rede ..................................................................207


.......................................................................................... 207
................................................................................... 208
........................................................... 209
.............................................................................................. 210
................................................ 211
........................................................................................ 212
............................................................................................ 213
.......................................................................................... 214
............................................................................................. 215
............................................................................................ 217
.................................................................... 218
..................................................................... 218
............................................................................. 219
.......................................................................... 220
.............................................. 221
..................................................... 222
................................................... 223
.............................................. 224
................................................ 225
................................................... 226

24. Tcnicas de Programao para Facilitar a Depurao,


24. Documentao, Economia e Execuo de Processos ......................228
Apndice A. Programas Avanados ......................................................239
............................................................................................. 239
.................................................................................................. 241
..................................................................................................... 244

Sumrio

XV

Apndice B. Ajuda .................................................................................247


.................................................................. 247
..................................................................................... 247
......................................................................... 248
................................................................................ 248

Apndice C. Compilando no Linux........................................................251


Apndice D. Utilizando o LCC-Win32....................................................255
................................................................................................... 255
................................................................ 261
.......................................................................... 262
........................................................ 267

Apndice E. Guia de Referncia das Funes .......................................271


Bibliografia ............................................................................................317
ndice Remissivo ....................................................................................319

Das könnte Ihnen auch gefallen