/* Beefed-up example from man 2 pipe to illustrate how xorriso is to be used by frontend programs via two pipes. Build: cc -g -o frontend_pipes_xorriso frontend_pipes_xorriso.c Usage: ./frontend_pipes_xorriso [path_to_xorriso_binary] */ #include #include #include #include #include #include /* Local helpers of parent process */ int await_all_replies(int fd, char *pending_mark); int prompt_for_command(char *line, int line_size); /* Parent and child */ int main(int argc, char *argv[]) { int command_pipe[2], reply_pipe[2]; pid_t cpid; char *xorriso_path = "/usr/bin/xorriso"; if (argc > 1) xorriso_path = argv[1]; if (pipe(command_pipe) == -1) { perror("pipe"); exit(1); } if (pipe(reply_pipe) == -1) { perror("pipe"); exit(1); } cpid = fork(); if (cpid == -1) { perror("fork"); exit(2); } if (cpid == 0) { /* Child redirects stdin and stdout. Then it becomes xorriso. */ char *xargv[8]; close(command_pipe[1]); /* Close unused write end */ close(reply_pipe[0]); /* Close unused read end */ /* Attach pipe ends to stdin and stdout */ close(0); if (dup2(command_pipe[0], 0) == -1) { perror("dup2(,0)"); exit(1); } close(1); if (dup2(reply_pipe[1], 1) == -1) { perror("dup2(,1)"); exit(1); } xargv[0] = xorriso_path; xargv[1] = "-dialog"; xargv[2] = "on"; xargv[3] = "-pkt_output"; xargv[4] = "on"; xargv[5] = "-mark"; xargv[6] = "0"; /* corresponds to mark_count = 0 in parent */ xargv[7] = NULL; execv(xorriso_path, xargv); perror("execv"); exit(1); } else { /* Parent prompts user for command lines and prints xorriso replies. It knows when all reply text of the pending command line has arrived by watching for -mark reply pending_mark. */ int mark_count = 0, ret; char pending_mark[16], line[4096]; close(command_pipe[0]); /* Close unused read end */ close(reply_pipe[1]); /* Close unused write end */ /* Dialog loop */ sprintf(pending_mark, "%d", mark_count); while (1) { /* Wait for pending mark and print all replies */ ret = await_all_replies(reply_pipe[0], pending_mark); if (ret < 0) break; /* Prompt for command line */ ret = prompt_for_command(line, sizeof(line)); if (ret <= 0) break; /* Send line and -mark command */ ret = write(command_pipe[1], line, strlen(line)); if (ret == -1) { perror("write"); break; } /* Produce new unique -mark text to watch for */ mark_count++; sprintf(pending_mark, "%d", mark_count); sprintf(line, "-mark %s\n", pending_mark); ret = write(command_pipe[1], line, strlen(line)); if (ret == -1) { perror("write"); break; } } /* >>> if child is still operational: send -rollback_end */; /* >>> wait a short while */; /* >>> if not yet ended: kill child */; wait(NULL); /* Wait for child */ exit(0); } } /* Local helpers of parent process */ int await_all_replies(int fd, char *pending_mark) { int count, remainder = 0; char buf[32769], *line, *npt; while (1) { count = read(fd, buf + remainder, sizeof(buf) - 1 - remainder); if (count == -1) { perror("read"); return(-1); } if (count == 0) { fprintf(stderr, "+++ EOF encounterd by Master process\n"); return(-2); } for (npt = buf + remainder; npt < buf + count; npt++) { if (*npt == 0) { fprintf(stderr, "+++ Protocol error : Reply contains 0-chars\n"); return(-1); } } /* Split buf into lines */ buf[remainder + count] = 0; /* for convenience */ line = buf; while (1) { npt = strchr(line, '\n'); if (npt == NULL) { /* Move line to start of buffer and set remainder */ if (line != buf) { remainder = 0; for (npt = line; *npt; npt++) buf[remainder++] = *npt; } /* Now read more data in the hope to get a newline char */ break; } /* Interpret line */ *npt = 0; if (line[0] == 'M') { /* M-replies will be outdated until the pending command line is completely done and the appended -mark command gets into effect. */ if (strlen(line) < 6) { fprintf(stderr, "+++ Protocol error : M-channel line shorter than 6 chars\n"); return(-1); } if (strcmp(line + 5, pending_mark) == 0) { if ((line - buf) + strlen(line) + 1 < count) { fprintf(stderr, "+++ Protocol error : Surplus reply data after M-match\n"); fprintf(stderr, "%s\n", line + strlen(line) + 1); return(-1); } return (1); /* Expected mark has arrived */ } } else if (line[0] == 'R') { /* R-replies are result lines of inquiry commands, like -ls. They should be handled by specialized code which knows how to parse and interpret them. */ printf("%s\n", line); } else { /* I-replies are pacifiers, notifications, warnings, or error messages. They should be handled by a general message interpreter which determines their severity and decides whether to bother the user. */ fprintf(stderr, "%s\n", line); } line = npt + 1; } } return(1); } int prompt_for_command(char *line, int line_size) { int l; char *line_res; fprintf(stderr, "+++ Enter a command and its parameters :\n"); line_res = fgets(line, line_size - 1, stdin); if (line_res == NULL) return(0); l = strlen(line); if (l == 0) { line[0] = '\n'; line[1] = 0; } else if (line[l - 1] != '\n') { line[l] = '\n'; line[l + 1] = 0; } return(1); }