2017-04-09 6 views
-1

ich zur Zeit auf eine Katze Programm arbeite und haben folgende Fälle zu unterscheiden:, wie die folgenden zwei Fälle, in C unterscheiden

./cat 

und

./cat <file1> file2.txt 

dies der Code ist

while((fileFD=read(STDIN_FILENO,str,1000))!=0)// If we just execute the command cat, it will receive input from the stdin and put it in the stdout. 
    { 
    write(STDOUT_FILENO,str,fileFD);// Write it to the standard output 
    if(fileFD==-1) 
    { 
    perror("error"); 
    exit(1); 
    } 
    } 
    break;  

Ich verwende die Parameter argv und argc, um die Argumente zu verfolgen. In beiden Fällen ist argc = 1, weil alles auf der rechten Seite von < nicht berücksichtigt wird. Wie würdest du das machen?

+7

'while (wahr == 0)' ist alle Arten von seltsamen – StoryTeller

+0

IS gibt es während (wahr) in C ?. Ich muss meinen Code aufräumen. Ich werde es später tun. Angenommen, es ist nur eine Weile wahr und irgendwie muss ich den Loop im zweiten Fall durchbrechen. – daniel

+0

Und Sie müssen Fall drei nicht "behandeln". Die Shell richtet den Stream für Sie korrekt ein. Das einfache Lesen von 'stdin' zieht den Inhalt von file1. – StoryTeller

Antwort

2

Bei zwei Dateideskriptoren, einer für die Eingabe, einer für die Ausgabe, kopiert die folgende Funktion die Daten von der Eingabe in die Ausgabe einigermaßen zuverlässig.

#include <unistd.h> 

/* Copy file from input file descriptor ifd to output file descriptor ofd */ 
extern int copy_file(int ifd, int ofd); 

int copy_file(int ifd, int ofd) 
{ 
    char buffer[65536]; // Resize to suit your requirements 
    ssize_t i_bytes; 
    while ((i_bytes = read(ifd, buffer, sizeof(buffer))) > 0) 
    { 
     ssize_t bytes_left = i_bytes; 
     char *posn = buffer; 
     ssize_t o_bytes; 
     while ((o_bytes = write(ofd, posn, bytes_left)) > 0) 
     { 
      bytes_left -= o_bytes; 
      posn += o_bytes; 
     } 
     if (o_bytes < 0) 
      return -1; 
    } 
    if (i_bytes < 0) 
     return -1; 
    return 0; 
} 

könnte Ein nacktes minimales Testprogramm sein:

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

…declaration or definition of file_copy()… 

int main(void) 
{ 
    int rc = EXIT_SUCCESS; 
    if (copy_file(STDIN_FILENO, STDOUT_FILENO) != 0) 
    { 
     int errnum = errno; 
     rc = EXIT_FAILURE; 
     fprintf(stderr, "copy_file failed: (%d) %s\n", errnum, strerror(errnum)); 
    } 
    return rc; 
} 

Diese korrekt kopieren Dateien von der Standardeingabe auf der Standardausgabe. Ich habe nicht definitiv einen 'kurzen Schreibvorgang' getestet. Es ist ein ziemlich seltenes Szenario, und der wahrscheinlichste Kontext ist, wenn der Ausgabedateideskriptor ein Socket ist. Das Testen der Fehlerpfade ist ebenfalls schwieriger. Ich habe das Programm cf89 aufgerufen. Ein Test war:

$ (trap '' 13; ./cf89 < /dev/zero) | (sleep 1) 
copy_file failed: (32) Broken pipe 
$ 

Die trap ignoriert SIGPIPE (13), so dass die Schreibblöcke, weil nichts liest das Rohr. Wenn der sleep beendet wird, erhält der Schreibprozess einen Fehler von write() - weil das Signal ignoriert wird - und es generiert die Fehlermeldung.

Nebenbei, es gibt diejenigen, die aus Sicherheitsgründen gegen die Meldung der Fehlernummer und der Fehlermeldung sprechen - es erzählt dem Angreifer zu viel über das System, wenn es ihnen gelingt, einen Fehler auszulösen. Ich bin nicht in diesem Lager; Der Angreifer kennt den Systemtyp bereits, wenn er ein solches Programm angreift. Es könnte in anderen Kontexten, wie etwa einem Webserver, relevant sein.

0

diese Befehlszeile:

cat <file1> file2.txt 

einfach wird Umleitung stdin und stdout und das Programm muss nichts Besonderes tun.

Wenn jedoch die Befehlszeilen sind:

cat file1 

Dann muss der Code wieder zu öffnen() stdin zur Datei

und es kann eine Nachricht sein, um stderr, wenn die() wieder öffnen versagt

in einem Satz von Befehlszeilenparameter ,, alle I/O würde von stdin und zu stdout

0

Sie vergessen andere Fälle. Was ist pipelines, wie

date | ./cat | wc 

vielleicht möchten Sie testen, ob stdin ein Pseudo-tty ist (oder nicht). Lesen Sie zuerst die tty demystified (mit termios(3) ...).Verwenden Sie dann isatty(3) als isatty(STDIN_FILENO), um das zu testen. Sie sollten jedoch eine Option zum Überschreiben des Tests bereitstellen. Siehe L. Serrni's deleted answer.

BTW, müssen Sie möglicherweise poll(2) verwenden. Lesen Sie Advanced Linux Programming.

Die Frage sieht wie einige XY problem aus.

Verwandte Themen