simple server-side language

enasni_mark
enasni_mark used Ask the Experts™
on
I am making a very very simple server-side scripting language.
All i want to do at the moment is read the file and send the file's text to the browser.
No alterations to the source as yet.

I have this code but it crashes everytime just after printing the filename.
I'm very new to C so there is probably something stupidly wrong.
Can you please help?

Code:

#include <stdlib.h>
#include <string.h>

void Code(char *webPage)
{
      FILE *source;
      char *script;
      source = fopen(webPage, "r");
      fread(&script, sizeof(script), 1, source);
      fclose(source);
      fprintf(stderr, webPage, webPage);
      if (script == "") {
            fprintf(stderr, "No text in file.\n\n", webPage);
      }
      else {
            fprintf(stderr, script, webPage);
      }
}
int main(int argc,char *argv[])
{
      fprintf(stderr, "Content-type: text/html\n\n");
      if (argc == 1) {
            fprintf(stderr, "No file has been specified.\n\n");
            return 1;
      }
      else {
            Code(argv[1]);
            return 0;
      }
}
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
"fread(&script, sizeof(script), 1, source);"
I think you have to allocate memory to script before to use it, if you want script to be 4 bytes long, for example, then, script = malloc(4); .... and do not use sizeof(script), it will always return the same as sizeof(char *), not the actual size of the data pointed

"fprintf(stderr, webPage, webPage);"
I didn't tested you code, but this line is error prone. What will happen if webpage == "foobar %d %d"? I guess you misunderstood fprintf function, check its sintax again (this line will not print webPage twice, as I guess you imagined)


Author

Commented:
no, i had the webPage, webPage part because LCC's simple program added it.
I will get rid of it though.
As i said, i am very new to C (i only started programming anything this morning)
I have no idea what any of the Malloc thing means, can you please give me an example of what you are saying so i can understand what you mean.
Let's suppose you want to read 10 bytes from the file .... the, code will look like this

char *script;                          // Here you declare the pointer variable. It still points to nothing
script = malloc(10);               // Here you reserve 10 bytes in memory and make script point to that area (malloc = memory allocate)
fread(script,10, 1, source);   // Here you read 10 bytes from the file and store it in the previously allocated memory

Understand it now? : ) I hope so
OWASP: Threats Fundamentals

Learn the top ten threats that are present in modern web-application development and how to protect your business from them.

Top Expert 2005

Commented:
    if (script == "") { ... }

script is a pointer to characters (which as knightmad mentioned has not been allocated).
Logical comparison operators on pointers compare the values of memory addresses.
To compare the string pointed to by script to another string, you need to dereference the
pointer.  

However, ANSI C only supports binary, unary, and logical operations on it atomic
types, which don't include compound objects such as arrays, structs, and strings
(which are actually arrays of char).  In other words, you can compare a single char
to another char, but you cannot compare two arrays of chars directly using == < >.

The standard C library provides functions that can be called to compare such compound
objects.  Since strings are so commonly used, there is an abundance of string manipulation
functions:  strlen, strdup, strcmp, strcpy, strchr, strstr, etc.   You can find them all prototyped
in <string.h>  For comparing two strings, there is strcmp() which returns 0, if they are
identical.  So a correct comparison would be   if (strcmp(script, "") == 0) {...}.

But empty strings are a bit easier to deal with when you understand the underlying
mechanism.  In C, strings are a series of characters terminated with the NUL character '\0'.
In an empty string, the NUL is the first (and only) character in the string.   So we can
quicky determine if a string is empty by checking its first character for NUL.  So the following
syntax is commonly seen in C programs:   if (script[0] == '\0') {...}
 
Since script is technically a pointer to a char, then dereferencing the pointer yields a char.
So *script returns the first char in the string pointed to by the script.  So the following
syntax is also commonly seen in C programs:   if (*script == '\0') {...}.

I've touched on one of the idiosyncrasies of C, the interchangeable use of pointer and array
nomenclatures.  See http://www.themost.org/courses/langs/eoc/lessons/eoc_04.html#Heading1
brett: Sorry, I think I didn't made myself clear enough when I said "What will happen if webpage == "foobar %d %d"" I actually meant "What will happen if webpage is equal to "foobar %d %d"" ... Nothing related to really compare char * using == operator.
brett: Oh, sorry (again), ignore my previous post, I misread your comment : )

Author

Commented:
ok, i have got it kind of working now. But instead of giving a specific length of script, i want it to output the complete file.
I'm sorry if you have already explained this, but i am kind of slow :)

Author

Commented:
i have tried using the sizeof(script) but it comes up with some strange characters after the first line of the file
Top Expert 2005

Commented:
The original posted code has too many errors to infer your recent changes.
Please repost the current code.
Let me see if I understood ... You want to read the entire file and write it to stderr? If yes, read, understand and test the following code. Could I ask you why to output to stderr and not to stdout? stderr is usually used to output program errors, while stdout is the common  output.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void Code(char *webPage)
{
  FILE *source;
  char *script;
  int fsize;
  // Open file
  source = fopen(webPage, "r");
  // Determine the length of the file
  fseek(source, 0, SEEK_END);
  fsize = ftell(source);
  fseek(source, 0, SEEK_SET);
  // Allocate memory to store the file
  script = malloc(fsize);
  // Read the entire file
  fread(script, fsize, 1, source);
  // Close the file
  fclose(source);
  //  Print
  fprintf(stderr, "%s\n",webPage); // <---------- This is the way to print a string, notice the %s
  if (fsize <= 0) {
    fprintf(stderr, "No text in file.\n\n", webPage);
  }
  else {
    fprintf(stderr, script, webPage);
  }
}

int main(int argc,char *argv[])
{
  fprintf(stderr, "Content-type: text/html\n\n");
  if (argc == 1) {
    fprintf(stderr, "No file has been specified.\n\n");
    return 1;
  }
  else {
    Code(argv[1]);
    return 0;
  }
}
Top Expert 2005

Commented:
It appears that you still don't understand how to use fprintf.
The second argument is a format string that instructs printf
how to interpret the rest of the arguments.  

You get it right with
   fprintf(stderr, "%s\n",webPage); // <---------- This is the way to print a string, notice the %s
but get it wrong again with
   fprintf(stderr, "No text in file.\n\n", webPage);
which should be
   fprintf(stderr, "No text in file %s.\n\n", webPage);

fprintf (and printf) is for formatted output to a stream.
They take a format string with specifications that tells
printf how to interpret and format for output the rest
of the arguments passed to the function.  

If you want to print a single string out to the stream,
use fputs rather than fprintf. Like this
  fputs("Hello World\n", stdout);


Finally we get to
   fprintf(stderr, script, webPage);
which treats the data you read from the file as if it were
a printf format string for printing the name of the file.
That is probably not what you want, unless the file contains
a string of text like this:
  "The name of this file is %s \n\0"

By your previous errors, I will assume you were using fprintf
incorrectly and actually wish to dump the data you read from
the file (contained in the script buffer) to stderr.

Lets move to the other problem: the output you see is the contents
of the file and some junk.  I will ignore the possibility that the file
actually is a printf format string with a format other than %s.

The most likely reason you are getting junk output is the fact that
the buffer of text you read from the file is not NUL-terminated.
C strings are terminated with a NUL character (byte of 0).  fputs
and fprintf expect NUL-terminated strings as input.  fread
does not automatically append a NUL byte to the data it read into
the buffer you supplied.  When you pass the buffer to fprintf,
it prints the text in the buffer, then keeps printing all bytes it sees
until it encounters a NUL.  You will have to NUL-terminate the buffer,
but remember to allocate enough memory to hold the extra byte.


  // Allocate memory to store the file + NUL terminator
  script = malloc(fsize + 1);
  // Read the entire file
  bytesRead = fread(script, fsize, 1, source);
  script[bytesRead] = '\0';

Notice that this pays attention to how many bytes are actually read
into the buffer, then puts the NUL after that.


Lastly, the size of the buffer needs to be considered.  You are declaring
the variable fsize as an int, but ftell returns a long.  If you are on a
system where sizeof(int) != sizeof(long), you could truncate the filesize.
On top of that, malloc and fread use size_t as the type for the allocated
buffer size.   Is size_t an int, a long, a long long (int64)?  You need to
carefully consider these issues.  In your case, MAXINT is probably 2^31-1
which is safe if your web page is less than 2 GB in size.  But what if the
file is only 1GB in size.  You will try to malloc 1GB of memory.  Depending
on your system, this might work, albeit slowly.   Experienced programmers
will usually limit the size of the allocated buffer (usually 4KB - 64KB).
If the size of the file exceeds the size of the buffer,  the program will read
and the file in chunks until the whole file has been read.   You don't need
to worry about that for your example program, but keep it in mind for
hard development.










" It appears that you still don't understand how to use fprintf."
Sorry, my mistake, hehehe. I only copied + pasted the code above, I was focusing on the 1st part of the code, the reading part .............
Are you sure you are talking with right person? I mean, I suppose you took me by the questioneer : ) I have no doubt about the use of fprintf, but thank you
for point my error to questioneer
"I only copied + pasted the code above"
Well, not the entire code ... I changed the reading part and that commented fprintf (fprintf(stderr, "%s\n",webPage);)
The rest I left almost unchanged : )

Author

Commented:
as i have said, i don't know C at all. I only started doing anything with it about 10 hours ago
but thank you all for you contributions, i have got it to work now.
the thing about the fprintf i still don't understand but i will re-read it in the morning and see if understand then.

Thank you
Top Expert 2005

Commented:
Sorry, knightmad, I did mistake you for the questioner since your post (with modified code)
appeared after I had ask him to repost his code.  I will try to pay more attention next time.

Author

Commented:
There is another problem i have found with it. If the file it is reading is empty, i wanted it to print the "No text in file." but instead it prints "Ð".
If there some kind of error handler for this?

Author

Commented:
I have just reallised, also, that after changing it to read the full length of the file, it now returns "" at the end if it is 1 less than a multiple of 3 and "" at the end if it is two less than a multiple of 3.
I have no idea what this i caused by
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void Code(char *webPage)
{
 FILE *source;
 char *script;
 long int fsize;                                   // brettjohnson suggestion

 source = fopen(webPage, "r");
 fseek(source, 0, SEEK_END);
 fsize = ftell(source);
 fseek(source, 0, SEEK_SET);
 script = malloc(fsize+1);                    // Well observed by brettjohnson
 fread(script, fsize, 1, source);
 script[fsize] = 0;
 fclose(source);
 fprintf(stdout, "%s\n",webPage);     // All fprintf updated, better to write to stdout
 if (fsize <= 0) {
   fprintf(stdout, "No text in file %s.\n\n", webPage);
 }
 else {
   fprintf(stdout, "%s", script);
 }
}

int main(int argc,char *argv[])
{
 fprintf(stdout, "%s", "Content-type: text/html\n\n");
 if (argc == 1) {
   fprintf(stdout, "%s", "No file has been specified.\n\n");
   return 1;
 }
 else {
   Code(argv[1]);
   return 0;
 }
}
I corrected some errors in my previous code and posted above .... Thank brettjohnson for noticing those errors

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial