tags:

views:

44

answers:

2

During the course of my program,

  1. I pass the output of an execv() to a file, for logging, (using the outCopy() function)
  2. and then print it back on screen to simulate stdout output. (using the printFile() function)

The 2 functions are:

void printFile(char *fileName)
{
    char *fileContent=(char *)malloc(200*sizeof(char));                 /* sufficiently large buffer */
    if((filePtr=fopen(fileName,"r"))==NULL)
    {
        printf("Error opening %s: %s\n",fileName,strerror(errno));
        if( (strcmp(fileName,"/tmp/command.log")==0) || (strcmp(fileName,"/tmp/output.log")==0) ){exitStatus=255;}
    }
    else
    {
        while(fscanf(filePtr,"%s",fileContent)!=EOF)   
        {
            printf("%s",fileContent);
            printf("%c",fgetc(filePtr));
        }
        fclose(filePtr);
    }
}

void outCopy(char *fileName)   
{
    char *fileContent=(char *)malloc(200*sizeof(char));                 /* sufficiently large buffer */
    if( (filePtr=fopen(fileName,"r"))==NULL || (filePtr2=fopen("/tmp/output.log","a"))==NULL )
    {
        printf("Error opening files: %s\n",strerror(errno));
    }
    else
    {
        while(fscanf(filePtr,"%s",fileContent)!=EOF)   
        {
            fprintf(filePtr2,"%s",fileContent);
            fprintf(filePtr2,"%c",fgetc(filePtr));
        }
        fclose(filePtr);
        fclose(filePtr2);
    }
}

However, my neat little scheme gets disturbed for the output of the ls command:

Expected output:

a.c c.c e.c
b.c d.c

Current output:

a.c
b.c
c.c
d.c
e.c

How can I change either or both of my functions to get the proper output?

(Please don't suggest using pipes or tees, or I will have to change a major portion of my exec() calling child)

Edit: Please note that both the outCopy() & the printFile() are run by the parent. Output has already been dup2() ed to the required temp file by the child.

+2  A: 

Some versions of ls (including the GNU version used in Linux) detect whether they are being run with a terminal or with a pipe as standard output, and change their formatting. If you want exactly the same output, you'll need to create a pseudo-TTY (pty) using the posix_openpt call and friends. Or you can use the script utility, which takes care of this for you.

Another option is to use the -C option to ls to force columnar layout; however, this may not be exactly the same, as ls won't know the width of your terminal, and may assume the wrong width. Additionally, other features such as colored output may be missing.

bdonlan
@bdonlan, is colored output a feature of ls or of the shell? I saw a variable in env which had the name "LS_COLORS"
Kedar Soparkar
**though I found that because my program SEGFAULTed on env command, as the line had 1279 characters :)
Kedar Soparkar
Colored output is a feature of `ls`, not the shell. However, the shell initialization scripts may set up `LS_COLORS` and the aliases to enable colors - this is not a feature of your shell, but rather of your linux distribution.
bdonlan
+2  A: 

When stdout is not a tty, ls changes behavior from user-friendly columns to script-friendly lists. The flag ls -C forces columnar output regardless of the type of device stdout is attached to.

msw
`ls -C` doesn't work quite the same way - it assumes a 80-column screen width, rather than using the actual screen width.
bdonlan
@msw, by columnar output, you mean the expected output?
Kedar Soparkar
Yes, I mean the expected output, and you can use the `--width=n` option if you want control over the output line width.
msw
can the output width be grabbed from some environment variable or something equivalent?
Kedar Soparkar