Linux Command pipe로 변수값으로 끌고오기 pipe()
- 최초 작성일: 2023년 2월 16일 (목)
목차
[TOC]
내용
소스코드 1
#include <iostream>
#include <cstdio>
#include <string>
int main() {
FILE* pipe = popen("arp -a", "r");
if (!pipe) return 1;
char buffer[128];
std::string result = "";
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != nullptr)
result += buffer;
}
pclose(pipe);
std::cout << result << std::endl;
return 0;
}
</br>
결과 1
? (192.168.8.152) at 88:36:6c:fc:2c:4f [ether] on wlan0
? (192.168.8.114) at 5a:ff:ec:d1:cb:a4 [ether] on wlan0
소스코드 2
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
std::vector<std::string> getE6ServerIPpipe()
{
std::vector<std::string> ip_list;
//static bool initflag=false;
//if(initflag)
// return ip_list;
//initflag=true;
int my_pipe[2];
char* arguments[] = {"arp",NULL};
if(pipe(my_pipe) == -1)
{
fprintf(stderr, "Error creating pipe\n");
}
//std::string ip;
//system("arp -a > /home/pi/test/e6/ip.txt");
pid_t child_id;
child_id = fork();
if(child_id == -1)
{
fprintf(stderr, "Fork error\n");
}
if(child_id == 0) // child process
{
close(my_pipe[0]); // child doesn't read
dup2(my_pipe[1], 1); // redirect stdout
execvp(arguments[0], arguments);
fprintf(stderr, "Exec failed\n");
}
else
{
close(my_pipe[1]); // parent doesn't write
char reading_buf[1024];
char *ptr=reading_buf;
while(read(my_pipe[0], ptr, 1) > 0)
{
//write(1, reading_buf, 1); // 1 -> stdout
ptr++;
}
(*ptr)='\0';
char *line=strtok(reading_buf,"\n"); // skip
line=strtok(NULL,"\n");
while(line)
{
int i;
for(i=0;!isspace(line[i]);i++);
line[i]='\0';
ip_list.push_back(line);
//printf("%s--------------------\n",line);
line=strtok(NULL,"\n");
}
close(my_pipe[0]);
wait();
}
return ip_list;
}
결과 2
192.168.8.152
192.168.8.114
위 소스를 컴파일해보면, 아래와 같은 ‘warning’을 확인할 수 있다. 무시해도 되지만, 찝찝하다면 다음과 같은 방법으로 해결하면 된다.
warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
char* arguments[] = {"arp",NULL};
해당 경고는 문자열 상수(string constant)를 char 포인터로 변환하는 것이 C++ 표준에 의해 금지된 것이라는 의미이다.
char* 타입의 포인터는 일반적으로 가리키는 메모리 공간을 수정할 수 있는 포인터로 간주되므로, 이러한 문자열 상수는 const char* 타입으로 선언하고 포인터에 대해 const 캐스팅을 수행해야 한다.
따라서 해당 경고를 해결하기 위해서는 다음과 같이 코드를 수정할 수 있다.
const char* arguments[] = {"arp", NULL};
소스코드 3
std::vector<std::string> getIPList() {
FILE* pipe = popen("arp -a", "r");
if (!pipe) {
std::cerr << "popen() failed!" << std::endl;
exit(1);
}
std::vector<std::string> ip_list;
char buffer[128];
std::string arpOutput = "";
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != nullptr) {
arpOutput += buffer;
}
}
pclose(pipe);
size_t pos_left, pos_right;
while ((pos_left = arpOutput.find("(")) != std::string::npos) {
pos_right = arpOutput.find(")", pos_left);
if (pos_right != std::string::npos) {
std::string token = arpOutput.substr(pos_left + 1, pos_right - pos_left - 1);
ip_list.push_back(token);
}
arpOutput.erase(0, pos_right + 1);
}
return ip_list;
}
결과 3
192.168.8.152
192.168.8.114