Запустите команду bash асинхронно с ncurses в c

Я хотел создать простую программу для подключения клиентов к моей беспроводной сети в любой момент. Для этого я использую nmap для поиска соответствующих адресов (MAC клиента, IP) и ncurses библиотеку в C.

Сценарий bash, который выполняет мою работу, выглядит следующим образом:

nmap -sP ip/24 | awk '/Nmap scan report for/{printf $5;}/MAC Address:/{print " - "$3;}' | sort

Программа c выглядит следующим образом:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <ncurses.h>

#define DELAY 30000

int main(int argc, char *argv[]) {
  raw();
  noecho();
  keypad(stdscr, TRUE);
  initscr();

  while (1) {

    clear();
    int  maxRows_y, maxCols_x;
    getmaxyx(stdscr, maxRows_y, maxCols_x);

    FILE *fp;
    char path[1000];

    fp = popen("nmap -sP 192.168.0.1/24 | awk '/Nmap scan report for/{printf $5;}/MAC Address:/{print \" => \"$3;}' | sort", "r");

    while (fgets(path, 1000, fp) != NULL) {
        printw("%s", path);
    }
    pclose(fp);

    refresh();
    usleep(DELAY); // Shorter delay between movements
  }

  endwin();

  return EXIT_SUCCESS;
}

Проблема в том, что программа зависает каждый раз, когда я запускаю трубу. Это вызывает другие проблемы. Например, если я хочу использовать часы для подсчета времени, прошедшего с начала моей программы, это не будет обновляться каждую секунду (1 -> 2 -> 3 -> .. и т. д.), потому что мы должны ждать канала заканчивать. А также, если я добавлю другие функции, такие как меню, это вызовет ужасные проблемы с пользовательским интерфейсом.

Я хотел спросить, есть ли способ запустить канал в фоновом режиме и получить результаты, когда он завершит процесс, не прерывая другие функции моей программы. Помните, что я должен запускать канал непрерывно, пока программа не завершится.

ОБНОВИТЬ:

Этот вопрос был первым, что я показал. Проблема в том, что если мы изменим код на эту версию, мы останемся без вывода.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <ncurses.h>
#include <fcntl.h>
#include <errno.h>

#define DELAY 30000

int main(int argc, char *argv[]) {
  raw();
  noecho();
  keypad(stdscr, TRUE);
  initscr();


  FILE *f = popen("nmap -sP 192.168.0.1/24 | awk '/Nmap scan report for/{printf $5;}/MAC Address:/{print \" => \"$3;}' | sort", "r");
  int d = fileno(f);
  fcntl(d, F_SETFL, O_NONBLOCK);

  while (1) {

    clear();
    int  maxRows_y, maxCols_x;
    getmaxyx(stdscr, maxRows_y, maxCols_x);

    char path[1000];
    ssize_t r = read(d, path, sizeof(path));
    if (r == -1 && errno == EAGAIN) {
      printw("waiting for data....");
    }
        
    else if (r > 0) {
      printw("%s", path);
      fcntl(d, F_SETFL, O_NONBLOCK);
    }
    else {
      printw("pipe closed");
    }
         

    refresh();
    usleep(DELAY); // Shorter delay between movements
  }

  endwin();

  return EXIT_SUCCESS;
}

person Community    schedule 10.12.2016    source источник
comment
@ merlin2011 это не дубликат. Смотрите мое обновление. Это не работает.   -  person    schedule 11.12.2016


Ответы (1)


Я думаю, проблема может заключаться в том, что вывод мигает слишком быстро, чтобы вы могли его увидеть.

Если вы немного измените свой код, чтобы не очищать экран после вывода (по крайней мере, в течение нескольких секунд), я думаю, вы увидите данные.

Вот одна версия, которая сработала для меня. Обратите внимание, что подсеть отличается, потому что я тестировал в своей собственной сети.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <ncurses.h>
#include <fcntl.h>
#include <errno.h>

#define DELAY 30000

int main(int argc, char *argv[]) {
    raw();
    noecho();
    keypad(stdscr, TRUE);
    initscr();


    FILE *f = popen("nmap -sP 10.0.0.13/24", "r");

    int d = fileno(f);
    fcntl(d, F_SETFL, O_NONBLOCK);

    bool processingOutput = false;

    while (1) {
        if (!processingOutput)
            clear();
        int  maxRows_y, maxCols_x;
        getmaxyx(stdscr, maxRows_y, maxCols_x);

        char path[1000];
        ssize_t r = read(d, path, sizeof(path));
        if (r == -1 && errno == EAGAIN && !processingOutput) {
            printw("waiting for data....");
        }
        else if (r > 0) {
            processingOutput = true;
            path[r] = '\0';
            printw("%s", path);
        }
        else {
            printw("pipe closed");
            sleep(10);
            processingOutput = false;
        }


        refresh();
        usleep(DELAY); // Shorter delay between movements
    }
    endwin();
    return EXIT_SUCCESS;
}
person merlin2011    schedule 11.12.2016