2016-05-07 16 views
2

Ich habe eine Möglichkeit gefunden, unix externe Befehle ohne Argumente (zB "ls", "pwd") aufzurufen. Es geht so:Unix externe Befehle mit Argumenten aufrufen

//Child process 
char cwd[1024]; 
getcwd(cwd, sizeof(cwd)); 
char *argv[] = {*args, NULL}//(ex.) {"ls", NULL} 
char *env[] = {cwd, NULL}; 
//concat():method that connects 2 strings 
char *command_source = concat("/bin/", *args); 
execve(command_source, argv, env); 
return 0; 

Ich versuche, diesen Code zu konvertieren, um externe Befehle mit Argumenten wie „ls -l“ zu akzeptieren

+1

Zappen die gesamte Umgebung lesen und es mit nur den aktuellen Verzeichnisnamen ersetzt wird einige Programme unglücklich machen. So tust du es nicht - was auch immer du versuchst zu tun. –

+0

Ein typischer Befehl sieht folgendermaßen im Speicher aus: 'static char * cmd1 [] = {" awk "," {print $ 1} ", 0};' Beachten Sie, dass die Anführungszeichen entfernt sind und der Abschluss 0 ist. –

Antwort

1

Unter der Annahme, dass Sie die Anzahl der Argumente in args wissen und dass es ist argcs:

... 
char **argv = calloc(sizeof(char*), argcs+1); 
for (int i=0; i<argcs; i++) 
    argv[i]=args[i]; 
argv[argcs]=NULL; 
... 

Wenn nicht, Sie leicht argcs durch Iteration durch das Array der Suche nach dem Ende NULL bestimmen können.

0

Sie können auch eine Pipeline erstellen; schauen, wie die Befehle aufgebaut sind und die Struktur sehen, sie sind Arrays, die mit 0 und die Anführungszeichen am Ende werden entfernt:

/* who | awk '{print $1}' | sort | uniq -c | sort -n */ 
/*static char *cmd0[] = {"who", 0}; 
static char *cmd1[] = {"awk", "{print $1}", 0}; 
static char *cmd2[] = {"sort", 0}; 
static char *cmd3[] = {"uniq", "-c", 0}; 
static char *cmd4[] = {"sort", "-n", 0};*/ 

Hier sind einige Utility-Funktion, wenn Sie eine Pipeline mit Argumenten erstellen. Sie sind gut getestet und fehlerfrei.

pipeline.c

#define _XOPEN_SOURCE 500 
/* One way to create a pipeline of N processes */ 

#ifndef STDERR_H_INCLUDED 
#define STDERR_H_INCLUDED 

static void err_sysexit(char const *fmt, ...); 

static void err_syswarn(char const *fmt, ...); 

#endif /* STDERR_H_INCLUDED */ 

/* pipeline.c */ 
#include <assert.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include "openshell.h" 
#include <errno.h> 

/* exec_nth_command() and exec_pipe_command() are mutually recursive */ 
static void exec_pipe_command(int ncmds, char ***cmds, Pipe output); 

/* With the standard output plumbing sorted, execute Nth command */ 
static void exec_nth_command(int ncmds, char ***cmds) { 
    assert(ncmds >= 1); 
    if (ncmds > 1) { 
     pid_t pid; 
     Pipe input; 
     if (pipe(input) != 0) 
      err_sysexit("Failed to create pipe"); 
     if ((pid = fork()) < 0) 
      err_sysexit("Failed to fork"); 
     if (pid == 0) { 
      /* Child */ 
      exec_pipe_command(ncmds - 1, cmds, input); 
     } 
     /* Fix standard input to read end of pipe */ 
     dup2(input[0], 0); 
     close(input[0]); 
     close(input[1]); 
    } 
    execvp(cmds[ncmds - 1][0], cmds[ncmds - 1]); 
    err_sysexit("Failed to exec %s", cmds[ncmds - 1][0]); 
    /*NOTREACHED*/ 
} 

/* Given pipe, plumb it to standard output, then execute Nth command */ 
static void exec_pipe_command(int ncmds, char ***cmds, Pipe output) { 
    assert(ncmds >= 1); 
    /* Fix stdout to write end of pipe */ 
    dup2(output[1], 1); 
    close(output[0]); 
    close(output[1]); 
    exec_nth_command(ncmds, cmds); 
} 


/* who | awk '{print $1}' | sort | uniq -c | sort -n */ 
/*static char *cmd0[] = {"who", 0}; 
static char *cmd1[] = {"awk", "{print $1}", 0}; 
static char *cmd2[] = {"sort", 0}; 
static char *cmd3[] = {"uniq", "-c", 0}; 
static char *cmd4[] = {"sort", "-n", 0};*/ 

/*static char **cmds[] = {cmd0, cmd1, cmd2, cmd3, cmd4};*/ 
/*static int ncmds = sizeof(cmds)/sizeof(cmds[0]);*/ 

/* Execute the N commands in the pipeline */ 
void exec_pipeline(int ncmds, char ***cmds) { 
    assert(ncmds >= 1); 
    pid_t pid; 
    if ((pid = fork()) < 0) 
     err_syswarn("Failed to fork"); 
    if (pid != 0) 
     return; 
    exec_nth_command(ncmds, cmds); 
} 

#include <stdarg.h> 

static const char *arg0 = "<undefined>"; 

static void err_vsyswarn(char const *fmt, va_list args) { 
    int errnum = errno; 
    fprintf(stderr, "%s:%d: ", arg0, (int) getpid()); 
    vfprintf(stderr, fmt, args); 
    if (errnum != 0) 
     fprintf(stderr, " (%d: %s)", errnum, strerror(errnum)); 
    putc('\n', stderr); 
} 

static void err_syswarn(char const *fmt, ...) { 
    va_list args; 
    va_start(args, fmt); 
    err_vsyswarn(fmt, args); 
    va_end(args); 
} 

static void err_sysexit(char const *fmt, ...) { 
    va_list args; 
    va_start(args, fmt); 
    err_vsyswarn(fmt, args); 
    va_end(args); 
    exit(1); 
} 

Der Code von einem aus einer früheren Frage vor Shell-Projekt kommt, wo eine Prämie für den obigen Code ausgezeichnet wurde. Es gibt eine ausführliche Antwort bereits mit Details - How to fix these errors in my code. Es gibt auch die frühere Antwort auf C minishell: adding pipelines, die den größten Teil des zitierten Codes enthält.

Sie können auch pipe(2), pipe(7) und Advanced Linux Programming

+3

Das ist netter Code - Wo hast du es her, und wirst du Kredit geben, wo der Kredit fällig ist? Gibt es einen Grund, warum Sie nicht in Vergessenheit geraten sollten für [Plagiat] (https://stackoverflow.com/questions/13636252/c-minishell-adding-pipelines) –

+2

Welche Websites? Sie sollten diesen Punkten Kredit geben - genauso wie diese Websites SO einen Kredit geben sollten, da dort der Code zuerst veröffentlicht wurde. –

+0

@JonathanLeffler Ich bin mir sicher, dass ich dir früher eine Prämie für diesen Code gegeben habe, du hast mir auf der Chat-Seite geholfen und mich gelehrt. –