lib/process: Add option to pipe to process stdin
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Thu, 14 Feb 2019 23:39:05 +0000 (10:39 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 5 Mar 2019 20:54:10 +0000 (09:54 +1300)
If pipe_stdin exists, create a second pipe to write to the child
process's STDIN. This allows Petitboot to pipe information to a process,
for example piping a LUKS password to cryptsetup.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
lib/process/process.c
lib/process/process.h

index 02b6f490dad8318744ba8b4f43b30c6362ceae09..7bd29b8219eb386ba4f575f744eb0539925a640c 100644 (file)
@@ -50,6 +50,7 @@ struct process_info {
        int                     stdout_buf_len;
        struct waiter           *stdout_waiter;
        int                     stdout_pipe[2];
+       int                     stdin_pipe[2];
        void                    *orig_ctx;
 };
 
@@ -130,12 +131,37 @@ static int process_setup_stdout_pipe(struct process_info *procinfo)
        return 0;
 }
 
+static void process_setup_stdin_parent(struct process_info *procinfo)
+{
+       FILE *in;
+
+       if (!procinfo->process.pipe_stdin)
+               return;
+
+       close(procinfo->stdin_pipe[0]);
+       in = fdopen(procinfo->stdin_pipe[1], "w");
+       if (!in) {
+               pb_log_fn("Failed to open stdin\n");
+               return;
+       }
+       fputs(procinfo->process.pipe_stdin, in);
+       fflush(in);
+}
+
+static void process_setup_stdin_child(struct process_info *procinfo)
+{
+       if (procinfo->process.pipe_stdin) {
+               close(procinfo->stdin_pipe[1]);
+               dup2(procinfo->stdin_pipe[0], STDIN_FILENO);
+       }
+}
 static void process_setup_stdout_parent(struct process_info *procinfo)
 {
        if (!procinfo->process.keep_stdout || procinfo->process.raw_stdout)
                return;
 
        close(procinfo->stdout_pipe[1]);
+
 }
 
 static void process_setup_stdout_child(struct process_info *procinfo)
@@ -350,6 +376,11 @@ static int process_run_common(struct process_info *procinfo)
        rc = process_setup_stdout_pipe(procinfo);
        if (rc)
                return rc;
+       if (procinfo->process.pipe_stdin) {
+               rc = pipe(procinfo->stdin_pipe);
+               if (rc)
+                       return rc;
+       }
 
        pid = fork();
        if (pid < 0) {
@@ -359,6 +390,7 @@ static int process_run_common(struct process_info *procinfo)
 
        if (pid == 0) {
                process_setup_stdout_child(procinfo);
+               process_setup_stdin_child(procinfo);
                if (procset->dry_run)
                        exit(EXIT_SUCCESS);
                execvp(process->path, (char * const *)process->argv);
@@ -366,6 +398,7 @@ static int process_run_common(struct process_info *procinfo)
        }
 
        process_setup_stdout_parent(procinfo);
+       process_setup_stdin_parent(procinfo);
        process->pid = pid;
 
        return 0;
index 9473a0d492b00e0e644b4e957fa78f1f8599764a..eb6e3360d73c914e8f3421d5cf2d4e447eb2fc75 100644 (file)
@@ -43,6 +43,7 @@ struct process {
        void                    *data;
        waiter_cb               stdout_cb;
        void                    *stdout_data;
+       char                    *pipe_stdin;
 
        /* runtime data */
        pid_t                   pid;