Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
• Status: Solved
• Priority: Medium
• Security: Public
• Views: 281

# 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

0
ashi2
• 8
• 6
1 Solution

Commented:
This sounds like a homework exercise... Correct me if I am wrong.

As a general approach:

Create an array of structs, where each struct has two fields: name of country and name of capital

Each request for a capital amounts to a table lookup:

for (i = 0; i < N; i++) {
if (!strcmp(countries[i].country, user_input) {
break;
}
}

if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}

I'll leave the rest to you...
0

Author Commented:
Thanx! evest, I think I got a idea of how to do I will do it and submit again to chk if i am doing right.

No its not an official homework excerise but sort of sample question, which I need to practise for exam.

0

Author Commented:
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].country, user_input) {
break;
}
}

if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}

0

Commented:
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.

0

Author Commented:
what is the pupose of NULL NULL, not very clear with it
0

Commented:
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 }};

0

Author Commented:
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" },
{"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].country, user_input) {
break;
}
}
if (i == N) {
printf("unknown country\n");
} else {
printf("capital = %s\n", countries[i].capital);
}
}
0

Commented:
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(countries[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].Country, 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?

0

Author Commented:
no not really, but still its high level and I am not good at it
0

Author Commented:
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.

0

Commented:
I'd prefer to keep the "conversation" here in EE.

What errors are you getting?

Can you just post the relevant code snippets?
0

Author Commented:
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);
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;

// 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) {
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;

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;
}

/* Parse URI from GET request */
is_static = parse_uri(uri, filename, cgiargs);
if (stat(filename, &sbuf) < 0) {
"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",
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 */

/*
*/
{
char buf[MAXLINE];

while(strcmp(buf, "\r\n"))
return;
}

/*
* 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);
//}
//}

0

Author Commented:
its ok ewest,

I am done with it.
0

Commented:
Congrats!
0

## Featured Post

• 8
• 6
Tackle projects and never again get stuck behind a technical roadblock.