popen() 에 관련된 질문입니다.
글쓴이: study / 작성시간: 월, 2017/04/17 - 2:52오전
우선은 아래와 같은 프로그램을 만들었습니다.
Password: 라는 prompt를 출력하고, user가 입력을 하면 입력된 password가 무엇인지 표시해주는 건데요.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[30];
printf("Password : ");
fflush(stdout);
scanf("%s", &str);
fflush(stdout);
printf("entered password is %s\n", str);
return 0;
}
<code>
실행 예는 아래와 같습니다.
<code>
$ ./password
Password : 123456
entered password is 123456
<code>
이 프로그램에 password를 전달해주고 출력을 받아내는 프로그램을 만드는게 목적이었는데요.
아래와 같이 만들어봤습니다.
<code>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *fp;
char *line;
size_t len = 0;
fp = popen("./password", "r");
while(getline(&line, &len, fp) != -1)
{
printf("line = %s", line);
}
free(line);
pclose(fp);
}
<code>
실행 예는 아래와 같습니다.
<code>
$ ./a.out
123456
line = Password : entered password is 123456
<code>
결국 password를 user에가 받아와서 원래의 program에 전달이 되긴 되었는데요.
Password:라는 prompt를 표시하고 싶었는데, 그건 안되네요.
user입력을 먼저 받고, Password: prompt를 표시하는 것 같은데요.
이 순서를 바꿀 수 있는 방법이 있을까요?Forums:


getline() 은 '\n' 를 기다립니다.
getline() 은 '\n' 를 기다립니다.
다른 방법을 찾으세요.
그리고 pipe 는 일방통행입니다.
"password를 전달" 과 "출력을 받아내는" 것 중에서 하나만 할 수 있습니다.
마지막으로, 패스워드 비슷한 것을 입력받는 프로그램의 절대다수는 stdin 이 tty 이기를 요구합니다.
terminal 에 echo off 를 해서 패스워드 노출을 막기 위해서입니다.
forkpty() 에 대해 알아보세요.
두개의 pipe를 만들었는데요
이곳 KLDP를 찾아보다가, https://kldp.org/node/138700를 발견해서요.
그 코드를 이용해서 다시 password전달 프로그램을 만들어 봤는데요 .
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> typedef struct pipe_rw { pid_t cpid; int pipe_r[2]; int pipe_w[2]; } RWPIPE; char *get_user_input(void) { char buf[128]; char *input; char ch; int n; int len = 0; memset(buf, 0x0, 128); while((ch = fgetc(stdin)) != 0xa) { buf[len] = ch; len++; } input = malloc(sizeof(char) * (len)); strncpy(input, buf, (len)); return input; } int pclose_rw(RWPIPE *rwp) { int status, ret = 0; if (rwp) { if (rwp->cpid > 0) { kill(rwp->cpid, SIGTERM); do { ret = waitpid(rwp->cpid, &status, WUNTRACED|WCONTINUED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } close(rwp->pipe_r[0]); close(rwp->pipe_w[1]); free(rwp); } return ret; } RWPIPE *popen_rw(const char *command) { RWPIPE *rwp = (RWPIPE *)malloc(sizeof(*rwp)); if (rwp == NULL) return NULL; memset(rwp, 0x00, sizeof(*rwp)); if (pipe(rwp->pipe_r) != 0 || pipe(rwp->pipe_w) != 0) { free(rwp); return NULL; } rwp->cpid = fork(); if (rwp->cpid == -1) { free(rwp); return NULL; } if (rwp->cpid == 0) { dup2(rwp->pipe_w[0], STDIN_FILENO); dup2(rwp->pipe_r[1], STDOUT_FILENO); close(rwp->pipe_r[0]); close(rwp->pipe_r[1]); close(rwp->pipe_w[0]); close(rwp->pipe_w[1]); execl(command, command, NULL); printf("Error: fail to exec command - %s ..\n", command); exit (1); } else { close(rwp->pipe_r[1]); close(rwp->pipe_w[0]); } return rwp; } ssize_t read_p(RWPIPE *rwp, void *buf, size_t count) { return read(rwp->pipe_r[0], buf, count); } ssize_t write_p(RWPIPE *rwp, const void *buf, size_t count) { return write(rwp->pipe_w[1], buf, count); } int main(void) { char rbuf[BUFSIZ], wbuf[BUFSIZ]; int ret, len, n = 0; char *password; RWPIPE *rwp = popen_rw("./password"); if (rwp == NULL) { printf("Error: fail to open command ..\n"); return EXIT_FAILURE; } while (1) { memset(rbuf, 0x00, sizeof(rbuf)); if (read_p(rwp, rbuf, sizeof(rbuf)) < 1) { printf("No more input..\n"); break; } printf("%s", rbuf); password = get_user_input(); len = strlen(password); ret = write_p(rwp, password, len); if (ret != len) { printf("Write %d bytes (expected %d) ..\n", ret, len); break; } printf("end"); } pclose_rw(rwp); return EXIT_SUCCESS; } <code> 실행예는 아래와 같은데요,,password를 입력받는 것까지는 되는것같은데요. password를 전달해주는 쪽에 문제가 있는것 같아요 <code> [root@localhost test_code]# [root@localhost test_code]# gcc popen_rw.c [root@localhost test_code]# ./a.out Password : 1234 <code>forkpty(), tcsetattr(),
forkpty(), tcsetattr(), execvp()
댓글 달기