user191776
user191776

Reputation:

Reading correctly from a file

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.

Upvotes: 1

Views: 202

Answers (2)

bdonlan
bdonlan

Reputation: 231063

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.

Upvotes: 2

msw
msw

Reputation: 43487

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.

Upvotes: 2

Related Questions