ashi2
asked on
need help with cprogram
I need to write a cgi-bin program capitals.c that keeps information about the capital of a number of countries (at least ten) and, given as request parameter the country, returns the capital name. For example, if the country requested is America, it returns the information that "The capital of America is WashingtonDC" or "I do not know what is the capital of America".
How should i start, I tried to write something but was confused, do i need to make an array, I am not very good at C.
need help
How should i start, I tried to write something but was confused, do i need to make an array, I am not very good at C.
need help
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hello ewest, This is what I tried but don't know if I doing right, how will i enter the capital, do i need another struct of it, can I do it togther.
include <stdio.h>
typedef struct /* Define a structure */
{
char Country[20];
char *Capital[30];
} country = {
"America",
"Australia",
"China".
"CostaRica"
} ;
int main()
{
printf("Enter the name of country to see its capital"\n");
scanf(-----------
for (i = 0; i < N; i++) {
if (!strcmp(countries[i].coun try, user_input) {
break;
}
}
if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}
include <stdio.h>
typedef struct /* Define a structure */
{
char Country[20];
char *Capital[30];
} country = {
"America",
"Australia",
"China".
"CostaRica"
} ;
int main()
{
printf("Enter the name of country to see its capital"\n");
scanf(-----------
for (i = 0; i < N; i++) {
if (!strcmp(countries[i].coun
break;
}
}
if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}
You can initialize the struct with
typedef struct /* Define a structure */
{
const char *Country;
const char *Capital;
} country = {
{"N.America", "Washington D.C."},
{"Australia", "Canberra"},
{"China", "Beijing"},
{"CostaRica", "San Jose"},
{ NULL, NULL }
} ;
You are initializing an array of structs, not a simple array.
Note too I've initialized the table with string literals.
typedef struct /* Define a structure */
{
const char *Country;
const char *Capital;
} country = {
{"N.America", "Washington D.C."},
{"Australia", "Canberra"},
{"China", "Beijing"},
{"CostaRica", "San Jose"},
{ NULL, NULL }
} ;
You are initializing an array of structs, not a simple array.
Note too I've initialized the table with string literals.
ASKER
what is the pupose of NULL NULL, not very clear with it
These are just guard values. When you create a table lookup with string literals, you can scan until you hit a NULL guard value. Using guard values allows you to extend the table with additional entries without having to maintain a count value.
For example, using the guard value approach the lookup becomes:
struct {
char *name;
int value;
} table[] = {{"blue", 1},
{"red", 2},
{"green", 3},
{NULL, -1}};
for (i=0; NULL != table[i].name; i++) {
/* look for name */
}
It should be apparent that I can add entries before the guard value without having to change the termination value of the for loop.
As I look at your code, I see you need to remove the typedef and add the array brackets:
struct {
const char * country;
const char * capital;
} countries[] = {
{"N.America", "Washington DC"},
{"Australia", "Canberra"},
...
{ NULL, NULL }};
For example, using the guard value approach the lookup becomes:
struct {
char *name;
int value;
} table[] = {{"blue", 1},
{"red", 2},
{"green", 3},
{NULL, -1}};
for (i=0; NULL != table[i].name; i++) {
/* look for name */
}
It should be apparent that I can add entries before the guard value without having to change the termination value of the for loop.
As I look at your code, I see you need to remove the typedef and add the array brackets:
struct {
const char * country;
const char * capital;
} countries[] = {
{"N.America", "Washington DC"},
{"Australia", "Canberra"},
...
{ NULL, NULL }};
ASKER
this is what i changed in following, did i do rite, but I am stil having errors,
what does it mean, initialized country? I got this as an warning. and some other errors as countries not decleared but I fixed that.
#include <stdio.h>
#include <string.h>
struct /* Define a structure */
{
const char *Country;
const char *Capital;
} countries[] =
{"N.America", "Washington D.C."},
{"Australia", "Sydney"},
{"China", "Beijing"},
{"CostaRica", "San Jose"},
{"Germany", "Berlin" },
{"Iraq", "Baghdad"},
{"Israel","Jerusalem"},
{"Italy", "Rome"),
{"Japan", "Tokyo"},
{NULL,NULL}
};
int main(){
int i,N;
printf("Enter the name of Country to see its capital:\n");
for (i = 0; i < N; i++) {
if (!strcmp(countries[i].coun try, user_input) {
break;
}
}
if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}
}
what does it mean, initialized country? I got this as an warning. and some other errors as countries not decleared but I fixed that.
#include <stdio.h>
#include <string.h>
struct /* Define a structure */
{
const char *Country;
const char *Capital;
} countries[] =
{"N.America", "Washington D.C."},
{"Australia", "Sydney"},
{"China", "Beijing"},
{"CostaRica", "San Jose"},
{"Germany", "Berlin" },
{"Iraq", "Baghdad"},
{"Israel","Jerusalem"},
{"Italy", "Rome"),
{"Japan", "Tokyo"},
{NULL,NULL}
};
int main(){
int i,N;
printf("Enter the name of Country to see its capital:\n");
for (i = 0; i < N; i++) {
if (!strcmp(countries[i].coun
break;
}
}
if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}
}
I see you took my sample code snippet without filling in the "blanks". Your for loop as coded uses N as a limit. However N was not set to any known value. Worse it has a random value that may be greater than the maximum index to the countries array. If you *really* want to use N. You can initialize it to the number of elements in countries with
N = sizeof(countries)/sizeof(c ountries[0 ])
On the other hand, using the guard values, write the for loop as
char *capital = NULL
for (i = 0; NULL != countries[i]; i++) {
if (!strcmp(countries[i].Coun try, user_input)) {
capital = &countries[i].Capital;
break;
}
}
if (NULL == capital) {
/* handle error */
} else {
/* found the capital */
}
You still haven't addressed how to get the user supplied country name into user_input. In fact you haven't properly declared user_input.
Question: are you expected to be fluent in C for this exam?
N = sizeof(countries)/sizeof(c
On the other hand, using the guard values, write the for loop as
char *capital = NULL
for (i = 0; NULL != countries[i]; i++) {
if (!strcmp(countries[i].Coun
capital = &countries[i].Capital;
break;
}
}
if (NULL == capital) {
/* handle error */
} else {
/* found the capital */
}
You still haven't addressed how to get the user supplied country name into user_input. In fact you haven't properly declared user_input.
Question: are you expected to be fluent in C for this exam?
ASKER
no not really, but still its high level and I am not good at it
ASKER
Hello ewest,
I need help for web server code, this is an assignement, a web server is give to me and I have to make it as concurent server. I have written the code from Unix Network Programming book and understood the way they have explained it by using fork. but I am getting some errors and I am sure its the way I have placed it.
I am not sure if i should paste the code in here as my class mates must be seekign help from here, is it a way I can e-mail it to you, if not then I will post it here.
I need help for web server code, this is an assignement, a web server is give to me and I have to make it as concurent server. I have written the code from Unix Network Programming book and understood the way they have explained it by using fork. but I am getting some errors and I am sure its the way I have placed it.
I am not sure if i should paste the code in here as my class mates must be seekign help from here, is it a way I can e-mail it to you, if not then I will post it here.
I'd prefer to keep the "conversation" here in EE.
What errors are you getting?
Can you just post the relevant code snippets?
What errors are you getting?
Can you just post the relevant code snippets?
ASKER
ok ewest, I will post here,
this is 2 question on assignment. we are given a file tiny.c and I working just with that file.
I have to
1)Change this sequential server to be a concurrent server that forks a separate handler for each request. The handler will terminate when it completes its response. The parent must reap (have a wait statement) for the children.
2)All HTTP headers received and sent by the server should also be printed to the screen by the server. Try not to interleave lines from different interactions (here by interaction I mean a request or a response) of different handlers.
For reference I am taking help with UNIX Network Programming.
last nite I worked on it, and fix the errors atleast which I was getting with fork and signals, now I am trying to insert semaphores in my code and I am not getting, how can i insert semaphores code in my program though I have code written for semaphores.
also can u tell me if i have inserted fork and signals correctly. and for the second part printing http header where I should change. lastly how can i run, I start server and thenc client, I run the post as tiny 09872 &
then I go to client and comile after that the scren just goes away and does not let me type anything.
where ever I have made a change I have written as comment
//change here
following is the code
/* $begin tinymain */
/*
* tiny.c - A simple, iterative HTTP/1.0 Web server that uses the
* GET method to serve static and dynamic content.
*/
#include "csapp.h"
#define dport 09872 // change here
void doit(int fd);
void read_requesthdrs(rio_t *rp);
int parse_uri(char *uri, char *filename, char *cgiargs);
void serve_static(int fd, char *filename, int filesize);
void get_filetype(char *filename, char *filetype);
void serve_dynamic(int fd, char *filename, char *cgiargs);
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg);
//change here
void sigchld_handler(int sig)
{
while (waitpid(-1, 0, WNOHANG) > 0)
;
return;
}
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen;
struct sockaddr_in clientaddr;
// pid_t childpid; //change here
/* Check command line args */
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
port = atoi(argv[1]);
// making change here
Signal(SIGCHLD, sigchld_handler); // change here
listenfd = Open_listenfd(port);
while (1) {
clientlen = sizeof(clientaddr);
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
if (Fork() == 0) { // change here
// change here
Close(listenfd); /* Child closes its listening socket */
doit(connfd);
Close(connfd);
//change here
exit(0); /* Child exits */
}
//change here
Close(connfd); /* Parent closes connected socket (important!) */
}
}
/* $end tinymain */
/*
* doit - handle one HTTP request/response transaction
*/
/* $begin doit */
void doit(int fd)
{
int is_static;
struct stat sbuf;
char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
char filename[MAXLINE], cgiargs[MAXLINE];
rio_t rio;
/* Read request line and headers */
Rio_readinitb(&rio, fd);
Rio_readlineb(&rio, buf, MAXLINE);
sscanf(buf, "%s %s %s", method, uri, version);
if (strcasecmp(method, "GET")) {
clienterror(fd, method, "501", "Not Implemented",
"Tiny does not implement this method");
return;
}
read_requesthdrs(&rio);
/* Parse URI from GET request */
is_static = parse_uri(uri, filename, cgiargs);
if (stat(filename, &sbuf) < 0) {
clienterror(fd, filename, "404", "Not found",
"Tiny couldn't find this file");
return;
}
if (is_static) { /* Serve static content */
if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {
clienterror(fd, filename, "403", "Forbidden",
"Tiny couldn't read the file");
return;
}
serve_static(fd, filename, sbuf.st_size);
}
else { /* Serve dynamic content */
if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) {
clienterror(fd, filename, "403", "Forbidden",
"Tiny couldn't run the CGI program");
return;
}
serve_dynamic(fd, filename, cgiargs);
}
}
/* $end doit */
/*
* read_requesthdrs - read and parse HTTP request headers
*/
/* $begin read_requesthdrs */
void read_requesthdrs(rio_t *rp)
{
char buf[MAXLINE];
Rio_readlineb(rp, buf, MAXLINE);
while(strcmp(buf, "\r\n"))
Rio_readlineb(rp, buf, MAXLINE);
return;
}
/* $end read_requesthdrs */
/*
* parse_uri - parse URI into filename and CGI args
* return 0 if dynamic content, 1 if static
*/
/* $begin parse_uri */
int parse_uri(char *uri, char *filename, char *cgiargs)
{
char *ptr;
if (!strstr(uri, "cgi-bin")) { /* Static content */
strcpy(cgiargs, "");
strcpy(filename, ".");
strcat(filename, uri);
if (uri[strlen(uri)-1] == '/')
strcat(filename, "home.html");
return 1;
}
else { /* Dynamic content */
ptr = index(uri, '?');
if (ptr) {
strcpy(cgiargs, ptr+1);
*ptr = '\0';
}
else
strcpy(cgiargs, "");
strcpy(filename, ".");
strcat(filename, uri);
return 0;
}
}
/* $end parse_uri */
/*
* serve_static - copy a file back to the client
*/
/* $begin serve_static */
void serve_static(int fd, char *filename, int filesize)
{
int srcfd;
char *srcp, filetype[MAXLINE], buf[MAXBUF];
/* Send response headers to client */
get_filetype(filename, filetype);
sprintf(buf, "HTTP/1.0 200 OK\r\n");
sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);
sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
Rio_writen(fd, buf, strlen(buf));
/* Send response body to client */
srcfd = Open(filename, O_RDONLY, 0);
srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
Close(srcfd);
Rio_writen(fd, srcp, filesize);
Munmap(srcp, filesize);
}
/*
* get_filetype - derive file type from file name
*/
void get_filetype(char *filename, char *filetype)
{
if (strstr(filename, ".html"))
strcpy(filetype, "text/html");
else if (strstr(filename, ".gif"))
strcpy(filetype, "image/gif");
else if (strstr(filename, ".jpg"))
strcpy(filetype, "image/jpeg");
else
strcpy(filetype, "text/plain");
}
/* $end serve_static */
/*
* serve_dynamic - run a CGI program on behalf of the client
*/
/* $begin serve_dynamic */
void serve_dynamic(int fd, char *filename, char *cgiargs)
{
char buf[MAXLINE], *emptylist[] = { NULL };
/* Return first part of HTTP response */
sprintf(buf, "HTTP/1.0 200 OK\r\n");
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Server: Tiny Web Server\r\n");
Rio_writen(fd, buf, strlen(buf));
if (Fork() == 0) { /* child */
/* Real server would set all CGI vars here */
setenv("QUERY_STRING", cgiargs, 1);
Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */
Execve(filename, emptylist, environ); /* Run CGI program */
}
Wait(NULL); /* Parent waits for and reaps child */
}
/* $end serve_dynamic */
/*
* clienterror - returns an error message to the client
*/
/* $begin clienterror */
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg)
{
char buf[MAXLINE], body[MAXBUF];
/* Build the HTTP response body */
sprintf(body, "<html><title>Tiny Error</title>");
sprintf(body, "%s<body bgcolor=""ffffff"">\r\n", body);
sprintf(body, "%s%s: %s\r\n", body, errnum, shortmsg);
sprintf(body, "%s<p>%s: %s\r\n", body, longmsg, cause);
sprintf(body, "%s<hr><em>The Tiny Web server</em>\r\n", body);
/* Print the HTTP response */
sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-type: text/html\r\n");
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-length: %d\r\n\r\n", strlen(body));
Rio_writen(fd, buf, strlen(buf));
Rio_writen(fd, body, strlen(body));
}
/* $end clienterror */
//#ifndef SEM_H
//# define SEM_H
//# include <sys/sem.h>
//# include <sys/types.h>
//# include <stdio.h>
//# include <stdlib.h>
//typedef int semaphore;
//void sem_init(semaphore *, int);
//void P(const semaphore *);
//void V(const semaphore *);
//void sem_destroy(const semaphore *);
//# define binary_sem_init(s) sem_init(s, 1);
//#endif
//sem.c
//#include "sem.h"
//static struct sembuf acquire = {0, -1, SEM_UNDO},
//release = {0, 1, SEM_UNDO};
//void sem_init(semaphore *s, int value)
//{
//*s = 0;
//if ((*s = semget(0, 1, IPC_CREAT | IPC_EXCL | 0600)) == -1) {
// perror("sem_init: semget: ");
// exit(1);
//}
//if(semctl(*s, 0, SETVAL, value) == -1) {
// perror("sem_init: semctl: ");
// exit(1);
// }
//}
//void P(const semaphore *s)
//{
//if (semop(*s, &acquire, 1) == -1) {
// perror("P: ");
// exit(1);
//}
//}
//void V(const semaphore *s)
//{
//if (semop(*s, &release, 1) == -1) {
// perror("V: ");
// exit(1);
//}
//}
//void sem_destroy(const semaphore *s)
//{
//if (semctl(*s, 0, IPC_RMID, NULL) == -1) {
// perror("sem_destroy: semctl: ");
// exit(1);
//}
//}
this is 2 question on assignment. we are given a file tiny.c and I working just with that file.
I have to
1)Change this sequential server to be a concurrent server that forks a separate handler for each request. The handler will terminate when it completes its response. The parent must reap (have a wait statement) for the children.
2)All HTTP headers received and sent by the server should also be printed to the screen by the server. Try not to interleave lines from different interactions (here by interaction I mean a request or a response) of different handlers.
For reference I am taking help with UNIX Network Programming.
last nite I worked on it, and fix the errors atleast which I was getting with fork and signals, now I am trying to insert semaphores in my code and I am not getting, how can i insert semaphores code in my program though I have code written for semaphores.
also can u tell me if i have inserted fork and signals correctly. and for the second part printing http header where I should change. lastly how can i run, I start server and thenc client, I run the post as tiny 09872 &
then I go to client and comile after that the scren just goes away and does not let me type anything.
where ever I have made a change I have written as comment
//change here
following is the code
/* $begin tinymain */
/*
* tiny.c - A simple, iterative HTTP/1.0 Web server that uses the
* GET method to serve static and dynamic content.
*/
#include "csapp.h"
#define dport 09872 // change here
void doit(int fd);
void read_requesthdrs(rio_t *rp);
int parse_uri(char *uri, char *filename, char *cgiargs);
void serve_static(int fd, char *filename, int filesize);
void get_filetype(char *filename, char *filetype);
void serve_dynamic(int fd, char *filename, char *cgiargs);
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg);
//change here
void sigchld_handler(int sig)
{
while (waitpid(-1, 0, WNOHANG) > 0)
;
return;
}
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen;
struct sockaddr_in clientaddr;
// pid_t childpid; //change here
/* Check command line args */
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
port = atoi(argv[1]);
// making change here
Signal(SIGCHLD, sigchld_handler); // change here
listenfd = Open_listenfd(port);
while (1) {
clientlen = sizeof(clientaddr);
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
if (Fork() == 0) { // change here
// change here
Close(listenfd); /* Child closes its listening socket */
doit(connfd);
Close(connfd);
//change here
exit(0); /* Child exits */
}
//change here
Close(connfd); /* Parent closes connected socket (important!) */
}
}
/* $end tinymain */
/*
* doit - handle one HTTP request/response transaction
*/
/* $begin doit */
void doit(int fd)
{
int is_static;
struct stat sbuf;
char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
char filename[MAXLINE], cgiargs[MAXLINE];
rio_t rio;
/* Read request line and headers */
Rio_readinitb(&rio, fd);
Rio_readlineb(&rio, buf, MAXLINE);
sscanf(buf, "%s %s %s", method, uri, version);
if (strcasecmp(method, "GET")) {
clienterror(fd, method, "501", "Not Implemented",
"Tiny does not implement this method");
return;
}
read_requesthdrs(&rio);
/* Parse URI from GET request */
is_static = parse_uri(uri, filename, cgiargs);
if (stat(filename, &sbuf) < 0) {
clienterror(fd, filename, "404", "Not found",
"Tiny couldn't find this file");
return;
}
if (is_static) { /* Serve static content */
if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {
clienterror(fd, filename, "403", "Forbidden",
"Tiny couldn't read the file");
return;
}
serve_static(fd, filename, sbuf.st_size);
}
else { /* Serve dynamic content */
if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) {
clienterror(fd, filename, "403", "Forbidden",
"Tiny couldn't run the CGI program");
return;
}
serve_dynamic(fd, filename, cgiargs);
}
}
/* $end doit */
/*
* read_requesthdrs - read and parse HTTP request headers
*/
/* $begin read_requesthdrs */
void read_requesthdrs(rio_t *rp)
{
char buf[MAXLINE];
Rio_readlineb(rp, buf, MAXLINE);
while(strcmp(buf, "\r\n"))
Rio_readlineb(rp, buf, MAXLINE);
return;
}
/* $end read_requesthdrs */
/*
* parse_uri - parse URI into filename and CGI args
* return 0 if dynamic content, 1 if static
*/
/* $begin parse_uri */
int parse_uri(char *uri, char *filename, char *cgiargs)
{
char *ptr;
if (!strstr(uri, "cgi-bin")) { /* Static content */
strcpy(cgiargs, "");
strcpy(filename, ".");
strcat(filename, uri);
if (uri[strlen(uri)-1] == '/')
strcat(filename, "home.html");
return 1;
}
else { /* Dynamic content */
ptr = index(uri, '?');
if (ptr) {
strcpy(cgiargs, ptr+1);
*ptr = '\0';
}
else
strcpy(cgiargs, "");
strcpy(filename, ".");
strcat(filename, uri);
return 0;
}
}
/* $end parse_uri */
/*
* serve_static - copy a file back to the client
*/
/* $begin serve_static */
void serve_static(int fd, char *filename, int filesize)
{
int srcfd;
char *srcp, filetype[MAXLINE], buf[MAXBUF];
/* Send response headers to client */
get_filetype(filename, filetype);
sprintf(buf, "HTTP/1.0 200 OK\r\n");
sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);
sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
Rio_writen(fd, buf, strlen(buf));
/* Send response body to client */
srcfd = Open(filename, O_RDONLY, 0);
srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
Close(srcfd);
Rio_writen(fd, srcp, filesize);
Munmap(srcp, filesize);
}
/*
* get_filetype - derive file type from file name
*/
void get_filetype(char *filename, char *filetype)
{
if (strstr(filename, ".html"))
strcpy(filetype, "text/html");
else if (strstr(filename, ".gif"))
strcpy(filetype, "image/gif");
else if (strstr(filename, ".jpg"))
strcpy(filetype, "image/jpeg");
else
strcpy(filetype, "text/plain");
}
/* $end serve_static */
/*
* serve_dynamic - run a CGI program on behalf of the client
*/
/* $begin serve_dynamic */
void serve_dynamic(int fd, char *filename, char *cgiargs)
{
char buf[MAXLINE], *emptylist[] = { NULL };
/* Return first part of HTTP response */
sprintf(buf, "HTTP/1.0 200 OK\r\n");
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Server: Tiny Web Server\r\n");
Rio_writen(fd, buf, strlen(buf));
if (Fork() == 0) { /* child */
/* Real server would set all CGI vars here */
setenv("QUERY_STRING", cgiargs, 1);
Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */
Execve(filename, emptylist, environ); /* Run CGI program */
}
Wait(NULL); /* Parent waits for and reaps child */
}
/* $end serve_dynamic */
/*
* clienterror - returns an error message to the client
*/
/* $begin clienterror */
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg)
{
char buf[MAXLINE], body[MAXBUF];
/* Build the HTTP response body */
sprintf(body, "<html><title>Tiny Error</title>");
sprintf(body, "%s<body bgcolor=""ffffff"">\r\n", body);
sprintf(body, "%s%s: %s\r\n", body, errnum, shortmsg);
sprintf(body, "%s<p>%s: %s\r\n", body, longmsg, cause);
sprintf(body, "%s<hr><em>The Tiny Web server</em>\r\n", body);
/* Print the HTTP response */
sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-type: text/html\r\n");
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-length: %d\r\n\r\n", strlen(body));
Rio_writen(fd, buf, strlen(buf));
Rio_writen(fd, body, strlen(body));
}
/* $end clienterror */
//#ifndef SEM_H
//# define SEM_H
//# include <sys/sem.h>
//# include <sys/types.h>
//# include <stdio.h>
//# include <stdlib.h>
//typedef int semaphore;
//void sem_init(semaphore *, int);
//void P(const semaphore *);
//void V(const semaphore *);
//void sem_destroy(const semaphore *);
//# define binary_sem_init(s) sem_init(s, 1);
//#endif
//sem.c
//#include "sem.h"
//static struct sembuf acquire = {0, -1, SEM_UNDO},
//release = {0, 1, SEM_UNDO};
//void sem_init(semaphore *s, int value)
//{
//*s = 0;
//if ((*s = semget(0, 1, IPC_CREAT | IPC_EXCL | 0600)) == -1) {
// perror("sem_init: semget: ");
// exit(1);
//}
//if(semctl(*s, 0, SETVAL, value) == -1) {
// perror("sem_init: semctl: ");
// exit(1);
// }
//}
//void P(const semaphore *s)
//{
//if (semop(*s, &acquire, 1) == -1) {
// perror("P: ");
// exit(1);
//}
//}
//void V(const semaphore *s)
//{
//if (semop(*s, &release, 1) == -1) {
// perror("V: ");
// exit(1);
//}
//}
//void sem_destroy(const semaphore *s)
//{
//if (semctl(*s, 0, IPC_RMID, NULL) == -1) {
// perror("sem_destroy: semctl: ");
// exit(1);
//}
//}
ASKER
its ok ewest,
I am done with it.
I am done with it.
Congrats!
ASKER
No its not an official homework excerise but sort of sample question, which I need to practise for exam.