ich einen tokenizer in c geschrieben haben, die shell Kommandosprache Eingabe tokenizes und wenn ich die Befehle ausführen ich die Ausgabe in „falschen Reihenfolge“ erhalten nach dem fork
, wenn ich ein fork und exec
tun dann die Ausgabe von fork und exec kommen könnte, in der Mitte einer Schleife in einer anderen Funktion. Die erwartete Ausgabe i willWie kann ich diesen C-Code synchronisieren?
$ ls openshell.*|grep o
{ls} {openshell.cbp} {|} {grep} {o} {|}
p[0][0] ls
p[0][1] openshell.cbp
p[1][0] grep
p[1][1] o
17109: executing ls
17108: executing grep
openshell.cbp
Während der Ausgang I erhalten
$ ls openshell.*|grep o
{ls} {openshell.cbp} {|} {grep} {o} {|}
p[0][0] ls
p[0][1] openshell.cbp
17108: executing grep
p[1][0] grep
openshell.cbp
17109: executing ls
p[1][1] o
den Code Einige, die tut dies ist
static int runCmd(const char *cmd) {
const char *cp;
pid_t pid;
int status;
struct command shellcommand[4];
char **argv = 0;
int argc = 1;
bool pipe = false;
char *pString[75][75];
char *command[40];
char *command2[40];
int i1 = 0;
char **tokens;
char tokenscopy[75];
bool keep = false;
char *conc[75];
char *conc2[75];
*conc = "\0";
*conc2 = "\0";
char temp[75] = {'\0'};
int w = 0;
bool quoted = false;
int j = 0;
int i;
int p = 0;
char **ptr;
char *tmpchar;
char *cmdtmp;
bool change = false;
int f = 0;
char *char2;
int y = 0;
for (int i = 0; i < 75; i++) { /* for each pipeline */
for (int j = 0; j < 75; j++) { /* for each pipeline */
pString[i][j] = '\0';
}
}
for (cp = cmd; *cp; cp++) {
if ((*cp >= 'a') && (*cp <= 'z')) {
continue;
}
if ((*cp >= 'A') && (*cp <= 'Z')) {
continue;
}
if (isDecimal(*cp)) {
continue;
}
if (isBlank(*cp)) {
continue;
}
if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
(*cp == '+') || (*cp == '=') || (*cp == '_') ||
(*cp == ':') || (*cp == ',') || (*cp == '\'') ||
(*cp == '"')) {
continue;
}
}
char a[20] = {0};
cmdtmp = malloc(sizeof(cmd));
strcpy(cmdtmp, cmd);
tmpchar = malloc(sizeof(cmd));
strcpy(tmpchar, cmd);
tokens = str_split(command, cmdtmp, '|');
if (strstr(cmd, "|") == NULL) {
/* not a pipeline */
makeArgs(cmd, &argc, (const char ***) &argv, pipe, 0, 0);
/*dump_argv((const char *) "d", argc, argv);*/
for (j = 0; j < argc; j++) {
pString[0][j] = argv[j];
shellcommand[i].argv = pString[0]; /*command;*/
}
}
else {
i1 = 1;
for (i = 0; *(tokens + i); i++) { /* for each pipeline*/
i1++;
int e = 0;
*conc2 = "\0";
strcpy(tokenscopy, *(tokens + i));
if ((tokenscopy[0] != '\0') && !isspace(tokenscopy[0])) {
ptr = str_split(command2, *(&tokenscopy), ' ');
f = 0;
int j2 = 0;
for (j = 0; *(ptr + j); j++) {
if (ptr + j && !quoted && strstr(*(ptr + j), "'")) {
quoted = true;
strcpy(temp, *(ptr + j));
if(y<1) {
/* pString[i][j] = temp;*/
y++;
}
}
while (quoted) {
if (*(ptr + j) && strstr(*(ptr + j), "'")) { /* end of quote */
quoted = false;
if(y<1) {
pString[i][j] = strcpy(temp, *(ptr + j));
}
y=0;
}
else if (*(ptr + j)) { /* read until end of quote */
pString[i][j] = temp;
continue;
} else {
quoted = false;
break;
}
}
if (ptr + j) {
if (*(ptr + j)[0] == '{') {
keep = true;
}
if (testFn(*(ptr + j))) { /* test for last char */
pString[i][j - p] = concat(*conc, *(ptr + j));
keep = false;
free(*conc);
goto mylabel;
}
if (keep) {
*conc = concat(*conc, *(ptr + j));
*conc = concat(*conc, " ");
p++;
} else {
if (*(ptr + j + f + 1) == NULL)
break;
strcpy(temp, *(ptr + j));
change = false;
for (e = 0; *(ptr + j + e); e++) {
change = true;
if (*(ptr + e + j)) {
*conc2 = concat(*conc2, *(ptr + e + j));
*conc2 = concat(*conc2, " ");
}
}
if (change) j++;
if (makeArgs(*conc2, &argc, (const char ***) &argv, pipe, i, j2)) {
for (int r = 0; argv[r] != NULL; r++) {
char2 = malloc(sizeof(char *));
*char2 = '0';
strcpy(char2, argv[r]);
pString[w][r] = char2;
}
w++;
dump_argv((const char *) "d", argc, argv);
} else {
if (!change) {
for (int r = 0; argv[r] != NULL; r++) {
pString[i][r] = argv[r];
}
}
}
}
}
}
mylabel:
free(ptr);
}
}
free(tokens);
free(cmdtmp);
free(tmpchar);
for (i = 0; i < i1 - 1; i++) {
for (j = 0; pString[i][j] != 0; j++) {
printf("\np[%d][%d] %s", i, j, pString[i][j]);
}
shellcommand[i].argv = pString[i];
}
}
pid = fork();
if (pid < 0) {
perror("fork failed");
return -1;
}
/* If we are the child process, then go execute the pString.*/
if (pid == 0) {
/* spawn(cmd);*/
fork_pipes(i1 - 1, shellcommand);
}
/*
* We are the parent process.
* Wait for the child to complete.
*/
status = 0;
while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
if (pid < 0) {
fprintf(stderr, "Error from waitpid: %s", strerror(errno));
return -1;
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "pid %ld: killed by signal %d\n",
(long) pid, WTERMSIG(status));
return -1;
}
return WEXITSTATUS(status);
}
fork_pipes
/* Helper function that forks pipes */
void fork_pipes(int n, struct command *cmd) {
int i;
int in = 0;
int fd[2];
for (i = 0; i < n - 1; ++i) {
if (pipe(fd) == -1) {
err_syserr("Failed creating pipe");
}
spawn_proc(in, fd[1], cmd + i);
close(fd[1]);
in = fd[0];
}
if (dup2(in, 0) < 0) {
err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]);
}
fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd[i].argv[0]);
execvp(cmd[i].argv[0], cmd[i].argv);
err_syserr("failed to execute %s: ", cmd[i].argv[0]);
}
/* Helper function that spawns processes */
int spawn_proc(int in, int out, struct command *cmd) {
pid_t pid;
pid = fork();
if (pid == 0) {
if (in != 0) {
if (dup2(in, 0) < 0)
err_syserr("dup2() failed on stdin for %s: ", cmd->argv[0]);
close(in);
}
if (out != 1) {
if (dup2(out, 1) < 0)
err_syserr("dup2() failed on stdout for %s: ", cmd->argv[0]);
close(out);
}
fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd->argv[0]);
execvp(cmd->argv[0], cmd->argv);
err_syserr("failed to execute %s: ", cmd->argv[0]);
}
else if (pid < 0) {
err_syserr("fork failed: ");
} else {
/* printf("** we are the parent ***"); */
}
return pid;
}
Es ist nicht unbedingt notwendig, dass ich fixiere es in meinem Code, aber ich möchte lernen, warum ich nicht erwarten kann, dass die Ausgabe "gerade" ist, wenn ich fork starte.
Hat 'fork_pipes'' exec' aufgerufen und sich nie gedreht? – fluter
@fluter Ich kann diesen Code auch posten. –
Probieren Sie 'printf (" [% d] [% d]% s \ n ", i, j, pString [i] [j]);' aus, da das Stdout liniengepuffert ist. Warum "verzweigt" ihr beide in 'spaw_proc' und' fork_pipes'? – fluter