I wanted to create a simple program to get the connected clients each moment on my wireless network. For that purposes I use nmap
to find the appropriate addresses (MAC of the client, IP) and ncurses
library in C
.
The bash script that do my job is the following:
nmap -sP ip/24 | awk '/Nmap scan report for/{printf $5;}/MAC Address:/{print " - "$3;}' | sort
The c program is the following:
#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;
}
The problem is that the program freezes every time I run the pipe. This cause other problems. For instance, if I want to use a clock to count the elapsed time from the beginning of my program, this won't update every second (1 -> 2 -> 3 -> ..etc) cause we have to wait the pipe to finish. And also if I add other functionalities such as menus, this will cause terrible user experience issues.
I wanted to ask if there is a way to run the pipe on the background and get the results when it finishes the process without interrupting other functionalities of my program. Remember that I have to run the pipe continuously until the program exit.
UPDATE:
This question was the first I show. The problem is that if we change the code to this version, we end up without any output.
#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;
}