When file (pipe) descriptor is shared between parent and child process.
When one of them closes it other one can`t use it any more?
Child after its creation executes close(pipefd[1]);
After that parent can't write any more? because the pipe's write end is closed. but still the below code works. How does it happen?
int main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2)
{
fprintf(stderr, "Usage: %s \n", argv[0]);
exit(EXIT_FAILURE);
}
if (pipe(pipefd) == -1) /* An error has occurred. */
{
fprintf(stderr, "%s", "The call to pipe() has failed.\n");
exit(EXIT_FAILURE);
}
cpid = fork(); /* fork() returns the child process's PID */
if (cpid == -1) /* An error has occurred. */
{
fprintf(stderr, "%s", "The call to fork() has failed.\n");
exit(EXIT_FAILURE);
}
if (cpid == 0)
{ /* Child reads from pipe */
printf("I am the child.\n");
close(pipefd[1]); /* Close unused write end */
printf("The child is about to read from the pipe.\n");
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
printf("The child has just echoed from the pipe to standard output.\n");
_exit(EXIT_SUCCESS);
}
else
{ /* Parent writes argv[1] to pipe */
printf("I am the parent.\n");
close(pipefd[0]); /* Close unused read end */
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]); /* Closing creates the EOF marker. */
printf("The parent has just written data into the pipe.\n");
printf("The parent will now wait for the child to terminate.\n");
wait(NULL); /* Parent waits for the child to terminate */
exit(EXIT_SUCCESS);
}
return 0;
}
Related
Recently, I am trying to use bpf ringbuf in uprobe example of libbpf. But when running, error occurred which is "libbpf: load bpf program failed: Invalid argument". I have no idea why this happened. Could anyone help? Below is my test code.
Kernel space code: uprobe.bpf.c, define a rb struct, and use bpf_ringbuf_reserve in uprobe code block.
#include <linux/bpf.h>
#include <linux/ptrace.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "Dual BSD/GPL";
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");
SEC("uprobe/func")
int BPF_KPROBE(uprobe, int a, int b)
{
__u64* e = bpf_ringbuf_reserve(&rb, sizeof(__u64), 0);
if (!e)
return 0;
bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b);
return 0;
}
SEC("uretprobe/func")
int BPF_KRETPROBE(uretprobe, int ret)
{
bpf_printk("UPROBE EXIT: return = %d\n", ret);
return 0;
}
User space code: uprobe.c
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "uprobe.skel.h"
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
static void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}
/* Find process's base load address. We use /proc/self/maps for that,
* searching for the first executable (r-xp) memory mapping:
*
* 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat
* ^^^^^^^^^^^^ ^^^^^^^^
*
* Subtracting that region's offset (4th column) from its absolute start
* memory address (1st column) gives us the process's base load address.
*/
static long get_base_addr() {
size_t start, offset;
char buf[256];
FILE *f;
f = fopen("/proc/self/maps", "r");
if (!f)
return -errno;
while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) {
if (strcmp(buf, "r-xp") == 0) {
fclose(f);
return start - offset;
}
}
fclose(f);
return -1;
}
static int handle_event(void *ctx, void *data, size_t data_sz)
{
return 0;
}
/* It's a global function to make sure compiler doesn't inline it. */
int uprobed_function(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct uprobe_bpf *skel;
long base_addr, uprobe_offset;
int err, i;
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
bump_memlock_rlimit();
/* Load and verify BPF application */
skel = uprobe_bpf__open_and_load();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
base_addr = get_base_addr();
if (base_addr < 0) {
fprintf(stderr, "Failed to determine process's load address\n");
err = base_addr;
goto cleanup;
}
/* uprobe/uretprobe expects relative offset of the function to attach
* to. This offset is relateve to the process's base load address. So
* easy way to do this is to take an absolute address of the desired
* function and substract base load address from it. If we were to
* parse ELF to calculate this function, we'd need to add .text
* section offset and function's offset within .text ELF section.
*/
uprobe_offset = (long)&uprobed_function - base_addr;
/* Attach tracepoint handler */
skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe,
false /* not uretprobe */,
0 /* self pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* we can also attach uprobe/uretprobe to any existing or future
* processes that use the same binary executable; to do that we need
* to specify -1 as PID, as we do here
*/
skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe,
true /* uretprobe */,
-1 /* any pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uretprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* Set up ring buffer polling */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
fprintf(stderr, "Failed to create ring buffer\n");
goto cleanup;
}
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
"to see output of the BPF programs.\n");
for (i = 0; ; i++) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* trigger our BPF programs */
fprintf(stderr, ".");
uprobed_function(i, i + 1);
sleep(1);
}
cleanup:
ring_buffer__free(rb);
uprobe_bpf__destroy(skel);
return -err;
}
I'm a new to socket programming. I tried to connect a server to multiple clients and i have two problems in it. 1)I can't send a message unless i get a reply i.e if a client connects and sends a message,client can't send a message again until it gets reply from server. If client types some message it stores the messages and it sends the message after it gets a reply.
2)I want to restrict the number of connections to 1 and if some one connects no one else should connect until the client the client quits. If the client quits the one who is first in waiting should be connected.
server
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define MYPORT 3490 /* the port users connect to */
#define BACKLOG 0 /* max no. of pending connections in server queue */
#define MAXDATASIZE 200
void sigchld_handler(int s)
{
while( wait( NULL) > 0); /* wait for any child to finish */
}
int main( void)
{
int listenfd;
/* listening socket */
int connfd;
/* connection socket */
struct sockaddr_in server_addr; /* info for my addr i.e. server */
struct sockaddr_in client_addr; /* client's address info */
int sin_size;
/* size of address structure */
struct sigaction sa; /* deal with signals from dying children! */
int yes = 1;
char clientAddr[ 20]; /* holds ascii dotted quad address */
if ((listenfd = socket( AF_INET, SOCK_STREAM, 0)) == -1)
{
perror( "Server socket");
exit( 1);
}
/* Set Unix socket level to allow address reuse */
if( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,&yes, sizeof( int)) == -1)
{
perror( "Server setsockopt");
exit( 1);
}
sin_size = sizeof( server_addr);
memset( &server_addr, 0, sin_size);
/* zero struct */
server_addr.sin_family = AF_INET;
/* host byte order ... */
server_addr.sin_port = htons( MYPORT); /* . short, network byte order */
server_addr.sin_addr.s_addr = INADDR_ANY; /* any server IP addr */
if( bind( listenfd, (struct sockaddr *)&server_addr,sizeof( struct sockaddr)) == -1)
{
perror( "Server bind");
exit( 1);
}
if( listen( listenfd, BACKLOG) == -1)
{
perror( "Server listen");
exit( 1);
}
/* Signal handler stuff */
sa.sa_handler = sigchld_handler; /* reap all dead processes */
sigemptyset( &sa.sa_mask);
sa.sa_flags = SA_RESTART;
if( sigaction( SIGCHLD, &sa, NULL) == -1)
{
perror( "Server sigaction");
exit( 1);
}
while( 1)
{
/* main accept() loop */
sin_size = sizeof( struct sockaddr_in);
if( (connfd = accept( listenfd,(struct sockaddr *)&client_addr, &sin_size)) == -1)
{
perror( "Server accept");
continue;
}
strcpy( clientAddr, inet_ntoa( client_addr.sin_addr));
printf( "Server: got connection from %s\n", clientAddr);
if( !fork())
{
/* the child process dealing with a client */
char msg[ MAXDATASIZE];
int numbytes;
close( listenfd); /* child does not need the listener */
msg[ 0] = '\0';
/* no message yet! */
do
{
if( (numbytes =recv( connfd, msg, MAXDATASIZE -1, 0)) == -1)
{
perror( "Server recv");
exit( 1);
/* error end of child */
}
msg[ numbytes] = '\0';
/* end of string */
fprintf( stderr, "Message received: %s\n", msg);
do
{
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
printf( "Message to send: ");
scanf( "%s", msg);
if( send( connfd, msg, strlen( msg), 0) == -1)
{
perror( "server send");
//exit(1);
}
/* error end of child */
}
while( strcmp( msg, "quit") != 0);
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
//close( connfd);
//exit(0);
/* end of child! */
}
while(1);
//fork();
//close(connfd); /* parent does not need the connection socket */
return 0;
}
}
}
client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
/* for gethostbyname() */
#define PORT 3490
/* server port the client connects to */
#define MAXDATASIZE 100 /* max bytes to be received at once */</i>
int main( int argc, char * argv[])
{
int sockfd, numbytes;
char buf[ MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; /* server address info */
char msg[ MAXDATASIZE];
if( argc != 2) {
fprintf( stderr, "usage: client hostname\n");
exit( 1);
}
/* resolve server host name or IP address */
if( (he = gethostbyname( argv[ 1])) == NULL) { /* host server info */
perror( "Client gethostbyname");
exit( 1);
}
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1) {
perror( "Client socket");
exit( 1);
}
memset( &their_addr, 0, sizeof( their_addr));
/* zero all */
their_addr.sin_family = AF_INET;
/* host byte order .. */
their_addr.sin_port = htons( PORT);
/* .. short, network byte order */
their_addr.sin_addr = *((struct in_addr *)he -> h_addr);
if( connect( sockfd, (struct sockaddr *)&their_addr,
sizeof( struct sockaddr)) == -1) {
perror( "Client connect");
exit( 1);
}
do {
printf( "Message to send: ");
scanf( "%s", msg);
if( (numbytes = send( sockfd, msg, strlen( msg), 0)) == -1) {
perror( "Client send");
continue;
}
if( (numbytes = recv( sockfd, buf, MAXDATASIZE - 1, 0)) == -1) {
perror( "Client recv");
continue;
}
buf[ numbytes] = '\0';
/* end of string char */
printf( "Received: %s\n", buf);
} while( strcmp( msg, "quit") != 0);
close( sockfd);
return 0;
}
dear you have to use multithreading for this start a new thread to handle new connection
in that thread also use separate threads for receiving data and sending data ...
1)I can't send a message unless i get a reply i.e if a client connects
and sends a message,client can't send a message again until it gets
reply from server.
That's no wonder, since you have programmed this sequential arrangement of scanf and recv in your client's do loop. To handle message input and socket receipt in order of appearance, we can use select; your do loop could then look like:
do
{ fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(sockfd, &fds); // set of descriptors holds stdin and socket
printf("Message to send: "), fflush(stdout);
if (select(sockfd+1, &fds, NULL, NULL, NULL) < 0) break; // error?
// see which descriptors of set are ready
if (FD_ISSET(STDIN_FILENO, &fds))
{ // it is the standard input
scanf("%s", msg);
numbytes = send(sockfd, msg, strlen(msg), 0);
if (numbytes == -1) perror("Client send");
}
if (FD_ISSET(sockfd, &fds))
{ // this is the peer's message or termination
numbytes = recv(sockfd, buf, MAXDATASIZE - 1, 0);
if (numbytes <= 0)
{
perror("Client recv");
break; // no more data from peer, so close the connection
}
buf[numbytes] = '\0'; /* end of string char */
printf("Received: %s\n", buf);
}
} while (strcmp(msg, "quit") != 0);
2)I want to restrict the number of connections to 1 and if some one
connects no one else should connect until the client the client quits.
We can achieve this simply by not forking a server process after we accept a client connection request, but rather handling the message transfer in the one and only server task itself (quite similar as shown above for the client); just omit the lines if( !fork()) as well as return 0; instead uncomment the close(connfd); and don't forget to break out of the do loop when recv returns a nonpositive value.
Below is the code for restarting the socket connection server,so when their is some disturbance its able to reconnect but at some point or situations its not able to reconnect/connect what may be the issue in the code issue at below
/*** restarting the server by capturing the SIGHUP signal ***/
int isfirst;`enter code here`
char **command_args;
void sig_hangup(int signum)
{
if ( isfirst )
{
isfirst = 0;
fprintf(stderr, "Parent died\n");
}`enter code here`
else /* Restart! */
{
fprintf(stderr, "Restarting...\n");
/*** Kill all existing child processes ***/
execv(command_args[0], command_args);
fprintf(stderr, "Could not restart!!!\n");
abort();
}
}
void child(void)
{ struct sigaction act;
bzero(&act, sizeof(act));
act.sa_handler = sig_hangup;
act.sa_flags = SA_RESTART;
/* if ( sigaction(SIGHUP, &act, 0) != 0 )
perror("Can't capture SIGHUP");*/
for (;;)
{
fprintf(stderr, "[pid=%d] I'm still here\n", getpid());
sleep(1);
}
exit(0);
}
int main(int count, char *strings[])
{
isfirst = 1;
command_args = strings;
if ( fork() == 0 )
child();
sleep(1);
return 0;
}
I am using the select call and accepting the connection from "X" no of clients.
I made duplex connection i.e. server to client and client to server.
When connection is established between 2 entities ,I am going to send
data in chunks from one entity to other.
During send I read one file in chunks and send the data in chunks.
while(file_size !=0)
{
read_bytes = read(fd, buff, sizeof(buff));
cnt_ = send(_sock_fd,buff,actually_read,0);
file_size = file_size - cnt_;
printf("total sent remaining %d : %d\n",size,actually_read);
}
while at receiver side
//First I send the header which contain size it got accepted fine but during the following send call I used "get_readable_bytes" (Using ioctl) which returns me the no of bytes arrived at socket
`while(size != 0)
{
int test_ = 0;
while(((cnt_= get_readable_bytes(_sock_fd))== 0) )//&& test_ == 0
{
cnt_= get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_);
//test_ = test_ + 1;
}
while(cnt_ != 0)
{
actually_read = recv(_sock_fd, buff, sizeof(buff),0);
int _cnt = get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_-_cnt);
write(_fd,buff,actually_read);
cnt_ = cnt_ - actually_read;
test_ = 0;
}
`Now the problem is
1.During this execution of receive function control automatically go to the select function and it tries to execute whole receive function again so is there any way to synchronize the sender and receivers such that when the sender complete then start receiver or as soon as sender start receiver ?
2.And how do I maintain the count of bytes sent and received.
and this is my select call
`is_read_availble = select(maxfd + 1,&read_set,NULL,NULL,&timeout)`
with timeout 10sec.
Sketch of the kind of buffer code you need. (To allow partial reads/writes, the buffers need to be persistent between calls) BTW: you really need to handle the -1 return from read() and write() because they would seriously disturb your buffer-bookkeeping. EINTR + EAGAIN/EWOULDBLOCK is very common.
struct buff {
unsigned size;
unsigned bot;
unsigned top;
char *buff;
};
struct buff bf = {0,0,0,NULL};
initialisation:
bf.buff = malloc(SOME_SIZE);
/* ... error checking omitted */
bp.size = SOME_SIZE;
bp.bot = bp.top =0;
reading:
unsigned todo;
int rc;
/* (maybe) shift the buffer down to make place */
todo = bf.top - bf.bot;
if (todo) {
memmove (bf.buff, bf.buff + bf.bot, todo);
bf.top = todo; bf.bot = 0;
}
todo = bf.size - bf.top;
if (!todo) { /* maybe throttle? ... */ return; }
rc = read (fd, bf.buff+bp.top, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc == 0) {...}
else {
total_read += rc;
bp.top += rc;
}
writing:
unsigned todo;
int rc;
todo = bf.top - bf.bot;
if (!todo) { /* maybe juggle fd_set ... */ return; }
rc = write (fd, bf.buff+bp.bot, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc ==0) { ...}
else {
bp.bot += rc;
total_written += rc;
if (bp.bot == bp.top) bp.bot = bp.top =0;
}
/* ... this is the place to juggle the fd_set for writing */
It seems my questions are strange and i'm not getting enough help but I'm back.
I've another strange question which needs to be solved in emergency.
I'm developing an iPhone app. which uses libssh 2 for commands execution through iPhone over remote host. It's okay and working all methods and commands if i execute them in single.
My problem is,
consider a sequence of commands,
pwd
=> o/p will be /Users/mac01
cd xyz
=> nothing as o/p
pwd
=> o/p will be /Users/mac01/xyz
So, my question is to save the last state of the command which has been executed... but what I'm getting as o/p is
/Users/mac01
after second pwd command execution, which is wrong.
So, could anyone help me out with such type of problems..? Thanks in advance.
I'm using libssh 2.0 library.
The method executing command:
char* cmd_exec(const char *commandline, const char *host, const char *username, const char *password, int port){
int sock, rc, bytecount = 0;
char *cmd_contents;
if(!he)
{
struct sockaddr_in sin;
ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
endif
/* Init and Make Socket Connection */
/* Start Socket Connection */
sock = socket(AF_INET, SOCK_STREAM, 0);
ifndef WIN32
fcntl(sock, F_SETFL, 0);
endif
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
/*sin.sin_addr.s_addr = inet_addr(host);
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { // in case connection failure
fprintf(stderr, "Internet connection is required!\n");
return "NETWORKFAILURE";
}*/
//const char *c = getIPFromHost("pepsi");
//sin.sin_addr.s_addr = inet_addr(c);
/* IP Address Calculation */
he = gethostbyname(host);
if(!he)
return "Invalid hostname";
struct in_addr **addr_list;
addr_list = (struct in_addr **)he->h_addr_list;
//for(int i = 0; addr_list[i] != NULL; i++) {
if(addr_list != NULL){
sin.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
//printf("%s", inet_ntoa(*addr_list[0]));
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { // in case connection failure
fprintf(stderr, "Internet connection is required!\n");
return "NETWORKFAILURE";
}
}
}
/* End Socket Connection */
// Initialize and create Session Instance
if(!session)
{
session = libssh2_session_init();
if ( !session )
{
fprintf( stderr, "Error initializing SSH session\n" );
return "SESSIONFAILURE";
}
/* Since we have set non-blocking, tell libssh2 we are non-blocking */
//libssh2_session_set_blocking(session, 0);
// Session starting
if (libssh2_session_startup(session, sock)) {
fprintf(stderr, "Failure establishing SSH session\n");
return "SESSIONFAILURE";
}
/* Authenticate via password */
if(strlen(password) != 0){
if ( libssh2_userauth_password( session, username, password ) )
{
fprintf( stderr, "Unable to authenticate user [%s]"
"(wrong password specified?)\n", username );
return "AUTHENTICATIONFAILURE";
}
}else{
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/user/"
".ssh/id_rsa.pub",
"/home/user/"
".ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "\tAuthentication by public key failed\n");
return "AUTHENTICATIONFAILURE";
}
}
//libssh2_session_set_blocking(session, 1);
}
// Open a session channel for command execution
if(!channel)
{
channel = libssh2_channel_open_session(session);
if (!channel) {
fprintf(stderr, "Unable to open a session\n");
return "SESSIONFAILURE";
}
// Execute a command through channel
while( (rc = libssh2_channel_shell(channel)) ==
//while( (rc = libssh2_channel_exec(channel, commandline)) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 ) // if command execution failed
{
fprintf(stderr,"Error\n");
return "CMDFAILURE";
}
}
//libssh2_channel_write(channel,commandline,strlen(commandline));
do {
/* write the same data over and over, until error or completion */
rc = libssh2_channel_write(channel, commandline, sizeof(commandline));
if (rc < 0) {
fprintf(stderr, "ERROR %d\n", rc);
}
} while (rc == 0);
while (libssh2_channel_send_eof(channel) == LIBSSH2_ERROR_EAGAIN);
/* read channel output */
/* Start channel read */
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
// char *tcontents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
bytecount += rc;
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents){
free(cmd_contents);
}
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
fprintf(stderr, "\n");
}
else {
//fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else
break;
}
/* End channel read */
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN );
/* closing channel */
int exitcode = 127;
// while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN );
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
}
//
libssh2_channel_free(channel); // freeup memory
channel = NULL;
/*
libssh2_session_disconnect( session, "" ); // closing session
libssh2_session_free( session ); // free up memory
close( sock ); // closing socket
*/
return cmd_contents;
}
Try this maybe it works... i havent tried it but you can get enough idea and may be the proper solution
libssh2_session_set_blocking(session, 0);
char buffer[0x4000]; rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents)
{
free(cmd_contents);
}
buffer[i] = '\0';
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
hAPPY cODING...
libssh2_session_set_blocking(session, 0);
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents){
free(cmd_contents);
}
buffer[i] = '\0';
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}