Linux C programing - c

Its the 1st time im making a question here , so i hope im not making any mistakes...
Im doing a server-client program and i have this error when i run client, i have "core dumped error".
I think i know where is the error but i dont know how to solve it.
I have 2 structs :
typedef struct {
int pid;
int cmd; //1 -login,2-registrar,3-tecla
char login[100];
char pw[100];
int tecla;
} PEDIDO;
typedef struct {
int cmd;
int res;
BONECO *b;
} RESPOSTA;
Code when server sends data to client through a named pipe :
int main(int argc, char *argv[], char *envp[]){
//...
i = read(fd, &p, sizeof (p));
printf(">>> Li %d bytes\n", i);
printf("User : %s PID : %d\n", p.login, p.pid);
if (p.cmd == 1) { //LOGIN
char user_fd[100], pw_fd[100];
FILE *f = fopen(argv[1], "r");
if (!f) {
printf("Erro ao abrir ficheiro\n");
exit(0);
}
while ((fscanf(f, "%s %s ", user_fd, pw_fd))) {
if (strcmp(p.login, user_fd) == 0 && strcmp(p.pw,pw_fd) == 0) {
printf("\nLOGIN CORRECTO!!!\n");
for (i = 0; i < 20; i++) {
if (clientes[i][0] != p.pid && clientes[i][0] == -1) {
clientes[i][0] = p.pid;
break;
}
}
sprintf(cli_fifo, "ccc%d", p.pid);
fd_resp = open(cli_fifo, O_WRONLY);
r.cmd = 1;
r.res = 1;
i = write(fd_resp, &r, sizeof (r));
close(fd_resp);
fclose(f);
break;
}
//...
}
Code of client to receive data from server :
void *recebe_msg(void *dados) {
int i;
sprintf(cli_fifo, "ccc%d", getpid());
mkfifo(cli_fifo, 0600);
fd_resp = open(cli_fifo, O_RDWR);
menu();
do {
i = read(fd_resp, &r, sizeof (r));
if (ESTADO == 0) {
if (r.cmd == 1 && r.res == 1) { // OK
ESTADO = 1;
wclear(win);
mvwprintw(win, 10, 14, "Login efectuado com sucesso!");
wprintw(win, "BONECO %d, %d , %d , %d ",r.b[0].num,r.b[0].humano,r.b[0].remate,r.b[0].tempo);
wrefresh(win);
sleep(3);
desenha_campo();
}
if (r.cmd == 1 && r.res == 0) { // NOK
wclear(win);
mvwprintw(win, 10, 14, "Senha e/ou login incorrectos!!!");
wrefresh(win);
sleep(3);
menu();
}
if (r.cmd == 2 && r.res == 0) {
wclear(win);
mvwprintw(win, 10, 14, "Login já está em uso!");
wrefresh(win);
sleep(3);
menu();
}
if (r.cmd == 2 && r.res == 1) {
wclear(win);
mvwprintw(win, 10, 14, "Registo efectuado com sucesso!");
wrefresh(win);
sleep(3);
menu();
}
if (r.cmd == 9) { // sair
FIM = 1;
}
} else if (ESTADO == 1 || ESTADO == 2) {
wclear(win3);
scrollok(win3, TRUE);
keypad(win3, TRUE);
noecho();
if (r.cmd == 3) { // actualizacao de jogadores
desenha_campo();
desenha_jogadores();
} else if (r.cmd == 9) { // sair
FIM = 1;
}
}
} while (!FIM);
close(fd_resp);
unlink(cli_fifo);
pthread_exit(0);
}
OBS: I think the error is on the 3rd field of struct RESPOSTA, but i dont know how to solve it

Here you read BONECO structure:
i = read(fd_resp, &r, sizeof (r));
Please note, BONECO is declared as pointer, NOT ACTUAL DATA.
But here you try to read this data:
wprintw(win, "BONECO %d, %d , %d , %d ",r.b[0].num,r.b[0].humano,r.b[0].remate,r.b[0].tempo);
While you try to access r.b[0], you get segmentation fault, as you try to dereference b pointer, which point to... Unknown location. This cause error just as planned.
I suggest to modify your struct to:
typedef struct {
int cmd;
int res;
int count_of_boneco;
BONECO b[];
} RESPOSTA;
If you allocate sufficiently large buffer, you can read all your data and then dereference at you do it now.

Related

fgets doesn't wait for input in parent process but it does in the child one

This is an external function that sets environment variables
int mini_read(char ** variables){
if(variables[1] == NULL){
fprintf(stderr, "error\n");
return 1;
}
char buf[100];
fgets(buf, 100, stdin);
//I doubt the bug is below here
buf[strcspn(buf, "\n")] = 0;
char ** valores = NULL;
char * valor = strtok(buf, " \t");
valores[0] = valor;
int i = 1;
// Guardar valores en array
while(valor != NULL){
valor = strtok(NULL, " \t");
valores[i] = valor;
i++;
}
for(int i = 1; ; i++){
if(valores[i-1] == NULL) break;
//printf("variables[%d]: %s\n valor[%d]: %c\n", i, variables[i], i, valor[i]);
if(variables[i] == NULL){
char*fin = NULL;
//Si hay más valores que variables, concatenar valores
for(int j = i-1; valores[j] != NULL; j++){
printf("%s\n", fin);
strcat(fin, valores[j]);
}
printf("%s\n", fin);
setenv(variables[i-1], fin, 1);
break;
}
setenv(variables[i], valores[i-1], 1);
}
return 0;
Then I want to call the function in the parent process because if I call it from the child process the environment variables don't get set "globally".
If I call it from the child process it works just fine; however, if I call it from the parent process, fgets() doesn't wait for input.
int main(void){
pid = fork();
if(pid == 0){
//Option 1
if(strcmp(argv[0], "read") == 0) mini_read(argv);
}
else{
//Option 2
if(strcmp(argv[0], "read") == 0) mini_read(argv);
waitpid(pid, &wstatus, 0);
}
}

Tcp server client Connection issue in C

so i am trying to implement a TCP server-client(s) using server ip and port. Connection between the two was established, with the use of threads.
Now i'm expecting the program to: for everytime a client joins or leave, if there are other clients present, then it will print "Client has joined/left the server" on these other clients screen. However if it is the only client present, it won't say the join or leave stuff and will proceed with asking user an input of what does the client wants to do.(user input is what the client has typed after this arrow ">")
What it is actually doing: When the first client has successfully joined the server, the command line remains empty, the ">" does not appear and even if you can type, no input is recorded by the client. As you connect a second client, that's when the arrow appears on the first client only and you can start inputting.
I would like to know which part i should edit to make my client when alone to start taking input without needing another client to join before doing so + When there are multiple clients and a client joins/leave, on the other clients' screen is printed "Client has joined/left the server"
Server code
void client_queuing(client_thr *cl){
pthread_mutex_lock(&cli_mutex);
for(int i=0; i < MAXLINE; ++i){
if(!cli[i]){
cli[i] = cl;
break;
}
}
pthread_mutex_unlock(&cli_mutex);
}
void client_removal(int uid){
pthread_mutex_lock(&cli_mutex);
for(int i=0; i < MAXLINE; ++i){
if(cli[i]){
if(cli[i]->uid == uid){
cli[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&cli_mutex);
}
void convey_msg(char *st, int uid){
pthread_mutex_lock(&cli_mutex);
for(int i=0; i<MAXLINE; ++i){
if(cli[i]){
if(cli[i]->uid != uid){
if(write(cli[i]->sockfd, st, strlen(st)) < 0){
perror("ERROR: Failure to write to descriptor");
break;
}
}
}
}
pthread_mutex_unlock(&cli_mutex);
}
void *man_cli(void *arg){
char buffer_o[SIZEOF_BUFFER];
char nickname[20];
int leave_flag = 0;
num_client++;
client_thr *clice = (client_thr *)arg;
// nickname
if(recv(clice->sockfd, nickname, 20, 0) <= 0 || strlen(nickname) >= 19){
printf("Name not Entered.\n");
leave_flag = 1;
}
else{
strcpy(cli->nickname, nickname);
sprintf(buffer_o, "A new user %s has joined SNC!\n", cli->nickname);
printf("%s", buffer_o);
convey_msg(buffer_o, clice->uid);
}
bzero(buffer_o, SIZEOF_BUFFER);
while(1){
if (leave_flag) {
break;
}
int receive = recv(clice->sockfd, buffer_o, SIZEOF_BUFFER, 0);
if (receive > 0){
if(strlen(buffer_o) > 0){
convey_msg(buffer_o, clice->uid);
array_trimming(buffer_o, strlen(buffer_o));
printf("%s -> %s\n", buffer_o, clice->nickname);
//printf("%s\n", buffer_o);
}
}
else if (receive == 0 || strcmp(buffer_o, "quit") == 0){
sprintf(buffer_o, "Server: %s has stopped chatting.\n", clice->nickname);
printf("%s", buffer_o);
convey_msg(buffer_o, clice->uid);
//trial
//strcpy(buffer_o, clice->nickname);
send(clice->sockfd, buffer_o, strlen(buffer_o)+1,0);
leave_flag = 1;
}
/* else {
printf("Error is -1\n");
leave_flag = 1;
} */
bzero(buffer_o, SIZEOF_BUFFER);
}
/* Delete client from queue and yield thread */
close(clice->sockfd);
client_removal(clice->uid);
free(clice);
num_client--;
pthread_detach(pthread_self());
return NULL;
}
client code
void handle_message_convey() {
char message[LENGTH] = {};
char buff[LENGTH + 20] = {};
while(1) {
flush_stdout();
fgets(message, LENGTH, stdin);
array_trimming(message, LENGTH);
if (strcmp(message, "quit") == 0) {
break;
}
else {
sprintf(buff, "%s: %s\n", nickname, message);
send(sockfd, buffer, strlen(buff), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 20);
}
quit_with_catch_ctrl_c(2);
}
void handle_message_recv() {
char message[LENGTH] = {};
while (1) {
int message_rcv = recv(sockfd, message, LEN, 0);
if (message_rcv > 0) {
printf("%s", message);
flush_stdout();
}
else if (message_rcv == 0) {
break;
}
else {
// nothing happens = -1
}
memset(message, 0, sizeof(message));
}
}
int main(){
recv(sock_fd, buffer_o, sizeof(buffer_o), 0);
//printf("%s \n", buffer_o);
pthread_t message_sending_thr;
if(pthread_create(&message_sending_thr, NULL, (void* ) handle_message_convey, NULL) != 0) {
printf("Error with pthread:");
}
//printf("Hello, Welcome!");
pthread_t message_del_thr;
if(pthread_create(&message_del_thr, NULL, (void *)handle_message_recv, NULL) != 0){
printf("Error with pthread");
}
}

What's the best way for a process to know when another one is terminated?

I am coding in C and I wanted to know if there is a way another process can know if another one terminated via threads or named pipes, or would it be better with signals? What is the best way do to that?
More info: I am not working with sockets. Only fifos and threads. I have one process that is the server. Another the client. And when the server shutdown I wanted the client to know it and shutdown too. Thanks
Some parts are in portuguese. I hope you can understand the context :/
util.h
#define FIFO_SERV "cli.txt"
typedef struct{
char u[10], pass[10];
char op;
int pid;
int acesso;
//int FIM;
} PEDIDO;
servidor.c - server file
#include "util.h"
int main(int argc, char *argv[]) {
FILE *f_dados;
int fd, fd_resp, i;
char cmd[20], user[10], pwd[10], users[100], str[80];
PEDIDO p;
fd_set conj;
struct timeval tempo;
int ret;
mkfifo(FIFO_SERV, 0600);
fd = open(FIFO_SERV, O_RDWR); //vai ler para escrever
printf("Servidor iniciado...\n");
f_dados = fopen(argv[1], "w+");
do{
FD_ZERO(&conj);
FD_SET(0 ,&conj); //ATENCAO AO TECLADO!
FD_SET(fd, &conj); //ATENCAO AO FIFO!
tempo.tv_sec = 1; //ESPERA 1.5 SEGUNDOS
tempo.tv_usec = 50000;
ret = select(fd+1, &conj, NULL, NULL, &tempo);
if(ret > 0){ //existem dados
if(FD_ISSET(0, &conj)){ // ... no teclado!
scanf("%s", cmd);
if(strcmp(cmd, "user") == 0){
f_dados = fopen(argv[1], "a+");
if (f_dados == NULL)
{
printf("NÃO FOI POSSIVEL A ABERTURA DO FICH.\n");
return 1;
}
scanf("%s %s", user, pwd);
fprintf(f_dados, "%s %s\n", user, pwd);
printf("\t#user adicionado\n");
fclose(f_dados);
}
else if(strcmp(cmd, "users") == 0){
f_dados = fopen(argv[1], "r+");
if (f_dados == NULL)
{
printf("NÃO FOI POSSIVEL A ABERTURA DO FICH.\n");
return 1;
}
while(fgets(users, 100, f_dados)) {
printf(">%s\n", users);
}
}
else if(strcmp(cmd, "sair") == 0){
break;
}
else{
printf("\tComando inválido.\n\n");
}
}
if(FD_ISSET(fd, &conj)){ // ... no fifo!
i = read(fd, &p, sizeof(p));
if(i==sizeof(p)){
printf("Recebi um pedido...");
printf("Pedido: %s %s {%d}\n", p.u, p.pass, p.pid);
autenticacao(f_dados, &p);
//ENVIAR RESPOSTA...
sprintf(str, "cli%d", p.pid);
fd_resp = open(str, O_WRONLY);
i = write(fd_resp, &p, sizeof(p));
close(fd_resp);
printf("Enviei a resposta...\n");
}
}
}
}while(strcmp(cmd, "sair") != 0);
close(fd);
fclose(f_dados);
printf("Vou terminar!\n");
unlink(FIFO_SERV);
}
return(0);
}
cliente.c - client file
#include "util.h"
int main(void) {
int fd, i, fd_resp, res;
char str[80]; //buffer para guardar dados
PEDIDO p;
if (access(FIFO_SERV, F_OK) != 0){
printf("O servidor nao esta a correr!\n");
return 1;
}
p.pid = getpid();
sprintf(str, "cli%d", p.pid);
mkfifo(str, 0600);
fd = open(FIFO_SERV, O_WRONLY);
do{
//INTERFACE
printf("\nLogin: ");
scanf("%s", p.u);
printf("Password: ");
scanf("%s", p.pass);
// printf("\nPEDIDO: %s - %s\n", p.u, p.pass);
//INTERFACE... ainda falta
i = write(fd, &p, sizeof(p));
printf("\nPedido enviado...");
//RECEBE RESPOSTA...
fd_resp = open(str, O_RDONLY);
i = read(fd_resp, &p, sizeof(p));
close(fd_resp);
printf("Recebi a resposta... {%d}\n", p.acesso);
if(p.acesso == 0){
printf("\n\t[Não autenticado.]\n");
}
else if(p.acesso == 1){
printf("\n\t[Autenticado.]\n");
}
}while(!p.acesso && strcmp(p.u, ".") != 0);
close(fd);
unlink(str);
return(0);
}

Unable to receive data with libusb

I want to send and receive data from device to pc and vice versa. I am sending the string, but not able to receive it fully. Example: Sent string is Hello, and the output is:
Received:H
Error in read! e = -4 and received = 5
#include <string.h>
#include<stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#define BULK_EP_OUT 0x01
#define BULK_EP_IN 0x81
/*find these values using lsusb -v*/
uint16_t VENDOR = 0x0483;
uint16_t PRODUCT = 0x5740;
int main(void)
{
int ret = 1; //int type result
struct libusb_device **usb_dev;
struct libusb_device_descriptor desc;
struct libusb_device_handle *handle = NULL;
struct device_handle_expected;
//struct libusb_device_handle device_expected_handle = NULL;
struct libusb_device *dev, *dev_expected;
char *my_string, *my_string1;
int e = 0, config;
char found = 0;
int transferred = 0;
int received = 0;
int length = 0;
int i=0;
int count;
/*struct libusb_device *dev;
struct libusb_device **devs;
struct dev_expected;*/
// Initialize libusb
ret = libusb_init(NULL);
if(ret < 0)
{
printf("\nFailed to initialise libusb\n");
return 1;
}
else
printf("\nInit successful!\n");
// Get a list of USB devices
count = libusb_get_device_list(NULL, &usb_dev);
if (count < 0)
{
printf("\nThere are no USB devices on the bus\n");
return -1;
}
printf("\nToally we have %d devices\n", count);
while ((dev = usb_dev[i++]) != NULL)
{
ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0)
{
printf("Failed to get device descriptor\n");
libusb_free_device_list(dev, 1);
break;
}
e = libusb_open(dev, &handle);
if (e < 0)
{
printf("Error opening device\n");
libusb_free_device_list(dev, 1);
libusb_close(handle);
break;
}
if(desc.idVendor == 0x0483 && desc.idProduct == 0x5740)
{
found = 1;
break;
}
}//end of while
if(found == 0)
{
printf("\nDevice NOT found\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return 1;
}
else
{
printf("\nDevice found");
// dev_expected = dev;
//device_handle_expected = handle;
}
e = libusb_get_configuration(handle, &config);
if(e!=0)
{
printf("\n***Error in libusb_get_configuration\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
printf("\nConfigured value: %d", config);
if(config != 1)
{
libusb_set_configuration(handle, 1);
if(e!=0)
{
printf("Error in libusb_set_configuration\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
else
printf("\nDevice is in configured state!");
}
if(libusb_kernel_driver_active(handle, 0) == 1)
{
printf("\nKernel Driver Active");
if(libusb_detach_kernel_driver(handle, 0) == 0)
printf("\nKernel Driver Detached!");
else
{
printf("\nCouldn't detach kernel driver!\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
}
e = libusb_claim_interface(handle, 0);
if(e < 0)
{
printf("\nCannot Claim Interface");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
else
printf("\nClaimed Interface\n");
int nbytes = 64;
my_string = (char *) malloc(nbytes + 1);
my_string1 = (char *) malloc(nbytes + 1);
memset(my_string, '\0', 64);//The C library function void (an unsigned char) to the first n characters of the string pointed to, by the argument str.
memset(my_string1, '\0', 64);
strcpy(my_string, "Hello");
length = strlen(my_string);
printf("\nTo be sent: %s", my_string);
e = libusb_bulk_transfer(handle, BULK_EP_OUT, my_string, length, &transferred, 0);
if(e == 0 && transferred == length)
{
printf("\nWrite successful!");
printf("\nSent %d bytes with string: %s\n", transferred, my_string);
}
else
printf("\nError in write! e = %d and transferred = %d\n", e, transferred);
// sleep(3);
i = 0;
for(i = 0; i <= length; i++)
{
e = libusb_bulk_transfer(handle, BULK_EP_IN, my_string1,length, &received, 0); //64: Max Packet Length
if(e == 0 && received == length)
{
printf("\nReceived:");
printf("%c", my_string1[i]);
sleep(5);
}
else
{
printf("\nError in read! e = %d and received = %d bytes\n", e, received);
return -1;
}
}
libusb_release_interface(handle, 0);
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
libusb_exit(NULL);
printf("\n");
return 0;
}
Pretty certain the bulk in transfer will transfer the entire buffer at once(up to 64--or 512 if you're doing high speed--bytes), not a byte at a time.
You're iterating over the size of the expected buffer and doing a bulk in for each byte, and only printing out the first byte.
Get rid of the for loop on the read and change your printf() to be printf("%s\n",my_string1);

2 way communication between with fork and pipe

I'm trying to get 2 way communication between a main file and a helper file.
The main file forks, and the child does some pipe work and then runs an exec.
My problem is that I can send information from the child exec to the parent exec, but not the other way around.
Below Is my entire code from the two files, so you should be able to run it.
Any help in getting the 2 way communication working will be extremely helpful. i'm been at this for almost 8 hours straight now.
When you run it, you'll see it print out "yo 0". This was me testing that it takes an integer from the main file, sends it to the helper, adds yo in front of it and sends it back. The first slab of code is the main file, second is the helper, third is the map file needed to run it. make sure there isn't a blank line underneath the last line, and the fourth is the agent file needed to run it.
the running is [./handler mapfile 20 agentfile.]
the int 20 doesn't do anything yet, but you need it in there to run the file.
If anyone actually goes to the effort to do all this and help me, i am eternally grateful
main file (handler.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
enum ErrorCode {
SHOW_USAGE = 1, BAD_STEPS, OPEN_MAP_ERROR, CORRUPT_MAP,
OPEN_AGENT_ERROR, CORRUPT_AGENTS, AGENT_ERROR,
AGENT_WALLED, AGENT_COLLIDED, TOO_MANY_STEPS, INVALID_AGENT_RESPONSE,
AGENT_CLOSED, AGENT_DIED, SIGINT_REC
};
typedef struct {
int valid;
int row, col;
} Point;
typedef struct {
Point point;
int number;
char name;
char param[20];
char type[20];
} Agent;
typedef struct {
int rows, cols;
char **grid;
} Map;
Map map;
Map agentMap;
int listSize = 0;
void error(enum ErrorCode e) {
switch(e) {
case SHOW_USAGE:
fprintf(stderr, "Usage: handler mapfile maxsteps agentfile\n");
break;
case BAD_STEPS:
fprintf(stderr, "Invalid maxsteps.\n");
break;
case OPEN_MAP_ERROR:
fprintf(stderr, "Unable to open map file.\n");
break;
case CORRUPT_MAP:
fprintf(stderr, "Corrupt map.\n");
break;
case OPEN_AGENT_ERROR:
fprintf(stderr, "Unable to open agent file.\n");
break;
case CORRUPT_AGENTS:
fprintf(stderr, "Corrupt agents.\n");
break;
case AGENT_ERROR:
fprintf(stderr, "Error running agent.\n");
break;
case AGENT_WALLED:
fprintf(stderr, "Agent walled.\n"); // needs fixing, check spec sheet
break;
case AGENT_COLLIDED:
fprintf(stderr, "Agent collided.\n"); // same as AGENT_WALLED
break;
case TOO_MANY_STEPS:
fprintf(stderr, "Too many steps.\n");
break;
case INVALID_AGENT_RESPONSE:
fprintf(stderr, "Agent sent invalid response.\n"); // fixiing
break;
case AGENT_CLOSED:
fprintf(stderr, "Agent exited with status.\n"); // fixiing
break;
case AGENT_DIED:
fprintf(stderr, "Agent exited due to signal.\n"); // fixing
break;
case SIGINT_REC:
fprintf(stderr, "Exiting due to INT signal.\n");
break;
}
exit(e);
}
void print_map(Map map)
{
int r;
for (r = 0; r < map.rows; ++r) {
printf("%s", map.grid[r]);
}
puts("");
}
void print_agents(Agent *agents, int size)
{
int i;
for (i = 0; i < size; i++) {
Agent temp = agents[i];
printf("%d %d %c %d %s %s %i\n", temp.point.row, temp.point.col, temp.name, temp.number, temp.type, temp.param, i);
}
puts("");
}
void readMap(char *file)
{
int r;
FILE *fd = fopen(file, "r");
char buffer[20];
char d;
if (!fd) {
error(OPEN_MAP_ERROR);
}
if (fgets(buffer, 20, fd) == NULL) {
error(CORRUPT_MAP);
}
if (sscanf(buffer, "%d %d%1[^\n]\n", &map.rows, &map.cols, &d) != 2 ||
map.rows < 1 || map.rows > 999 || map.cols < 1 || map.cols > 999) {
error(CORRUPT_MAP);
}
map.grid = malloc(map.rows * sizeof(char *));
for (r = 0; r < map.rows; ++r) {
map.grid[r] = calloc(map.cols + 2, sizeof(char));
if (fgets(map.grid[r], map.cols + 2, fd) == NULL ||
map.grid[r][map.cols] != '\n') {
error(CORRUPT_MAP);
}
}
fclose(fd);
}
void checkAgent(char *file)
{
FILE *fd = fopen(file, "r");
if (!fd) {
error(AGENT_ERROR);
}
fclose(fd);
}
int growList (Agent **agentList, int curSize, int increaseNum)
{
const int newSize = curSize + increaseNum;
Agent *temp = (Agent*) realloc(*agentList, (newSize * sizeof(Agent)));
if (temp == NULL) {
exit(20);
}
else {
*agentList = temp;
return newSize;
}
}
Agent* readAgentFile(char *file, Agent *agentList)
{
int readCount = 0;
FILE *fp = fopen(file, "r");
char buffer[80];
listSize = 0;
if (!fp) {
error(OPEN_AGENT_ERROR);
}
if (fgets(buffer, 80, fp) == NULL) {
error(CORRUPT_AGENTS);
}
rewind(fp);
while (fgets(buffer, 80, fp) != NULL) {
if (buffer[0] != '#') {
Agent agent;
sscanf( buffer, "%d %d %c %s %s" ,&agent.point.row, &agent.point.col, &agent.name, agent.type, agent.param);
checkAgent(agent.type);
agent.number = readCount+1;
listSize = growList(&agentList, listSize, 1);
agentList[readCount] = agent;
readCount++;
}
}
if (readCount == 0) {
error(CORRUPT_AGENTS);
}
fclose(fp);
return agentList;
}
void createAgentMap()
{
int i,j;
agentMap = map;
for (i=0; i < map.rows; i++) {
for (j=0; j < map.cols; j++) {
char c = map.grid[i][j];
if (c == '.') {
agentMap.grid[i][j] = ' ';
}
}
}
}
int main(int argc, char **argv)
{
int steps;
int pid;
int returnStatus;
int i;
int out_pipe[2];
int in_pipe[2];
char ch[20];
Agent firstAgent;
Agent *agentList =(Agent *) calloc(1, sizeof(Agent));
if (argc != 4) {
error(SHOW_USAGE);
}
sscanf(argv[2], "%d", &steps);
if ((steps < 1)) {
error(BAD_STEPS);
}
readMap(argv[1]);
agentList = readAgentFile(argv[3], agentList);
firstAgent = agentList[0];
createAgentMap();
for (i=0; i < listSize; i++) {
if (pipe(out_pipe) < 0) {
perror("Pipe Error");
}
if (pipe(in_pipe) < 0) {
perror("Child pipe error");
}
Agent temp;
temp = agentList[i];
switch ( pid = fork() )
{
case -1:
perror("Can't fork.\n");
exit(20);
case 0:
/* Child */
/*close(1);
dup(in_pipe[1]);
close(0);
dup(out_pipe[0]);
close(in_pipe[0]);
close(out_pipe[1]);*/
dup2(out_pipe[0], 0);
dup2(in_pipe[1], 1);
execlp(temp.type, temp.type, temp.param, (char *)0);
perror("No exec");
default:
//close(1);
//dup(handlerChild[1]);
//fprintf(stdout, "%d", listSize);
write(out_pipe[1], "%d", listSize);
close(in_pipe[1]);
close(0);
dup(in_pipe[0]);
if (fgets(ch, 20, stdin) == NULL) {
break;
}
printf("%s\n", ch);
}
}
while (steps > 0) {
steps -= 1;
}
return 0;
}
helper file (simple.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct {
int valid;
int row, col;
} Point;
typedef struct {
int numAgents;
char agentNames[80];
int agentNumber;
} Info;
typedef struct {
int rows, cols;
char **grid;
} Map;
Map agent_map;
int main(int argc, char **argv)
{
int steps = 10;
int simple_pipe[2];
int dir;
char inputDir;
char input_stream[20];
int in = dup(0);
Info info;
if (argc == 2) {
sscanf(argv[1], "%c1", &inputDir);
switch (inputDir) {
case 'N': dir = 0; break;
case 'E': dir = 1; break;
case 'S': dir = 2; break;
case 'W': dir = 3; break;
default : fprintf(stdout, "Invalid params.\n"); exit(2);
}
}
else {
fprintf(stdout, "Incorrect number of params.\n");
exit(1);
}
close(0);
dup(simple_pipe[0]);
fgets(input_stream, 20, stdin);
sscanf(input_stream, "%d", &info.numAgents);
//printf("%d", info.numAgents);
//printf("this is the input: %s\n", input_stream); // This is successfully printing to stdout in the pipe
fprintf(stderr, "yo %d \n", info.numAgents);
while (steps > 0) {
steps -= 1;
}
exit(0);
}
map file
6 6
##..##
#....#
#.##.#
#....#
##....
######
agent file
1 1 A ./simple E
2 2 B ./simple N
5 2 C ./simple S
A pipe is a unidrectional connection across processes. Before you fork, you open the pipe and it will reserve two file descriptors, where fd[0] can be read from and fd[1] can be written to.
So when you want to have a two way commumincation you need to create two pipes, and then use one for reading in the parent writing in the child and the second pipe the other way around.
A more detailed explanation along with some sample code can be foun dhere: http://linux.die.net/man/2/pipe

Resources