pzozulka
asked on
C Programming: Returning array of char pointers
I'm having trouble with my code (deflect.c), and can't figure it out for the past 12 hours.
On line 407, I call the readConfig() method, but it returns nothing, and my log file has almost nothing written to it.
Inside the readConfig() method, on line 285, I call the fetchHTML() method, and it seems to return the string I need because when I do fprintf(), I can see it in the log file for the readConfig() method. But when I try to return the that string, nothing gets returned.
Question:
Am I calling and returning my array of chars correctly in fetchHTML() and readConfig() methods? If so, then what else can be causing the issue?
Below is the C file, called "deflect.c". It's the "server" side of things.
For testing purposes, I am also including the "client" C file called "twist.c", as well as the config.txt file.
Example situation:
./deflect 1 config.txt 1 9000
./twist http://www.facebook.com 9000
deflect.c
twist.c
config.txt
On line 407, I call the readConfig() method, but it returns nothing, and my log file has almost nothing written to it.
Inside the readConfig() method, on line 285, I call the fetchHTML() method, and it seems to return the string I need because when I do fprintf(), I can see it in the log file for the readConfig() method. But when I try to return the that string, nothing gets returned.
Question:
Am I calling and returning my array of chars correctly in fetchHTML() and readConfig() methods? If so, then what else can be causing the issue?
Below is the C file, called "deflect.c". It's the "server" side of things.
For testing purposes, I am also including the "client" C file called "twist.c", as well as the config.txt file.
Example situation:
./deflect 1 config.txt 1 9000
./twist http://www.facebook.com 9000
deflect.c
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <errno.h>
#include <malloc.h>
#define DAEMON_NAME "vdaemon"
char ** fetchHTML(char *uri, char *host) {
FILE *fpHTML=NULL;
// Open a log file in write mode.
fpHTML = fopen ("/home/users1/pz951772/html_log.txt", "w+");
fprintf(fpHTML, "Logging info...\n");
struct hostent *h;
struct in_addr **addr_list;
if((h = gethostbyname(host)) == NULL) {
fprintf(fpHTML, "Couldn't get host by name.\n");
fflush(fpHTML);
return NULL;
}
else {
fprintf(fpHTML, "gethostbyname() success.\n");
}
addr_list = (struct in_addr **)h->h_addr_list;
const char *ipAddr = inet_ntoa(*addr_list[0]); //gethostbyname
fprintf(fpHTML, "IP addr: %s\n", ipAddr);
socklen_t peer_addr_size;
int conStatus;
const char *protocolName = "tcp";
int sockfd;
struct protoent *myProtocol = getprotobyname(protocolName);
struct sockaddr_in sockIP4addr;
struct sockaddr *peerSockAddr;
int max_input = 4000;
char **buffer;
buffer = malloc( max_input * sizeof(char*));
if(!buffer) {
fprintf(fpHTML, "Couldn't malloc buffer.\n");
fflush(fpHTML);
return NULL;
}
else {
fprintf(fpHTML, "malloc buffer success.\n");
}
size_t count = 4000;
ssize_t bytes_read;
size_t requestLen;
sockIP4addr.sin_family = AF_INET;
sockIP4addr.sin_port = htons(80);
// store IP addr in sockIP4addr structure
inet_pton(AF_INET, ipAddr, &sockIP4addr.sin_addr);
sockfd = socket(AF_INET,SOCK_STREAM,myProtocol->p_proto);
if(sockfd == -1)
fprintf(fpHTML, "socket() error: %s\n", strerror(errno));
else {
fprintf(fpHTML, "socket() success.\n");
}
peer_addr_size = sizeof(struct sockaddr_in);
peerSockAddr = (struct sockaddr*)&sockIP4addr;
// Connect
conStatus = connect(sockfd, peerSockAddr, peer_addr_size);
if(conStatus == -1)
fprintf(fpHTML, "connect() error: %s\n", strerror(errno));
else {
fprintf(fpHTML, "connect() success.\n");
}
char *strRequest;
int myB;
if((myB = sprintf(strRequest, "GET %s HTTP/1.1\r\nHOST: %s\r\n\r\n",uri,host)) < 0)
fprintf(fpHTML, "sprintf() error: %s\n", strerror(errno));
else {
fprintf(fpHTML, "sprintf() success.\n");
}
fflush(fpHTML);
requestLen = strlen(strRequest);
fprintf(fpHTML, "%s\n", strRequest);
if((write(sockfd, strRequest, requestLen)) < 0)
fprintf(fpHTML, "write() error: %s\n", strerror(errno));
else {
fprintf(fpHTML, "write() success.\n");
}
if(( bytes_read = read(sockfd, buffer, count)) == -1) {
fprintf(fpHTML, "read() error: %s\n", strerror(errno));
}
else {
buffer[bytes_read]='\0';
fprintf(fpHTML, "read() success.\n");
fprintf(fpHTML, "%s\n", buffer);
}
fflush(fpHTML);
return buffer;
}
int readConfig(const char *config, char *host) {
FILE *configfp=NULL;
struct stat st;
ssize_t bytes_read;
size_t count = 400;
char *buffer;
char *ch;
char *Lines[100];
char LastChar;
int fd;
int LineCount;
off_t size;
stat(config, &st);
size = st.st_size;
buffer = (char *) malloc(size + 1);
// Open a log config file in write mode.
configfp = fopen ("/home/users1/pz951772/config_log.txt", "w+");
fprintf(configfp, "Config Log...\n");
// open config file
if( (fd = open(config, O_RDWR)) == -1 ) {
fprintf(configfp,"open() error: %s: %s\n",strerror(errno),config);
fflush(configfp);
}
// read config file line by line
if(( bytes_read = read(fd, buffer, size)) == -1) {
fprintf(configfp, "read() error: %s\n", strerror(errno));
fflush(configfp);
}
else if( bytes_read == 0) { /* EOF */
fprintf(configfp, "zero bytes read.\n");
fflush(configfp);
}
else {
// with \r\n in each end of line in buffer, file is one long string
// make all lines end with 0, and make them behave as strings
buffer[size] = '\0';
for(ch = buffer; *ch; ++ch) {
if(*ch == '\r' || *ch == '\n')
*ch = '\0';
}
// build array of pointers, pointing to each line in config
for(LineCount=0,LastChar='\0',ch=buffer;ch-buffer < size; ++ch){
if(LastChar == '\0') {
if(*ch) // ignore consecutive zero characters
Lines[LineCount++] = ch;
}
LastChar = *ch;
}
close(fd);
// parse host to strip http:// and any dirs
// *************************************
char src[50];
char dest[100];
char *httpProto = "http://";
if((strstr(host, httpProto)) != NULL) { //does host contain http://
memset(dest, '\0', sizeof(dest));
strcpy(dest, host+strlen(httpProto));
fprintf(configfp,"Stripped HTTP:\n%s\n",dest);
// http:// stripped -- use dest
}
// *************************************
// copy chars off to the hostName until you find "/" or '\0'
// *************************************
char request[50];
char hostName[100];
int a = 0, b = 0, forwardSlash = 0;
// **********USE DEST************
if((strstr(host, httpProto)) != NULL) { // host contains http://
for(a=0; dest[a] != '\0'; a++) { //copy domain name into hostName
if(dest[a] != '/') {
hostName[a] = dest[a];
}
else { // forward slash found
forwardSlash = 1;
break;
}
}
if(dest[a] == '\0')
hostName[a] = '\0';
while( (forwardSlash == 1) && (dest[a] != '\0')) {
request[b] = dest[a];
a++;
b++;
}
if( (forwardSlash == 1) && (dest[a] == '\0'))
request[b] = '\0';
}
// **********USE HOST***************
else { // host didn't contain http:// to begin with
for(a=0; host[a] != '\0'; a++) { //copy domain name into hostName
if(host[a] != '/') {
hostName[a] = host[a];
}
else { // forward slash found
forwardSlash = 1;
break;
}
}
if(host[a] == '\0')
hostName[a] = '\0';
while( (forwardSlash == 1) && (host[a] != '\0')) {
request[b] = host[a];
a++;
b++;
}
if( (forwardSlash == 1) && (host[a] == '\0'))
request[b] = '\0';
}
if(forwardSlash == 0) {
request[0] = '/';
request[1] = '\0';
}
fprintf(configfp,"Host:\n%s\n",host);
fprintf(configfp,"Domain:\n%s\n",hostName);
fprintf(configfp,"Request: \n%s\n",request);
// *************************************
int i,j,k,m=0;
char *t1;
char **html;
for(i=0; i < LineCount; i++) { // for each line,
// check if hostName in config file
// and fetch HTML
if(*Lines[i] != '#') { // ignore comment lines
fprintf(configfp,"%s\n",Lines[i]);
fprintf(configfp,"%s\n",host);
char *p;
//if( p[19] != '~' )
if((p = strstr(Lines[i], host)) != NULL) {
// found host in config file
fprintf(configfp, "R:%c %d\n",p[19],p[19]);
if(strstr(Lines[i], "redirected") != NULL) {
// ***************************************
if((html=fetchHTML(request, hostName)) != NULL)
fprintf(configfp,"Redirected:\n%s\n\n",html);
else
fprintf(configfp,"fetchHTML() error.\n");
fprintf(configfp, "\nReidrected: Return 1\n");
fflush(configfp);
return 1;
}
else if(strstr(Lines[i], "filtered") != NULL) {
// ***************************************
fflush(configfp);
return 2;
}
else if(strstr(Lines[i], "cached") != NULL) {
// ***************************************
if((html=fetchHTML(request, hostName)) != NULL)
fprintf(configfp,"Cached:\n%s\n\n",html);
else
fprintf(configfp,"fetchHTML() error.\n");
fflush(configfp);
return 3;
}
}
else { // couldn't find host in config file
m = -1;
}
}
}
// ***************************************
if((html=fetchHTML(request, hostName)) != NULL)
fprintf(configfp,"Not in config:\n%s\n\n",html);
else
fprintf(configfp,"fetchHTML() error.\n");
fflush(configfp);
fclose(configfp);
return m;
}
}
void communicate(const char *port, const char *conf) {
FILE *fp=NULL;
socklen_t peer_addr_size;
const char *protocolName = "tcp";
const char *ipAddr = "127.0.0.1";
int portNo = atoi(port); //argc = 5
int sockfd, csockfd, bindStatus, listenStatus, conStatus;
int mybacklog = 50;
int my_inet_addr_len = 16;
struct protoent *myProtocol = getprotobyname(protocolName);
struct sockaddr_in sockIP4addr, peerIP4addr;
struct sockaddr *mySockAddr, *peerSockAddr;
int max_input = 200;
char buffer[max_input];
size_t count = 200;
ssize_t bytes_read;
size_t blen;
char peerIPstr[INET_ADDRSTRLEN];
// Open a log file in write mode.
fp = fopen ("/home/users1/pz951772/log.txt", "w+");
fprintf(fp, "Logging info...\n");
fflush(fp);
sockIP4addr.sin_family = AF_INET;
sockIP4addr.sin_port = htons(portNo);
inet_pton(AF_INET, ipAddr, &sockIP4addr.sin_addr);
// Create Socket
sockfd = socket(AF_INET,SOCK_STREAM,myProtocol->p_proto);
if(sockfd == -1)
perror("socket() error");
else
fprintf(fp, "socket() success\n");
mySockAddr = (struct sockaddr*)&sockIP4addr;
// Bind Socket
bindStatus = bind(sockfd, mySockAddr, sizeof(struct sockaddr_in));
if(bindStatus == -1)
fprintf(fp, "bind() error %s\n", strerror(errno));
else
fprintf(fp, "bind() success\n");
// Listen
if (listen(sockfd, mybacklog) == -1)
fprintf(fp, "listen() error: %s\n", strerror(errno));
else
fprintf(fp, "listen() success\n");
peer_addr_size = sizeof(struct sockaddr_in);
peerSockAddr = (struct sockaddr*)&peerIP4addr;
// Accept connections - peerSockAddr is filled in with RemoteAddr
csockfd = accept(sockfd, peerSockAddr, &peer_addr_size);
if(csockfd == -1)
fprintf(fp, "accept() error %s\n", strerror(errno));
else {
fprintf(fp, "Accepted()\nPeer port: %d\nMy port: %d\n", ntohs(peerIP4addr.sin_port),ntohs(sockIP4addr.sin_port));
fprintf(fp, "Peer IP: %s\n", inet_ntop(AF_INET, &peerIP4addr.sin_addr, peerIPstr, INET_ADDRSTRLEN));
}
char *reply="";
do
{
fprintf(fp, "Logging info while...\n");
if(( bytes_read = read(csockfd, buffer, count)) == -1)
fprintf(fp, "read() error %s\n", strerror(errno));
else {
buffer[bytes_read]='\0';
int hostExist = 0;
if((hostExist = readConfig(conf, buffer)) == -1) {
reply = "host does not exist\n";
}
else if( hostExist == 1) {
reply = "host redirected\n";
}
else if( hostExist == 2) {
reply = "host filtered\n";
}
else if( hostExist == 3) {
reply = "host cached\n";
}
else {
reply = "error on readConfig()\n";
}
fprintf(fp, "%s\n", reply);
fflush(fp);
}
sleep(1);
blen = strlen(reply);
if((write(csockfd, reply, blen)) < 0)
fprintf(fp, "write() error %s\n", strerror(errno));
else
fprintf(fp, "write() success: %s\n", reply);
fflush(fp);
} while (0);
fclose(fp);
}
int main( int argc, char *argv[] ) {
//Set our Logging Mask and open the Log
/*setlogmask(LOG_UPTO(LOG_NOTICE));
openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
syslog(LOG_INFO, "Entering Daemon");
*/
pid_t process_id = 0, sid = 0;
// Get Current Working Directory
long sizeCWD;
char *bufCWD;
char *ptrCWD;
sizeCWD = pathconf(".", _PC_PATH_MAX);
if(( bufCWD = (char *)malloc((size_t)sizeCWD)) != NULL)
ptrCWD = getcwd(bufCWD, (size_t)sizeCWD);
// Specify absolute path for config file
strcat(ptrCWD, "/");
strcat(ptrCWD, argv[2]);
// Create child process
process_id = fork();
// fork() failure
if (process_id < 0)
{
printf("fork failed!\n");
// return exit status
exit(1);
}
// PARENT PROCESS -- KILL IT
if (process_id > 0)
{
printf("process_id of child process %d \n", process_id);
// return success in exit status
exit(0);
}
//unmask the file mode
umask(0);
// set new session
sid = setsid();
if(sid < 0)
{
// Return failure
exit(1);
}
// Change the current working directory to root
chdir("/");
// Close stdin. stdout and stderr
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//-------------------
//Main Process
//-------------------
communicate(argv[4], ptrCWD);
//Close the log
//closelog();
}
twist.c
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
int main( int argc, char *argv[] ) {
socklen_t peer_addr_size;
int conStatus;
const char *protocolName = "tcp";
const char *ipAddr = "127.0.0.1";
int sockfd;
struct protoent *myProtocol = getprotobyname(protocolName);
struct sockaddr_in sockIP4addr;
struct sockaddr *peerSockAddr;
int max_input = 200;
char buffer[max_input];
size_t count = 200;
ssize_t bytes_read;
size_t hostlen;
sockIP4addr.sin_family = AF_INET;
sockIP4addr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET, ipAddr, &sockIP4addr.sin_addr);
sockfd = socket(AF_INET,SOCK_STREAM,myProtocol->p_proto);
if(sockfd == -1)
perror("socket() error");
peer_addr_size = sizeof(struct sockaddr_in);
peerSockAddr = (struct sockaddr*)&sockIP4addr;
// Connect
conStatus = connect(sockfd, peerSockAddr, peer_addr_size);
if(conStatus == -1)
perror("connect() error");
const char *host = argv[1];
hostlen = strlen(host);
if((write(sockfd, host, hostlen)) < 0)
perror("write() error");
if(( bytes_read = read(sockfd, buffer, count)) == -1)
perror("read() error");
else if( bytes_read == 0) {
exit(1);
}
else {
buffer[bytes_read]='\0';
}
printf("%s\n", buffer);
}
config.txt
# Example Configuration File for deflect:
# deflect: Daemon for HTTP Egress, Filtering, Load balancing, and Caching Trivially
#
# URL-prefix Disposition Host list
http://www.csun.edu/ redirected 130.166.238.195, redwing.csun.edu
http://www.facebook.com/ filtered
http://www.csun.edu/~steve/ cached www.csun.edu
# Note that any URL that is not covered by any rule is transferred through the system
# without any additional processing.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.