Link to home
Start Free TrialLog in
Avatar of pzozulka
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
#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();
   
}

Open in new window


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


}

Open in new window


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.

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of chaau
chaau
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial