debugging server's cgi program - linux

i am trying to make a webserver in C which can handle request to dynamic contents.
the webserver part is finish already. i'm trying to execute the following command:
http://localhost:1601/cgi-bin/test?3&7
with the code of program test is as follow:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <wordexp.h>
#define MAXLINE 300
int main(int narg, char * arg[]) {
char *buf, *p;
char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
int n1=0, n2=0;
/* Extract the two arguments */
if ((buf = getenv("QUERY_STRING")) != NULL) {
p = strchr(buf, '&');
*p = '\0';
strcpy(arg1, buf);
strcpy(arg2, p+1);
n1 = atoi(arg1);
n2 = atoi(arg2);
}
/* Make the response body */
sprintf(content, "Welcome to add.com: ");
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
content, n1, n2, n1 + n2);
sprintf(content, "%sThanks for visiting!\r\n", content);
/* Generate the HTTP response */
printf("Content-length: %d\r\n", (int)strlen(content));
printf("Content-type: text/html\r\n\r\n");
printf("%s", content);
if (fork()==0) {
printf("asdfagloiauergauhfgaiudfhg");
execvp("ls",arg);
printf("child of adder error");
}
printf("%s", content);
fflush(stdout);
exit(0);
}
/* $end adder */
It run well. However, i wonder why the child code (the line printf("asdfagloiauergauhfgaiudfhg"); and execvp) didn't print out to the webserver's output. although everything else in test output correctly.

For starters you set the Content-length header to the length of the content, then sent the content, then sent more data in both threads. The browser is within its rights to ignore everything after content-length bytes in the output stream.

Related

Why do I get the error message when reading from a FIFO?

On the Introduction to Operative Systems course we're asked to build a client-server model using FIFOs. As client we send a string to the server, the server gets this string and if a file with this name exists it sends back the first line on this file. If the file doesn't exist or it does exist but it happens to be empty, it sends an empty string back.
The problem is that in only works once, i send file1 for example, the server sends back the first line and when I send again file1 or another file's name in the same "session" the printf("First line of the file %s: \n%s\n", name, recived); doesn't happen, it enters into if (read(fifo_serv_client, recived, sizeof(recived)) == -1) { printf("An error occurred.\n"); }.
Any idea on why is this? I tried doing it two times with the same file, so it exists 100% but I still get the same result.
Thank you so much!
Here is the code for the client:
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define BUFSIZE 512
int main()
{
int fifo_client_serv;
char *fifo1 = "fifo_client_serv";
int fifo_serv_client;
char *fifo2 = "fifo_serv_client";
char name[BUFSIZE];
while(1) {
printf("Write the file's name: ");
scanf("%s", name);
/* write str to the FIFO */
fifo_client_serv = open(fifo1, O_WRONLY);
fifo_serv_client = open(fifo2, O_RDONLY);
write(fifo_client_serv, name, sizeof(name));
char recived[BUFSIZE];
if (read(fifo_serv_client, recived, sizeof(recived)) == -1) {
printf("An error occurred.\n");
} else {
printf("First line of the file %s: \n%s\n", name, recived);
close(fifo_client_serv);
close(fifo_serv_client);
}
}
return 0;
}
And here's the code for the server:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define BUFSIZE 512
int main()
{
int fifo_client_serv;
char *fifo1 = "fifo_client_serv";
int fifo_serv_client;
char *fifo2 = "fifo_serv_client";
char buf[BUFSIZE];
char line[BUFSIZE];
FILE *file;
/* create the FIFO (named pipe) */
mkfifo(fifo1, 0777);
mkfifo(fifo2, 0777);
printf("Server runnning...\n");
while (1)
{
fifo_client_serv = open(fifo1, O_RDONLY);
fifo_serv_client = open(fifo2, O_WRONLY);
read(fifo_client_serv, buf, BUFSIZE);
if((file = fopen(buf, "r")) == NULL) {
write(fifo_serv_client, "", BUFSIZE);
} else {
fgets(line, BUFSIZE, file);
write(fifo_serv_client, line, BUFSIZE);
}
/* clear buffer and line */
memset(buf, 0, sizeof(buf));
memset(line, 0, sizeof(buf));
close(fifo_client_serv);
close(fifo_serv_client);
unlink(fifo1);
unlink(fifo2);
}
return 0;
}
UPDATE I found why this happens, if I create the fifo inside the while it works fine! I just put mkfifo(fifo1, 0777); mkfifo(fifo2, 0777); first in the while. My question is, is it really necessary to create the FIFO each time I send a text from the client? Can't I just create once the FIFO, do the communication from it and close once I finish?
Can you try to close the file after read/writes in the server file ?
if((file = fopen(buf, "r")) == NULL) {
write(fifo_serv_client, "", BUFSIZE);
fclose(file);
} else {
fgets(line, BUFSIZE, file);
write(fifo_serv_client, line, BUFSIZE);
fclose(file);
}
By the way. Its worth to do error checking on your writes.

Inter process communication using FIFO

Client server must pass to the Server process a filename and the Server process must return the number of lines in the file. My problem is that the received variable only contains 6 characters of the filename and it ends up by throwing segmentation fault dump core error. Do you know why this happens? This is my code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(){
int fd1,fd2;
const char *fifo1="./fifo1Channel";
const char *fifo2="./fifo2Channel";
mkfifo(fifo1,0666);
mkfifo(fifo2,0666);
char filename[30];
printf("Give me a filename:\n");
fgets(filename,30,stdin);
strtok(filename,"\n");
int pid=fork();
if(pid>0){
char received[30], ch;
FILE *fp;
fd1=open(fifo1, O_RDONLY);
read(fd1,received,strlen(received));
close(fd1);
printf("From server process:%s\n",received);
fp=fopen(received,"r");
int nrOfLines=0;
for(ch=getc(fp);ch!=EOF;ch=getc(fp))
if(ch=='\n')
nrOfLines++;
fd2=open(fifo2, O_WRONLY);
write(fd2,&nrOfLines,sizeof(nrOfLines));
close(fd2);
return 0;
}
if(pid==0){
int receivedNumber;
fd1=open(fifo1,O_WRONLY);
write(fd1,filename,strlen(filename));
close(fd1);
fd2=open(fifo2,O_RDONLY);
read(fd2,&receivedNumber,sizeof(receivedNumber));
close(fd2);
printf("From client process: %d\n",receivedNumber);
return 0;
}
return 0;
}
I think the problem was in server process. I replaced strlen(received) with 30, the maximum number of characters of filename, in function read and it works now!

setsockopt IPT_SO_SET_REPLACE flag return error (linux)

I try to use setsockopt with the flag IPT_SO_SET_REPLACE but i keep getting the wired error from errno Protocol not available this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <fcntl.h>
int main(void) {
int sock;
int ret;
void *data;
size_t size;
struct ipt_replace *repl;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("socket");
return -1;
}
size = sizeof(struct ipt_replace);
data = malloc(size); Protocol not available
if (data == NULL) {
perror("malloc");
return -1;
}
memset(data, 0, size);
repl = (struct ipt_replace *) data;
repl->num_counters = 0x1;
repl->size = 0xffffffff;
repl->valid_hooks = 0x1;
repl->num_entries = 0x1;
ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, size);
printf("\ndone %d\n", ret);
perror("error: ");
return 0;
}
this is the output :
sock:3
data:
size:92
done -1
error: : Protocol not available
Looking briefly at the kernel code, this would seem to indicate that the IP tables module isn't available (i.e. the kernel wasn't built with it configured, or it can't be found or loaded).
It appears to me that for a socket of the kind you created, the code flow is:
enter raw_setsockopt: level != SOL_RAW so...
call ip_setsockopt: level == SOL_IP but option isn't any of the IP_xxx options so...
call nf_setsockopt: Search loaded netfilter modules for one that has registered IPT_SO_SET_REPLACE.
I think the last must have failed, so you get ENOPROTOOPT back (== Protocol not available)

How to use static file descriptor using poll linux function call?

poll is running for infinite time interval.
i want poll to hit when some thing is written into file or when file is updated.
but poll is not able to detect when file is written.
#include <stdio.h>
#include <poll.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
char buf[5]="true";
struct pollfd ufds[1];
int rv;
ufds[0].fd = 0;
ufds[0].events = POLLIN;
char *filename="textfile.txt";
ssize_t ret_write,ret_read;
ufds[0].fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 5);
if(ufds[0].fd== -1){
perror("open");
return 3;
}
while(1) {
ret_write= write (ufds[0].fd, &buf, (ssize_t) 5);
if((rv = poll(ufds, 1,-1 )) == -1) perror("select");
else if (rv == 0) printf("Timeout occurred!\n");
else if (ufds[0].revents & POLLIN) {
printf("return hit\n");
read(ufds[0].fd, buf, 5);
}
fflush(stdout);
}
return 0;
}
Your example can't work because the file is not open for reading. Even if the file was opened for reading, the code would not work as intended because poll would return sucessfully on end of file.
What you want is the inotify function. Please try it by yourself first, and ask a question when you have code not working as intended.

UDP Server giving Segmentation Fault

Ive written the following echo server using UDP but i have no idea that why it is giving me Segmentation Fault in sendto function, it receives fine but has problem sending data back to client. Ive been trying to find the problem for a few hours now but got no where. Can somebody please point out the fault or what i may be doing wrong.
Thanks
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
int main(int argc,char **args)
{
int BUF_LENGTH=101;
int port_no=1800;
struct sockaddr_in serv_addr,rmt_addr;
//rmt_addr=malloc(sizeof(struct sockaddr_in));
char *buffer=malloc(BUF_LENGTH);
int byte_recv=0;
int rmt_length=0;
int sock_id;
sock_id=socket(AF_INET,SOCK_DGRAM,0);
if(sock_id<0)
{
printf("Error creating socket : %d",sock_id);
return -1;
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(port_no);
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(sock_id,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
printf("Created\n");
while(true)
{
printf("Waiting\n");
byte_recv=recvfrom(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,&rmt_length);
printf("%s\n",buffer);
if(byte_recv<0)
{
printf("Error receiving: %d",byte_recv);
error("recvfrom");
return -2;
}
printf("%d:%d %s\n",rmt_length,rmt_addr.sin_port,inet_ntoa(rmt_addr.sin_addr));
byte_recv=sendto(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,rmt_length); //The segmentation fault comes here
printf("Bytes sent: %d \n",byte_recv);
if(byte_recv<0)
error("sendto");
}
free(buffer);
return 0;
}
These lines:
error("recvfrom");
error("sendto");
don't do what you think they do. You probably meant to say perror.
Additionally, you aren't initializing rmt_length correctly. Try this:
int rmt_length=sizeof(rmt_addr);
Finally, you are echoing more bytes back than the server receives. Try this:
byte_recv=sendto(sock_id,buffer,byte_recv,0,(struct sockaddr*)&rmt_addr,rmt_length);

Resources