Reputation: 876
I know there is a way to program this in C by using fork and making pipes in some way (I know there is a way, I don't remember how to do it though).
The intended use is connecting a server's output (which I'd get using netcat) to a program of my own in c++ which will process said output and give back it's own to netcat. I have no clue how to connect directly in c++ (sockets are misterious beings) and I'd like to avoid installing boost since it should compile in more or less vanilla systems.
So, is there a way to use bash to redirect a program's output to another program's input and the second's output to the first's input in bash?
Upvotes: 1
Views: 1519
Reputation: 66
If you are working with C style servers and clients then, the following socket based solution can be used to transfer the data from the server to the client.
The solution uses the popen
function for running the required command on your host system and then transfer the data to the client using send
and recv
primitives for socket programming.
The code is as follows:
SERVER:
#include "stdio.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "error.h"
#include "string.h"
#include "unistd.h"
#include "arpa/inet.h"
#define ERROR -1
#define MAX_CLIENTS 2
#define MAX_DATA 1024
main(int argc, char **argv)
{
struct sockaddr_in server;
struct sockaddr_in client;
int sock;
int new,i;
int sockaddr_len = sizeof(struct sockaddr_in);
int data_len;
char data[MAX_DATA];
char temp[MAX_DATA];
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
{
perror("server socket: ");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
server.sin_addr.s_addr = INADDR_ANY;
bzero(&server.sin_zero, 8);
if((bind(sock, (struct sockaddr *)&server, sockaddr_len)) == ERROR)
{
perror("bind : ");
exit(-1);
}
if((listen(sock, MAX_CLIENTS)) == ERROR)
{
perror("listen");
exit(-1);
}
printf("\nThe TCPServer Waiting for client on port %d\n",ntohs(server.sin_port));
fflush(stdout);
FILE *fp;
char path[1035];
/* Open the command for reading. */
fp = popen("/bin/ls /etc/", "r");
if((new = accept(sock, (struct sockaddr *)&client, &sockaddr_len)) == ERROR)
{
perror("accept");
exit(-1);
}
printf("New Client connected from port no %d and IP %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
data_len = 1;
int path_len;
while (fgets(path, sizeof(path)-1, fp) != NULL) {
path_len = strlen(path);
send(new, path, path_len, 0);
}
printf("Client disconnected\n");
close(new);
close(sock);
}
CLIENT:
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "unistd.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "strings.h"
#include "arpa/inet.h"
#define BUFFER 1024
main(int argc, char **argv)
{
struct sockaddr_in serv;
int sock;
char in[BUFFER];
char out[BUFFER];
int len;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(-1);
}
serv.sin_family = AF_INET;
serv.sin_port = htons(atoi(argv[2]));
serv.sin_addr.s_addr = inet_addr(argv[1]);
bzero(&serv.sin_zero, 8);
printf("\nThe TCPclient %d\n",ntohs(serv.sin_port));
fflush(stdout);
if((connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr_in))) == -1)
{
perror("connect");
exit(-1);
}
len = 1;
while(len != 0) {
len = recv(sock, out, BUFFER, 0);
out[len] = '\0';
printf("Output: %s\n", out);
}
close(sock);
}
The server code takes the port number as command line argument and the client takes the ip address (127.0.0.1 for localhost) and the port number as command line arguments.
Even if you are running your server in some other language you can simply use the socket primitives for that server to send data to the client file.
NOTE: The code has been written in C and may produce some errors when compiling with C++. Please check for the compilation errors.
Upvotes: 0
Reputation: 20718
Given a netcat implementation, you already have what you need. Suppose your client is called /path/to/client
, you want to connect to service.example.com
at port 1234.
Either your netcat is like ncat from nmap, then you can do:
ncat -c ``/path/to/client`` service.example.com 1234
If your netcat is more minimalistic, you have to use a pipe:
mkdir pipes
cd pipes
mkfifo reverse_pipe
/path/to/client < reverse_pipe | nc service.example.com 1234 > reverse_pipe
mkfifo
creates a named pipe in the file system. It looks like a file, but is not (if you take a look using ls -l
, you’ll notice that its mode starts with p
, not with -
as for usual files). This is like what foo | bar
does, but it has a file name and is not opened by any process.
By passing this as input/output to a process, you can connect two commands manually (that is, without shell magic such as |
). Data written to pipes is not stored in the file system, but available for processes reading from the pipe. Data written is only ever read once. It works exactly like the pipes from shells, except that it has a name in the file system.
Upvotes: 2