Link to home
Start Free TrialLog in
Avatar of mravell
mravell

asked on

Standard Out

I am working on a cgi program that pipes a designated file through the standard out. This is so that I can send a file to a browser that is not under my doc root. Trouble is that when I send a file that is not just plain ASCII things get screwed up.

My test uses the following code:

  fp = fopen(lFilename, "rb");
  if (fp == NULL)
  {
    printf("File failed to open\n");
    return(0);
  }

  while((c = getc(fp)) != EOF)
    putchar(c);


Now, by rights this should just read a byte from the file and wwrite it to the standard out. I do get a file written but it is not exactly the same as the source. Does the standard out modify certin ascii values somehow?

I suspect that there may be some problem with either null, CRLF or EOF characters. Any ideas?


Regards
Marty
Avatar of cph
cph

For a file you should use fgetc and fputc.

Hope this help :)

      CpH
Avatar of mravell

ASKER

I've tried fgetc and fputc but to no avail.

From looking at the source and result files it seems that some characters are not output correctly. (I run the program on the command line with C:>grab source.exe > result.exe and then compare the two files)

I'll try to find an editor that can display the actual ascii codes to get a better idea today.

Is it possible that the fgetc and/or the fputc are not working as I would expect? Maybe it is something with the fact that the fgetc returns an int. (signed by default as far as I can work out). Now the result can be a -1 to indicate EOF so I need to make the c variable a signed type. What happens if the byte being read is > the signed max number?

I tried reading the byte into a short and then testing to see if it was -1 (for eof) and then fputc if it wasn't but this didn't seem to work either.

Very confusing! Any ideas? I thought that this would be a really simple program! What I need is a program that I can run from the command line like

C:>prog sample.exe > piped.exe

and get piped.exe to be byte for byte identical to sample.exe.




Regards
Marty







Ensure that c is declared as int type:

int c;

(getc & fgetc return an int, this is because the EOF return cannot be a valid character and assuming 8bit characters, all 256 possible values represent valid characters, so on a 32 machine all valid characters are returned as integers in the range 0x00000000 to 0x000000ff, with EOF not in this range, usually 0xffffffff (-1) but you should use the EOF define from the standard header files and not define your own).

If this does not solve the problem, run a binary compare to show what bytes are being changed, this may give a clue.
Avatar of mravell

ASKER

I've done some more testing and found that the program is inserting ASCII 13 in front of each ASCII 10 that it finds. Why would the standard out automatically do this? Is there a way of stopping it?

If I manually edit out the extra 13's I end up with a workable file!

Here is the source as it stands now:

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

int main(int argc, char *argv[])
{
  FILE *fp;
  int c;
  char lFilename[256];

  strcpy(lFilename, argv[1]);

  fp = fopen(lFilename, "rb");
  if (fp == NULL)
  {
    printf("File failed to open\n");
    return(0);
  }

  do
  {
    c = fgetc(fp);
    putchar(c);
  } while (c != EOF);

  fclose(fp);
  return(0);
}


Regards
Marty

PS. I also get an extra FF (256) at the end of the file but think I can get rid of it by changing the while loop or putting an if condition on the putchar.

ASKER CERTIFIED SOLUTION
Avatar of easterbk
easterbk

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
More info:
On i86 using Microsoft compiler, change mode as follows:

_setmode(_fileno(stdout),_O_BINARY);
Avatar of mravell

ASKER

This is an i386 app but if I add your line (for setting the mode) I get the following errors.


-----------Configuration: Grab - Win32 Release----------
Compiling...
grab.c
C:\Development\CGI\Grab\grab.c(13) : warning C4013: '_setmode' undefined; assuming extern returning int
C:\Development\CGI\Grab\grab.c(13) : error C2065: '_O_BINARY' : undeclared identifier
Error executing cl.exe.
grab.obj - 1 error(s), 1 warning(s)



Am I missing a header?

M
I assume you are using MSVC++ 4.x or 5.0. The help for 4.1 _setmode() states the following:
Required header: io.h
Optional headers: fcntl.h

I suggest you try adding firstly io.h and if that doesn't work fcntl.h.
If both of these fail, look up _setmode in your InfoViewer search and see what it says there.
Avatar of mravell

ASKER

Thanks for the assist.

I installed the help and found this stuff this morning. Works like a charm.

I found I needed both the headers. io.h is OK for the _setmode but the constant _O_BINARY seems to be defined in fcntl.h.


Regards
Marty