I have three bugs/questions regarding the source code pasted below:
stack smashing deteced: In order to compile and not have that error I have addedd the gcc compile flag -fno-stack-protector. However, this should be just a temporary solution, since I would like to find where the cause for this is and correct it. However, I haven't been able to do so. Any clues?
For some reason, the last open function call doesn't work and the programs just stops there, without an error, even though the fifo already exists.
I want to delete the pipes from the filesystem after before terminating the processes. I have added close and unlink statements at the end, but the fifos are not removed. What am I doing wrong?
Thanks very much in advance.
P.S.: I am pasting here the whole source file for additional clarity. Just ignore the comments, since they are in my own native language.
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_INPUT_LENGTH 100
#define FIFO_NAME_MAX_LEN 20
#define FIFO_DIR "/tmp/"
#define FIFO_NAME_CMD_CLI_TO_SRV "lrc_cmd_cli_to_srv"
typedef enum { false, true } bool;
bool background = false;
char* logfile = NULL;
void read_from_fifo(int fd, char** var)
{
int n_bytes;
read(fd, &n_bytes, sizeof(int));
*var = (char *) malloc (n_bytes);
read(fd, *var, n_bytes);
printf("read %d bytes '%s'\n", n_bytes, *var);
}
void write_to_fifo(int fd, char* data)
{
int n_bytes = (strlen(data)+1) * sizeof(char);
write(fd, &n_bytes, sizeof(int)); //primeiro envia o numero de bytes que a proxima instrucao write ira enviar
write(fd, data, n_bytes);
printf("writing %d bytes '%s'\n", n_bytes, data);
}
int main(int argc, char* argv[])
{
//CRIA FIFO CMD_CLI_TO_SRV, se ainda nao existir
char* fifo_name_cmd_cli_to_srv;
fifo_name_cmd_cli_to_srv = (char*) malloc ( (strlen(FIFO_NAME_CMD_CLI_TO_SRV) + strlen(FIFO_DIR) + 1) * sizeof(char) );
strcpy(fifo_name_cmd_cli_to_srv, FIFO_DIR);
strcat(fifo_name_cmd_cli_to_srv, FIFO_NAME_CMD_CLI_TO_SRV);
int n = mkfifo(fifo_name_cmd_cli_to_srv, 0660); //TODO ver permissoes
if (n < 0 && errno != EEXIST) //se houver erro, e nao for por causa de ja haver um com o mesmo nome, termina o programa
{
fprintf(stderr, "erro ao criar o fifo\n");
fprintf(stderr, "errno: %d\n", errno);
exit(4);
}
//se por acaso já existir, nao cria o fifo e continua o programa normalmente
//le informacao enviada pelo cliente, nesta ordem:
//1. pid (em formato char*) do processo cliente
//2. comando /CONNECT
//3. nome de fifo INFO_SRV_TO_CLIXXX
//4. nome de fifo MSG_SRV_TO_CLIXXX
char* command;
char* fifo_name_info_srv_to_cli;
char* fifo_name_msg_srv_to_cli;
char* client_pid_string;
int client_pid;
int fd_cmd_cli_to_srv, fd_info_srv_to_cli;
fd_cmd_cli_to_srv = open(fifo_name_cmd_cli_to_srv, O_RDONLY);
read_from_fifo(fd_cmd_cli_to_srv, &client_pid_string);
client_pid = atoi(client_pid_string);
read_from_fifo(fd_cmd_cli_to_srv, &command); //recebe commando /CONNECT
read_from_fifo(fd_cmd_cli_to_srv, &fifo_name_info_srv_to_cli); //recebe nome de fifo INFO_SRV_TO_CLIXXX
read_from_fifo(fd_cmd_cli_to_srv, &fifo_name_msg_srv_to_cli); //recebe nome de fifo MSG_TO_SRV_TO_CLIXXX
//CIRA FIFO MSG_CLIXXX_TO_SRV
char fifo_name_msg_cli_to_srv[FIFO_NAME_MAX_LEN];
strcpy(fifo_name_msg_cli_to_srv, FIFO_DIR);
strcat(fifo_name_msg_cli_to_srv, "lrc_msg_cli");
strcat(fifo_name_msg_cli_to_srv, client_pid_string);
strcat(fifo_name_msg_cli_to_srv, "_to_srv");
n = mkfifo(fifo_name_msg_cli_to_srv, 0660);
if (n < 0)
{
fprintf(stderr, "error creating %s\n", fifo_name_msg_cli_to_srv);
fprintf(stderr, "errno: %d\n", errno);
exit(5);
}
//envia ao cliente a resposta ao commando /CONNECT
fd_info_srv_to_cli = open(fifo_name_info_srv_to_cli, O_WRONLY);
write_to_fifo(fd_info_srv_to_cli, fifo_name_msg_cli_to_srv);
free(logfile);
free(fifo_name_cmd_cli_to_srv);
close(fd_cmd_cli_to_srv);
unlink(fifo_name_cmd_cli_to_srv);
unlink(fifo_name_msg_cli_to_srv);
unlink(fifo_name_msg_srv_to_cli);
unlink(fifo_name_info_srv_to_cli);
printf("fim\n");
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_INPUT_LENGTH 100
#define PID_BUFFER_LEN 10
#define FIFO_NAME_CMD_CLI_TO_SRV "lrc_cmd_cli_to_srv"
#define FIFO_NAME_INFO_SRV_TO_CLI "lrc_info_srv_to_cli"
#define FIFO_NAME_MSG_SRV_TO_CLI "lrc_msg_srv_to_cli"
#define COMMAND_MAX_LEN 100
#define FIFO_DIR "/tmp/"
typedef enum { false, true } bool;
char* nickname;
char* name;
char* email;
void write_to_fifo(int fd, char* data)
{
int n_bytes = (strlen(data)+1) * sizeof(char);
write(fd, &n_bytes, sizeof(int)); //primeiro envia o numero de bytes que a proxima instrucao write ira enviar
write(fd, data, n_bytes);
printf("writing %d bytes '%s'\n", n_bytes, data);
}
void read_from_fifo(int fd, char** var)
{
int n_bytes;
read(fd, &n_bytes, sizeof(int));
*var = (char *) malloc (n_bytes);
printf("read '%s'\n", *var);
read(fd, *var, n_bytes);
}
int main(int argc, char* argv[])
{
pid_t pid = getpid();
//CRIA FIFO INFO_SRV_TO_CLIXXX
char pid_string[PID_BUFFER_LEN];
sprintf(pid_string, "%d", pid);
char* fifo_name_info_srv_to_cli;
fifo_name_info_srv_to_cli = (char *) malloc ( (strlen(FIFO_DIR) + strlen(FIFO_NAME_INFO_SRV_TO_CLI) + strlen(pid_string) + 1 ) * sizeof(char) );
strcpy(fifo_name_info_srv_to_cli, FIFO_DIR);
strcat(fifo_name_info_srv_to_cli, FIFO_NAME_INFO_SRV_TO_CLI);
strcat(fifo_name_info_srv_to_cli, pid_string);
int n = mkfifo(fifo_name_info_srv_to_cli, 0660);
if (n < 0)
{
fprintf(stderr, "error creating %s\n", fifo_name_info_srv_to_cli);
fprintf(stderr, "errno: %d\n", errno);
exit(6);
}
int fd_cmd_cli_to_srv, fd_info_srv_to_cli;
fd_cmd_cli_to_srv = open("/tmp/lrc_cmd_cli_to_srv", O_WRONLY);
char command[COMMAND_MAX_LEN];
printf("> ");
scanf("%s", command);
while (strcmp(command, "/CONNECT"))
{
printf("O primeiro comando deverá ser \"/CONNECT\"\n");
printf("> ");
scanf("%s", command);
}
//CRIA FIFO MSG_SRV_TO_CLIXXX
char* fifo_name_msg_srv_to_cli;
fifo_name_msg_srv_to_cli = (char *) malloc ( (strlen(FIFO_DIR) + strlen(FIFO_NAME_MSG_SRV_TO_CLI) + strlen(pid_string) + 1) * sizeof(char) );
strcpy(fifo_name_msg_srv_to_cli, FIFO_DIR);
strcat(fifo_name_msg_srv_to_cli, FIFO_NAME_MSG_SRV_TO_CLI);
strcat(fifo_name_msg_srv_to_cli, pid_string);
n = mkfifo(fifo_name_msg_srv_to_cli, 0660);
if (n < 0)
{
fprintf(stderr, "error creating %s\n", fifo_name_info_srv_to_cli);
fprintf(stderr, "errno: %d\n", errno);
exit(7);
}
// ENVIA COMANDO /CONNECT
write_to_fifo(fd_cmd_cli_to_srv, pid_string); //envia pid do processo cliente
write_to_fifo(fd_cmd_cli_to_srv, command); //envia commando /CONNECT
write_to_fifo(fd_cmd_cli_to_srv, fifo_name_info_srv_to_cli); //envia nome de fifo INFO_SRV_TO_CLIXXX
write_to_fifo(fd_cmd_cli_to_srv, fifo_name_msg_srv_to_cli); //envia nome de fifo MSG_TO_SRV_TO_CLIXXX
// recebe do servidor a resposta ao comanddo /CONNECT
printf("msg1\n");
printf("vamos tentar abrir %s\n", fifo_name_info_srv_to_cli);
fd_info_srv_to_cli = open(fifo_name_info_srv_to_cli, O_RDONLY);
printf("%s aberto", fifo_name_info_srv_to_cli);
if (fd_info_srv_to_cli < 0) {
fprintf(stderr, "erro ao criar %s\n", fifo_name_info_srv_to_cli);
fprintf(stderr, "errno: %d\n", errno);
}
printf("msg2\n");
char* fifo_name_msg_cli_to_srv;
printf("msg3\n");
read_from_fifo(fd_info_srv_to_cli, &fifo_name_msg_cli_to_srv);
printf("msg4\n");
free(nickname);
free(name);
free(email);
free(fifo_name_info_srv_to_cli);
free(fifo_name_msg_srv_to_cli);
unlink(fifo_name_msg_srv_to_cli);
unlink(fifo_name_info_srv_to_cli);
printf("fim\n");
return 0;
}
makefile:
CC = gcc
CFLAGS = -Wall -lpthread -fno-stack-protector
all: client server
client: client.c
$(CC) $(CFLAGS) client.c -o client
server: server.c
$(CC) $(CFLAGS) server.c -o server
clean:
rm -f client server *~