Hello guys this is my first post here.
My problem is stupid I think but I can't find any solution, hope you can help me!
So, me and a friend are coding a small system monitor (learn better/fun), the code has 2 sections: the daemon and the command line interface (for now), when I compile the CLI section all went great, the daemon is particular one, because when I compile and I execute it in the compile directory it works without error! Magically, when I move out of the compile directory it gives me a segmentation fault!
Compiler: GCC
Here is the repository: https://github.com/StefanoBelli/JASM
Makefile:
#!/usr/bin/make -f
SHELL=/bin/sh
#### CONFIGURATION ####
CC=gcc
DEBUG=-g
CFLAGS=-O2 -pipe -Wall -std=c11 $(DEBUG)
LIBS=
BINOUT=jasm
#### SOURCES & RULES ####
OBJS:=$(patsubst %.c,%.o,$(wildcard *.c))
install:$(OBJS)
$(CC) $(CFLAGS) $(LIBS) -o $(BINOUT) $(OBJS)
clean:
rm -fv *.o
.PHONY: install,clean
GDB Output:
(gdb) run
Starting program: /home/stefanozzz123/Devel/C.Cpp/JASM/bin/jasm
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a7db04 in vfprintf () from /usr/lib/libc.so.6
(gdb)
Thank all of you guys! :)
EDIT: As you requested here is code:
jasm.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "queue.h"
#include "miscellaneous.h"
#include "ipc.h"
int main(int argc, char *argv[])
{
start_daemon();
start_server();
}
ipc.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "ipc.h"
#include "miscellaneous.h"
#include "getter.h"
static void excecute_command(int fd, char *command)
{
/*
* if get* -> modulo get
* if start* -> modulo dei moduli
*/
// ************************** getter ***************************************
if(strncmp("get", command, 3)==0) { //ricevuto comando getter
int i;
//char buf[BUFSIZ];
strcpy(command, &command[3]);
for(i=0; i<NGETTER; i++) {
if(strcmp(getterName[i], command)==0) { //se esiste getter
log_string("getter found :)");
getterFunction[i](fd);
return;
}
}
log_error("getter NOT found :(");
write(fd, "null\0", 4);
return;
}
// ************************** starter **************************************
if(strncmp("start", command, 5)==0) { //ricevuto start modulo
log_error("starter NOT found :(");
write(fd, "null\0", 4);
return;
}
// ************************** miscellaneous ********************************
if(strcmp("halt", command)==0) { //spegne jasm
log_string("# halt and catch fire, done");
write(fd, "halt\0", 4);
exit(0);
}
/*if(strcmp("getVersion", command)==0) {
write(fd, (void *)VERSION, sizeof(VERSION));
log_string("server reply <version> with success");
return;
}*/
log_error("request not found");
write(fd, "null\0", 4);
}
void start_server()
{
int server_sockfd, client_sockfd;
int server_len;
socklen_t client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int result;
fd_set readfds, testfds;
server_sockfd=socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family=AF_INET;
server_address.sin_addr.s_addr=htonl(INADDR_ANY);
server_address.sin_port=htons(SERVER_PORT);
server_len=sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
log_string("server started");
while(1) {
char buf[BUFSIZ];
char received[BUFSIZ];
int fd;
int nread;
testfds=readfds;
result=select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
if(result<1) {
log_error("server fail");
exit(1);
}
for(fd=0; fd<FD_SETSIZE; fd++) {
if(FD_ISSET(fd, &testfds)) {
if(fd==server_sockfd) {
client_len=sizeof(client_address);
client_sockfd=accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
FD_SET(client_sockfd, &readfds);
sprintf(buf, "adding client on fd %d", client_sockfd);
log_string(buf);
} else {
ioctl(fd, FIONREAD, &nread);
if(nread==0) {
close(fd);
FD_CLR(fd, &readfds);
sprintf(buf, "removing client on fd %d", fd);
log_string(buf);
} else {
read(fd, &received, BUFSIZ);
sprintf(buf, "received from fd %d command <%s>", fd, received);
log_string(buf);
excecute_command(fd, received);
}
}
}
}
}
}
miscellanous.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "miscellaneous.h"
char * getTime()
{
time_t curtime;
struct tm *loctime;
static char *ret;
curtime=time(NULL);
loctime=localtime(&curtime);
ret=asctime(loctime);
ret[24]='\0';
return ret;
}
void log_string(const char *message)
{
FILE *fp;
fp=fopen(LOGPATH, "a+");
fprintf(fp, "[%s] %s\n", getTime(), message);
fclose(fp);
}
void log_error(const char *message)
{
FILE *fp;
fp=fopen(LOGPATH, "a+");
fprintf(fp, "[%s] ERROR: %s!\n", getTime(), message);
fclose(fp);
}
void start_daemon()
{
pid_t pid;
char buf[BUFSIZ];
log_string("boot");
pid=fork();
switch(pid) {
case -1:
log_error("fork fail");
exit(1);
break;
case 0:
log_string("fork success");
break;
default:
exit(0);
break;
}
if(setsid()<0) {
log_error("setsid fail");
exit(1);
} else {
log_string("setsid success");
}
//chiude i file descriptor di stdin, stdout, stderr
close(0);
close(1);
close(2);
sprintf(buf, "jasm started with pid %d and ppid %d", getpid(), getppid());
log_string(buf);
}
Essentially these are main srcs...
GDB Backtrace says nothing as the program run stops immediately
Since the question was tagged gdb, let's see how gdb can help. In my case, I've installed the debuginfo files for libc, so that I can examine the arguments to C library functions, but you don't really need that in this case because we can find the bug by looking at the user's source code.
(gdb) run
Starting program: ./jasm
Program received signal SIGSEGV, Segmentation fault.
_IO_vfprintf_internal (s=0x0, format=0x4019b1 "[%s] %s\n",
ap=ap#entry=0x7fffffffbd38) at vfprintf.c:1295
1295 vfprintf.c: No such file or directory.
(gdb) bt
#0 _IO_vfprintf_internal (s=0x0, format=0x4019b1 "[%s] %s\n",
ap=ap#entry=0x7fffffffbd38) at vfprintf.c:1295
#1 0x00007ffff7a693f7 in __fprintf (stream=<optimized out>,
format=<optimized out>) at fprintf.c:32
#2 0x000000000040149d in log_string (message=0x4019cb "boot")
at miscellaneous.c:46
#3 0x000000000040151f in start_daemon () at miscellaneous.c:64
#4 0x0000000000401400 in main (argc=1, argv=0x7fffffffdf78) at jasm.c:31
The declaration for vfprintf is:
int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);
Even though we don't have the source code for vfprintf installed, we can see that the first argument passed to it, s, is a NULL stream pointer, and that is likely the cause of the seg fault.
Let's look at something we have source code for: frame 2, log_string.
(gdb) frame 2
#2 0x000000000040149d in log_string (message=0x4019cb "boot")
at miscellaneous.c:46
46 fprintf(fp, "[%s] %s\n", getTime(), message);
(gdb) print fp
$2 = (FILE *) 0x0
There it is.
#define LOGPATH "../../../../data/log/jasm.log"
void log_string(const char *message)
{
FILE *fp;
fp=fopen(LOGPATH, "a+");
fprintf(fp, "[%s] %s\n", getTime(), message);
fclose(fp);
}
void log_error(const char *message)
{
FILE *fp;
fp=fopen(LOGPATH, "a+");
fprintf(fp, "[%s] ERROR: %s!\n", getTime(), message);
fclose(fp);
}
Check the return value from fopen. It may be NULL depending on what directory the program is run from. It may be better to use an absolute pathname, possibly settable in the Makefile for portability.
write(fd, "halt\0", 4);
All of these should have a count of 5, to include the trailing NUL. (And it isn't absolutely necessary to explicitly include \0 in the string literal, because C string literals implicitly have a \0 at the end.)
Related
Here is a Synchronized Reader and Writer. The target is passing data between these two Processes via a Shared Memory.
The Writer opens a Shared Memory through a Structure and writes Some Data. I am getting Segmentation Fault(Core Dumped) error message.
The code is compiled through the following command in Ubuntu.
g++ Writer.c -o Writer -lrt
g++ Reader.c -o Reader -lrt
And these two Processes are run by-
./Writer
./Reader
The Writer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main(void){
struct MemData{
char* FileName;
int LastByteLength;
int ReadPointer;
int WritePointer;
char Data[512000];//MEMORY BLOCK SIZE: 500 KB
};
int SD;
struct MemData *M;
int NumberOfBuffers=10;
int BufferSize=51200;//FILE BUFFER SIZE 50 KB
SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
if(SD< 0){
printf("\nshm_open() error \n");
return EXIT_FAILURE;
}
fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO);
if(ftruncate(SD, sizeof(MemData))< 0){
printf ("ftruncate() error \n");
return EXIT_FAILURE;
}
//THE FOLLOWING TYPECASTING AVOIDS THE NEED TO ATTACH THROUGH shmat() in shm.h HEADER I GUESS.
M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
if(M== MAP_FAILED){
printf("mmap() error");
return EXIT_FAILURE;
}else{
M->FileName=(char*)"xaa";
M->LastByteLength=0;
M->ReadPointer=-1;
M->WritePointer=-1;
memset(M->Data, '\0', strlen(M->Data));
}
/*
FILE *FP= fopen(FileName, "rb");
if(FP!= NULL){
unsigned long int FilePosition;
fseek(FP, 0, SEEK_SET);
FilePosition=ftell(FP);
fclose(FP);
}
*/
close(SD);
return 0;
}
The Reader.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main(void){
struct MemData{
char* FileName;
int LastByteLength;
int ReadPointer;
int WritePointer;
char Data[512000];//MEMORY BLOCK SIZE: 500 KB
};
int SD;
struct MemData *M;
int NumberOfBuffers=10;
int BufferSize=51200;//FILE BUFFER SIZE 50 KB
SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
if(SD< 0){
printf("\nshm_open() error \n");
return EXIT_FAILURE;
}
fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO);
if(ftruncate(SD, sizeof(MemData))< 0){
printf ("ftruncate() error \n");
return EXIT_FAILURE;
}
//THE FOLLOWING TYPECASTING AVOIDS THE NEED TO ATTACH THROUGH shmat() in shm.h HEADER I GUESS.
M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
if(M== MAP_FAILED){
printf("mmap() error");
return EXIT_FAILURE;
}else{
printf("\n%s", M->FileName);
printf("\n%d", M->LastByteLength);
printf("\n%d", M->ReadPointer);
printf("\n%d", M->WritePointer);
}
/*
FILE *FP= fopen(FileName, "rb");
if(FP!= NULL){
unsigned long int FilePosition;
fseek(FP, 0, SEEK_SET);
FilePosition=ftell(FP);
fclose(FP);
}
*/
munmap(M,sizeof(MemData));
close(SD);
return 0;
}
Based on your comments, the issue is because of the way you're assigning and passing the FileName value.
M->FileName=(char*)"xaa";
This results in M->FileName holding a pointer to a string in the writer process' memory. Dereferencing this pointer in the reader process results in a segmentation fault due to the filename being stored in the writer process memory, which is not shared with the reader. You need to store the characters themselves in the shared memory, not a pointer to writer process memory.
If you can safely assume the maximum length of the filename string, you can change your struct to store the entire string rather than a pointer: change char* FileName; to char FileName[256]; or some other fixed length value. You will need to use strcpy rather than direct assignment after making this change: change M->FileName=(char*)"xaa"; to strcpy(M->FileName, "xaa");.
If you want a dynamic length string, you can call mmap again to allocate shared memory for just the string, and then store the pointer to this shared memory string in FileName.
we are trying to copy a binary/elf file into a shared-memory region of our system and then execute it thereafter. We don't want to call our "client"-program directly, since we need to execute it from the memory itself for our purpose.
While we know that our approach (described below) won't really work, we are (obviously) trying to get it to work. How would it be possible to copy a binary/elf/etc. file directly into the (shared)-memory and execute it thereafter? Maybe we just compiled it in the wrong way? Or something else was done wrong?
We also don't want to convert it into hex/shell-code, we already did that. We are looking for an easier and more practical solution.
Is anyone able to help? Would be much appreciated!
Two programs:
"Host"-Program (copy & execute client-program in shared memory)
"Client"-Program (basically a hello-world echo)
"Client"-Program:
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
}
Compiled with gcc -o binfile clientprogram.c -static.
"Host"-Program:
#include <string.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fp; //filepointer
size_t size; //filesize
unsigned char *buffer; //buffer
fp = fopen("binfile","rb");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
buffer = (unsigned char *) malloc(size);
if (fp == NULL){ //file empty?
printf("Error: There was an Error reading the file %s \n", "binfile");
exit(1);
}
else if (fread(buffer, sizeof *buffer, size, fp) != size){
printf("Error: There was an Error reading the file %s\n", "binfile");
exit(1);
}else{
int i;
// for(i=0; i<size;i++){
// printf("%02x", buffer[i]);
// }
}
void *mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
memcpy(mem, buffer, size);
mprotect(mem, size, PROT_READ|PROT_WRITE|PROT_EXEC);
void (*func)();
func = (void (*)()) buffer;
func();
munmap(mem, size);
fclose(fp);
free(buffer);
return 0;
}
Compiled with gcc hostprogram.c.
Build the client as a PIE, with -rdynamic. Then you'll be able to dlopen() it and dlsym() its main symbol (dlopen() will do the mmaping and mprotecting for you, as you'll be able to see if you strace the program), after which you'll be able to run its main from within the address space of the host.
Example:
#!/bin/sh
cat > client.c <<EOF
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("Hello, World!: from %ld\n", (long)getpid());
return 0;
}
EOF
gcc -fpic -c client.c
gcc -pie -rdynamic -o client client.o
cat > host.c <<EOF
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("Hello, I'm your host: %ld\n", (long)getpid()); ;
void *client_hndl;
typedef int main_t(int, char**);
main_t *client_main;
client_hndl = dlopen("./client", RTLD_LAZY);
if (!client_hndl){
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
client_main = (main_t*)dlsym(client_hndl, "main");
if (!client_main){
fprintf(stderr, "%s\n", dlerror());
exit(2);
}
return client_main(1, (char*[]){"client", 0});
}
EOF
gcc host.c -ldl
./client
echo =============
./a.out
Example output:
Hello, World!: from 14520
=============
Hello, I'm your host: 14521
Hello, World!: from 14521
You are looking for a solution to this GLIBC feature request.
This feature request is 7 years old, and it's somewhat unlikely that anything will happen with it any time soon.
Your best bet is probably to do roughly what you are already doing (building a fully-static binary).
Your approach doesn't work because the executable you built requires to be loaded at the address it was linked at (visible in readelf -l binfile as the address of the first PT_LOAD segment. You would need to mmap your binfile there with MAP_FIXED, no other address will do.
You also need to read and decode the Elf{32,64}_Ehdr that is found at the beginning of the file to find entry point to jump to. You currently are jumping to the ELF header itself, but that header is not where the execution should start.
I'm making a program(C language) on RaspberryPi
My program get a data from Arduino by Serial communication
Source Code here :
#ifdef RaspberryPi
//include system librarys
#include <stdio.h> //for printf
#include <stdint.h> //uint8_t definitions
#include <stdlib.h> //for exit(int);
#include <string.h> //for errno
#include <errno.h> //error output
//wiring Pi
#include <wiringPi.h>
#include <wiringSerial.h>
char device[]= "/dev/ttyACM0";
// filedescriptor
int fd;
unsigned long baud = 9600;
unsigned long time=0;
//prototypes
void loop(void);
void setup(void);
void setup(){
printf("%s \n", "Raspberry Startup!");
fflush(stdout);
//get filedescriptor
if ((fd = serialOpen (device, baud)) < 0){
fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
exit(1); //error
}
//setup GPIO in wiringPi mode
if (wiringPiSetup () == -1){
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
exit(1); //error
}
}
void loop(){
// Pong every 3 seconds
if(millis()-time>=3000){
serialPuts (fd, "Received\n");
time=millis();
}
// read signal
if(serialDataAvail (fd)){
char newChar = serialGetchar (fd);
printf("%c", newChar);
if((int)newChar >= 1){
system("raspistill -o image.jpg");
system("convert image.jpg -threshold 20% imagebw.jpg");
system("tesseract imagebw.jpg imageocr");
system("cat imageocr.txt");
}
fflush(stdout);
}
}
int main(void){
setup();
while(1) loop();
return 0;
}
#endif //#ifdef RaspberryPi
Before I put
system("convert image.jpg -threshold 20% imagebw.jpg");
system("tesseract imagebw.jpg imageocr");
system("cat imageocr.txt");
this code, it worked well
But, It does not work even if I delete it.
I found following error on my compiler(GCC)
/usr/lib/gcc/arm-linux-gneabihf/4.9/../../../arm-linux-gnueabihf/ort1.o:In function '_start':/build/glibc-mqlSLF/glibc-2.19/csu/../ports/sysdeps/arm/start.S:119 : undefined reference to 'main'
collect2: error: ld returned 1 exit sutatus
And I used following two command
sudo gcc test.c -o hello -lwiringPi -DRaspberryPi <br>
sudo gcc test.c -o hello -lwiringPi -DRaspberryPi -nostartfiles
Can anybody help me with this issue?
This program is supposed to print a webpage to terminal
usage: ./prog www.page.com 80 /folder/index.html
program always does as it should but always seg-faults at the end
#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <termios.h>
#define HOST "localhost"
#define PAGE "/"
#define PORT "80"
#define USERAGENT "HTML 1.1"
char *build_get_query(char *host,char *page){
char *query;
char *getpage = page;
char *tpl = "GET /%s HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nConnection: close\r\n\r\n";
if(getpage[0]=='/'){
getpage=getpage + 1; /*Removing leading / */
}
/* -5 is to consider the %s %s %s in tpl and the ending \0 */
query=malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5);
sprintf(query, tpl, getpage, host, USERAGENT);
return query;
}
int main(int argc, char **argv){
int sockfd;
struct addrinfo hints, *servinfo, *p;
int s;
char *page;
char *stringA;
int tmpres;
char *sstr;
if(argc<3){
fprintf(stderr,"\n\tUSAGE:\n\t%s hostname/ip PORTnr /PAGE/index.shtml \n\n",argv[0]);
fprintf(stderr,"\texample:\n\t%s www.anypage.com 80 /folder/index.shtml \n\n",argv[0]);
exit(1);
}
memset(&hints,0,sizeof(struct addrinfo));
hints.ai_family=AF_INET; /* Allow IPv4 or IPv6 */
hints.ai_socktype=SOCK_STREAM; /* stream socket */
hints.ai_flags=0;
hints.ai_protocol=0; /* Any protocol */
if((s=getaddrinfo(argv[1],PORT,&hints,&servinfo))!=0){
fprintf(stderr,"\n\tgetaddrinfo: %s\n",gai_strerror(s));
exit(EXIT_FAILURE);
}
for(p=servinfo; p!=NULL; p=p->ai_next){
if((sockfd=socket(p->ai_family,p->ai_socktype,p->ai_protocol))==-1){
fprintf(stderr,"\n\tSOCKET FAIL\n\n");
continue;
}
if((connect(sockfd,p->ai_addr,p->ai_addrlen))<0){
close(sockfd);
fprintf(stderr,"\n\tCONECTION FAIL\n\n");
continue;
}
break;
}
if(p==NULL){
fprintf(stderr,"\n\tCONECTION FAIL\n\n");
exit(2);
}
freeaddrinfo(servinfo);
if(argc > 3){
page=argv[3];
}else{
page=PAGE;
}
if((stringA=malloc(BUFSIZ))==NULL){
printf("\n\tMEMORY ERROR\n\n");
exit(1);
}
stringA=build_get_query(argv[1],page);
if((write(sockfd,stringA,strlen(stringA)))<0){
printf("\n\tERROR ON SEND\n\n");
}
memset(stringA, 0, sizeof(stringA));
while((tmpres=read(sockfd,stringA,BUFSIZ))>0){
if((sstr=strstr(stringA,"<!DOCTYPE "))!=NULL){
stringA=sstr;
}
if((sstr=strstr(stringA,"</html>"))!=NULL){
strncpy(sstr+7,"\n",(BUFSIZ-strlen(stringA))+5);
}
fprintf(stdout,"%s",stringA);
}
if(tmpres<0){
perror("READ ERROR");
}
close(sockfd);
return 0;
}
gdb info
Program received signal SIGSEGV, Segmentation fault.
_dl_fini () at dl-fini.c:183
183 dl-fini.c: No such file or directory.
in dl-fini.c
(gdb) bt
#0 _dl_fini () at dl-fini.c:183
#1 0x0015d1ef in __run_exit_handlers (status=0, listp=0x289324, run_list_atexit=true) at exit.c:78
#2 0x0015d25f in *__GI_exit (status=0) at exit.c:100
#3 0x00144bde in __libc_start_main (main=0x804892d <main>, argc=4, ubp_av=0xbffff454, init=0x8048d00 <__libc_csu_init>,
fini=0x8048cf0 <__libc_csu_fini>, rtld_fini=0x11e080 <_dl_fini>, stack_end=0xbffff44c) at libc-start.c:258
#4 0x08048811 in _start ()
(gdb)
I am intrigued with gdb information because I have installed sudo apt-get install build-essential about a year ago and never had problems until today.
The thing I see is that you allocate BUFSIZ bytes to the buffer, and you read up to BUFSIZ bytes into the buffer, but you are trying to use a strstr() and a strlen() on the buffer... which, if you have actually read BUFSIZ bytes into your buffer may well not be a null terminated string.
I would suggest you allocate BUFSIZ+1 and memset( stringA, 0, BUFSIZ+1 ) to guard against a random walk through memory by strlen() which would produce some pretty undefined behaviors in the while loop and could also result in the printf() within the loop behaving oddly, or at least use printf( "%.*s", BUFSIZ, stringA ); for the output.
char readBuffer[BUFSIZ+1] = { 0 };
stringA=build_get_query(argv[1],page);
if((write(sockfd,stringA,strlen(stringA)))<0){
printf("\n\tERROR ON SEND\n\n");
}
while((tmpres=read(sockfd,readBuffer,BUFSIZ))>0){
if((sstr=strstr(readBuffer,"<!DOCTYPE "))!=NULL){
strcpy( readBuffer, sstr );
}
if((sstr=strstr(readBuffer,"</html>"))!=NULL){
strncpy(sstr+7,"\n",(BUFSIZ-strlen(readBuffer))+5);
}
fprintf(stdout,"%s",readBuffer);
memset( readBuffer, 0 , BUFSIZ+1 );
}
PS: Actually, after reading the other response, I realize that you're making an even bigger mistake depending on stringA being a pointer to a BUFSIZ array after you have reassigned it to some other address (returned from the build query).
And the size of the buffer allocated to stringA isn't BUFSIZ. After all it receives the address of the buffer allocated in build_get_query, which could be even smaller than BUFSIZ.
I don't know why you use stringA=malloc(BUFSIZ) and in the next instruction you change the stringA pointer to another buffer. There are many memory leaks there.
I want to have a message send & receive through 2 uni-direction FIFO
Flow of data
FIFO1
stdin--->parent(client) writefd--->FIFO1-->child(server) readfd
FIFO2
child(server) writefd2---->FIFO2--->parent(client) readfd2--->stdout
I need to have boundary structed message mesg_len+mesg_type+mesg_data
The function is that if user input "Knock Knock" on stdin, which directs to client, client send this message to server through FIFO1, server compares the string, if matches with "Knock Knock", then server reply message "Who's there?" to client through FIFO2, and client write this message to the stdout.
The interactive part is like:
client:Knock Knock
server:who's there
client:eric
server:eric,welcome
client:exit
all signal terminate
Below is my code:
I need help on kill() signals when client types "exit".It seems the client process still live after call kill(). So i need to type ctrl+c to end
Please help me. Thanks a lot!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_BUF 100
#define MAXMESGDATA (MAX_BUF - 2* sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
struct mymesg{
long mesg_len; //byte in mesg_data
long mesg_type; //message type
char mesg_data[MAXMESGDATA];
};
ssize_t mesg_send (int fd, struct mymesg *mptr){
return (write (fd,mptr,MESGHDRSIZE + mptr->mesg_len));
}
ssize_t mesg_recv(int fd,struct mymesg *mptr){
size_t len;
ssize_t n;
if ((n=read(fd,mptr,MESGHDRSIZE))==0) {//read hear first, get len of data
return 0; //end of file
} else if (n!=MESGHDRSIZE){
printf("message header: expected %d, got %d\n", MESGHDRSIZE,n);
exit(1);
}
if ((len=mptr->mesg_len)>0)
{
if ((n=read(fd,mptr->mesg_data,len))!=len)
{
printf("message data: expected %d, got %d\n", len,n);
exit(1);
}
}
return len;
}
void client(int readfd,int writefd){
size_t len;
ssize_t n;
struct mymesg mesg;
for (;;)
{
printf("\nClient:");
fgets(mesg.mesg_data,MAXMESGDATA,stdin);//read mesg
len=strlen(mesg.mesg_data);
if (mesg.mesg_data[len-1]=='\n') //ignore newline
len--;
mesg.mesg_len=len;
mesg.mesg_type=1;
mesg_send(writefd,&mesg);//write to IPC channel
//read from IPC,write to std output
if((n=mesg_recv(readfd,&mesg))>0)
write(STDOUT_FILENO,mesg.mesg_data,n);
}
}
void server(int readfd,int writefd){
ssize_t n;
struct mymesg mesg;
for(;;)
{
mesg.mesg_type=1;
//read from IPC channel
if ((n=mesg_recv(readfd,&mesg))==0){
printf("Message missing");
exit(1);
}
mesg.mesg_data[n]='\0';
mesg.mesg_len=strlen(mesg.mesg_data);
char* str=NULL;
if (strcasecmp ("Knock Knock", mesg.mesg_data)==0){
str="Server:Who's there?";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
else if(strcasecmp ("Eric", mesg.mesg_data)==0){
str="Server:Eric,Welcome!";
strcpy(mesg.mesg_data,str);
mesg.mesg_len=strlen(str)-1;
}
else if(strcasecmp ("Exit", mesg.mesg_data)==0){
kill(getpid(),SIGTERM);
kill(getppid(),SIGTERM);
exit(0);
}
mesg_send(writefd,&mesg);
}
}
int main(int argc, char ** argv){
/*MAXMESGDATA== 92 bytes; sizeof(struct mymesg)== 100 bytes
2* sizeof(long)== 8 bytes; MESGHDRSIZE ==8 bytes*/
int readfd,writefd;
pid_t childpid;
//create 2 FIFOs
if ((mkfifo(FIFO1,FILE_MODE)<0) && (errno!=EEXIST)){
printf("can't create %s",FIFO1);
exit(1);
}
if ((mkfifo(FIFO2,FILE_MODE)<0) && (errno!=EEXIST)){
printf("can't create %s",FIFO1);
unlink(FIFO1);
exit(1);
}
if ((childpid=fork()==0)){//child
readfd=open(FIFO1,O_RDONLY,0);
writefd=open(FIFO2,O_WRONLY,0);
server(readfd,writefd);
exit(0);
}
//parent
writefd=open(FIFO1,O_WRONLY,0);
readfd=open(FIFO2,O_RDONLY,0);
client(readfd,writefd);
waitpid(childpid,NULL,0);
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
return EXIT_SUCCESS;
}
You open FIFO2 as WRONLY and FIFO1 as RDONLY in both the processes. Opening pipe for read will block until the other side opens for write, and you open for read on both sides - hence deadlocked.