Solved

Standard Out

Posted on 1997-08-17
9
297 Views
Last Modified: 2006-11-17
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
0
Comment
Question by:mravell
  • 4
  • 4
9 Comments
 
LVL 1

Expert Comment

by:cph
ID: 1253280
For a file you should use fgetc and fputc.

Hope this help :)

      CpH
0
 

Author Comment

by:mravell
ID: 1253281
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







0
 

Expert Comment

by:easterbk
ID: 1253282
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.
0
 

Author Comment

by:mravell
ID: 1253283
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.

0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Accepted Solution

by:
easterbk earned 70 total points
ID: 1253284
What if you change stdout to be binary mode? What is happening is the OS is treating the output stream as a ascii (non-binary) file and creating CRLF pairs for each new line character output.
On my system (HPUX) the c_oflag value ONLCR controls mapping of newline to CRLF pairs on output, this is controlled by termio(7). If you are on a Unix system do a "man 7 termio" and look for c_oflag or ONLCR, this will tell you how to do it on your system. On non-Unix, look up in your compiler library help.
This is not really a C problem but an OS/platform issue, but since such questions are asked so often they are usually answered as if they were, although answers are often not portable.
Look in the C FAQ (comp.lang.c Newsgroup) for discussion on this.
0
 

Expert Comment

by:easterbk
ID: 1253285
More info:
On i86 using Microsoft compiler, change mode as follows:

_setmode(_fileno(stdout),_O_BINARY);
0
 

Author Comment

by:mravell
ID: 1253286
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
0
 

Expert Comment

by:easterbk
ID: 1253287
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.
0
 

Author Comment

by:mravell
ID: 1253288
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
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now