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
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. –
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. –