ssh_channel_read_nonblocking( ) just echoback the given command? - c

I am trying to implement an ssh client using libssh but output seems to just be an echo of whatever been sent main part of program is :
do {
printf("Enter Command or q to exit: ");
fgets(command, 100, stdin);
command[strlen(command)-1] = 0;
if (ssh_channel_write(channel, command, strlen(command)) != strlen(command)) {
fprintf(stderr, "Unable to execute command\n");
exit(1);
}
printf("Data Sent: %s\n", command);
sleep(1);
while ((bytes_recieved = ssh_channel_read_nonblocking(channel, output, 2024, 0))) {
if (bytes_recieved < 1) {
fprintf(stderr, "Error Reading Output or End Of Data\n");
break;
}
printf("Data Recieved(%d): %.*s\n", bytes_recieved, bytes_recieved, output);
}
}while (strcmp(command, "q")!=0 ||strcmp(command, "Q")!=0 );
first command result in what I guess the banner to be sent althought I guess the banner is supposed to be sent before connection , this is output for only the first command after that anything i type is just echod back.
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-40-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* "If you've been waiting for the perfect Kubernetes dev solution for
macOS, the wait is over. Learn how to install Microk8s on macOS."
https://www.techrepublic.com/article/how-to-install-microk8s-on-macos/
65 updates can be installed immediately.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable
Your Hardware Enablement Stack (HWE) is supported until April 2025.
sshd_config files (server side) have been edited to include this as highlights:
AllowTcpForwarding no
PasswordAuthentication yes
PermitRootLogin prohibit-password
AllowUsers user_name
Whole code is here for anyone if he want's to use or test on it just change your username in ssh_options_set( ) part of the code.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <libssh/libssh.h>
int main(int argc, char* argv[])
{
printf("libssh version: %s\n", ssh_version(0));
if (argc < 2){
fprintf(stderr, "USAGE command hostname\n");
exit(1);
}
char* hostname = argv[1];
int port = 22;
ssh_session ssh = ssh_new();
ssh_options_set(ssh, SSH_OPTIONS_HOST, hostname);
ssh_options_set(ssh, SSH_OPTIONS_PORT, &port);
// TODO: Enable it in the future
int verbosity = SSH_LOG_PROTOCOL;
ssh_options_set(ssh, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
int error_code = ssh_connect(ssh);
if (error_code != SSH_OK){
fprintf(stderr, "Error creating connection with error %d", error_code);
exit(1);
}
printf("Connected to %s on port %d.\n", hostname, port);
printf("banner %s\n", ssh_get_serverbanner(ssh));
ssh_key key;
if(ssh_get_server_publickey(ssh, &key) != SSH_OK) {
fprintf(stderr,"Couldnt get server key\n");
exit(1);
}
unsigned char* hash;
size_t hash_len;
if(ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA1, &hash, &hash_len)!=SSH_OK){
fprintf(stderr, "Error Calculating Hash\n");
exit(1);
}
printf("Host public key hash:\n");
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA1, hash, hash_len);
ssh_key_free(key);
ssh_clean_pubkey_hash(&hash);
enum ssh_known_hosts_e known = ssh_session_is_known_server(ssh);
switch (known) {
case SSH_KNOWN_HOSTS_OK:printf("known Host\n");break;
case SSH_KNOWN_HOSTS_NOT_FOUND:printf("no host file\n");break;
case SSH_KNOWN_HOSTS_CHANGED:printf("Host Changed\n");break;
case SSH_KNOWN_HOSTS_ERROR:
printf("Host error. %s\n", ssh_get_error(ssh)); return 1;
case SSH_KNOWN_HOSTS_UNKNOWN: printf("Unknown Host verify please\n");break;
}
if(known == SSH_KNOWN_HOSTS_CHANGED){
printf("Server key changed Exiting\n");
exit(1);
}
if (
known == SSH_KNOWN_HOSTS_OTHER ||
known == SSH_KNOWN_HOSTS_UNKNOWN ||
known == SSH_KNOWN_HOSTS_NOT_FOUND)
{
printf("Do you want to trust this host\n");
char answer[10];
fgets(answer, 10, stdin);
if(answer[0] == 'y' || answer[0] == 'Y'){
ssh_session_update_known_hosts(ssh);
}else{
printf("Not trusting it\n");
exit(1);
}
}
ssh_options_set(ssh, SSH_OPTIONS_USER, "my_user");
printf("Enter password: ");
char pass[20];
fgets(pass, 20, stdin);
pass[strlen(pass)-1] = 0 ;
if(ssh_userauth_password(ssh, 0, pass) != SSH_AUTH_SUCCESS){
fprintf(stderr, "Unable to Authentication\n");
exit(1);
}else {
printf("Authentication successful!\n");
}
int err = ssh_userauth_publickey_auto(ssh, NULL, NULL);
if (err == SSH_AUTH_ERROR){
fprintf(stderr, "Unable to Authunticate\n");
exit(1);
}
ssh_channel channel = ssh_channel_new(ssh);
if(!channel){
fprintf(stderr, "Couldnt create a channel\n");
exit(1);
}
if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr, "Error Openning Session\n");
exit(1);
}
if (ssh_channel_request_pty(channel) != SSH_OK){
fprintf(stderr, "Can't initiate terminal\n");
exit(1);
}
if(ssh_channel_change_pty_size(channel, 80, 400) != SSH_OK){
fprintf(stderr, "Error Changing size of terminal\n");
exit(1);
}
if(ssh_channel_request_shell(channel) != SSH_OK){
fprintf(stderr, "Couldn't request a shell\n");
exit(1);
}
char command[100];
char output[2024];
int bytes_recieved;
do {
printf("Enter Command or q to exit: ");
fgets(command, 100, stdin);
command[strlen(command)-1] = 0;
if (ssh_channel_write(channel, command, strlen(command)) != strlen(command)) {
fprintf(stderr, "Unable to execute command\n");
exit(1);
}
printf("Data Sent: %s\n", command);
sleep(1);
while ((bytes_recieved = ssh_channel_read_nonblocking(channel, output, 2024, 0))) {
if (bytes_recieved < 1) {
fprintf(stderr, "Error Reading Output or End Of Data\n");
break;
}
printf("Data Recieved(%d): %.*s\n", bytes_recieved, bytes_recieved, output);
}
}while (strcmp(command, "q")!=0 ||strcmp(command, "Q")!=0 );
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(ssh);
ssh_free(ssh);
return 0;
}

Related

Socket not completely filling receive buffer

I'm building my own netcat style listener in C for a project that I'm working on.
The client (linux in this case) connects to the listener using netcat, and from the listener I'm able to send linux commands back. When running commands which give a small output (e.g. whoami, uname, pwd) the output comes back fine. However, when running a command that can give a substantial output (e.g. ls -la), I only get partial output until I send another command, which then means subsequent commands are executing the previous command. Screenshot:
Fig 1: Start of output
Fig 2: Entering another command to force output to finish
Fig 3: Now I'm one command behind, giving incorrect output.
Code as follows (includes/defines/other functions left out for brevity):
int main(int argc, char *argv[])
{
char readbuff[262144];
char user_input[1024] = "";
struct sockaddr_in srv, cln;
int bnd, checkrtr, len, lstn, new_sfd, rd, result, sfd, val;
if(argc != 2)
{
fprintf(stderr, "[*]Usage: %s <target_router>\n", argv[0]);
return -1;
}
check_router(argv[1]);
// Start a listener on port 8888
// Create the socket
sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1)
{
fprintf(stderr, "\n[*]socket: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
fprintf(stdout, "\n[*]Socket created.");
}
val = 1;
result = 0;
result = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
if(result == -1)
{
fprintf(stderr, "\n[*]setsockopt: %s (%d)", strerror(errno), errno);
}
else
{
fprintf(stdout, "\n[*]Address reuse set");
}
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = inet_addr(IP);
srv.sin_port = htons(atoi(LPORT));
len = sizeof(srv);
bnd = bind(sfd, (struct sockaddr*)&srv, len);
if(bnd != 0)
{
fprintf(stderr, "\n[*]bind: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
fprintf(stdout, "\n[*]Socket bound");
}
lstn = listen(sfd, 10);
if(lstn != 0)
{
fprintf(stderr, "\n[*]listen: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
fprintf(stdout, "\n[*]Server listening on %s:%s", IP, LPORT);
}
socklen_t len_c = sizeof(cln);
new_sfd = accept(sfd, (struct sockaddr*)&cln, &len_c);
if(new_sfd == -1)
{
fprintf(stderr, "\n[*]accept: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
char *ip_c = inet_ntoa(cln.sin_addr);
fprintf(stdout, "\n[*]New connection from client: %s:%d\n", ip_c, ntohs(cln.sin_port));
while(1)
{
memset(readbuff, 0x00, sizeof(readbuff));
memset(user_input, 0x00, sizeof(user_input));
fgets(user_input, sizeof(user_input), stdin);
if(user_input[0] == '\n')
{
continue;
}
int send_data = send(new_sfd, user_input, sizeof(user_input), 0);
if(send_data == -1)
{
fprintf(stderr, "\n[*]send: %s (%d)", strerror(errno), errno);
continue;
}
rd = read(new_sfd, readbuff, sizeof(readbuff));
fprintf(stdout, "\n size of rd: %d", rd);
fprintf(stdout, "\n size of readbuff: %ld", sizeof(readbuff));
if(rd > 0)
{
fprintf(stdout, "\n%s", readbuff);
}
else if(rd == 0)
{
fprintf(stdout, "\n[*]Client connection closed.\n");
continue;
//break;
}
else
{
fprintf(stderr, "\n[*]recv: %s (%d)", strerror(errno), errno);
continue;
}
}
}
}
Is anyone able to give me a reason why the output stops partway through please?
That's quite to be expected.
A single read can only read as much data as has been received so far (or otherwise it would need to bend time and space). The other end may also not have sent off everything they have to send by the time you issue read, so a single read won't be able to read everything either (because, well, it may not have been sent).
Since TCP is a stream protocol, you will need to devise a way to know how many bytes to expect for a single "message" from the other end, and read exactly that many bytes so you know you've gotten everything the other end has to say; I'd recommend some sort of Type-Length-Value scheme, even if you didn't need more than 1 type at present.

ssh_scp_read returns garbage

I'm trying to download a file from my server; both the client and the server are Linux, yet ssh_scp_read() returns an incorrect integer. According to the documentation the function writes up to 65536 bytes, yet is only reading 16384 when the file is 37980, but that's not my main concern; near the end of this 16384 bytes it starts to fill the buffer with NULL garbage, that will then be written to the file.
The creation of recursive directories works fine; the problem is downloading files larger than 16384 bytes. At this point I'll use sftp instead of scp, but I would like to know what I am doing wrong.
This is the function code:
int get(ssh_session gno_ses,ssh_scp scp)
{
int rc;
int size, permissions;
char *buff, *filename, path[PATH_MAX];
while(1)
{
rc = ssh_scp_pull_request(scp);
switch (rc)
{
// cases [...]
case SSH_SCP_REQUEST_NEWFILE:
size = ssh_scp_request_get_size(scp);
printf("Size is %d\n",size);
filename = strdup(ssh_scp_request_get_filename(scp));
permissions = ssh_scp_request_get_permissions(scp);
FILE *file;
file = fopen(filename, "w+");
if (!file)
{
ssh_scp_deny_request(scp,"Unable to open");
fprintf(stderr, " %s: %s\n", filename, strerror(errno));
fclose(file);
break;
}
buff = malloc(size);
printf("Size of buffer is %d\n", size);
if (!buff)
{
fprintf(stderr, "\nBuff memory allocation error.\n");
return SSH_ERROR;
}
if( ssh_scp_accept_request(scp) != SSH_OK)
{
fprintf(stderr, "Error accepting request: %s\n", ssh_get_error(gno_ses));
break;
}
do
{
rc = ssh_scp_read(scp, buff, size);
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(gno_ses));
break;
}
if (fwrite(buff, 1, size, file) != size)
{
perror("Error at writting to file: ");
break;
}
printf("ssh_scp_read got %d\n",rc);
} while (rc != 0);
fclose(file);
free(filename);
free(buff);
break;
}
}
return SSH_OK;
}
And this is the output:
Size is 37980
Size of buffer is 37980
ssh_scp_read got 16384
ssh_scp_read got 16384
ssh_scp_read got 5212
Error receiving file data: ssh_scp_read called under invalid state
Any input would be appreciated.
The problem was that I was writing size bytes when indeed scp_scp_read() had reported that it had read less than that:
rc = ssh_scp_read(scp, buff, size);
fwrite(buff, 1, size, file)
The fix is to write only rc bytes:
int len_loop = size;
int len;
do
{
rc = ssh_scp_read(scp, buff, size);
if (rc == SSH_ERROR || rc < 0)
{
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(gno_ses));
break;
}
else if (!rc)
{
break;
}
len = fwrite(buff, 1, rc, file);
if (len != rc)
{
perror("Error at writting to file: ");
break;
}
printf("ssh_scp_read got %d\n",rc);
len_loop -= rc;
} while(len_loop);
change your inner loop as
int len = size;
do
{
rc = ssh_scp_read(scp, buff, size);
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n",
ssh_get_error(gno_ses));
break;
}
if (fwrite(buff, 1, rc, file) != size)
{
perror("Error at writting to file: ");
break;
}
printf("ssh_scp_read got %d\n",rc);
len-=rc;
} while (len);

Strange File Reading Error

This program uses pipes to pass messages between processes. I compile with
gcc -Wall -o p2 p2.c INIT.DAT LOG.DAT TRANS1 TRANS2
I keep getting this error after compilation:
/usr/bin/ld:INIT.DAT: file format not recognized; treating as linker script
/usr/bin/ld:INIT.DAT:1: syntax error
with this source code:
#include "my.h"
int main(int argc, char **argv)
{
int pipe1[2], pipe2[2], pipe3[2];
int pid[3];
int p;
int len, i, index, check, oneOrTwo;
char val[10];
char buff[MAXLINE];
char strLog[MAXLINE];
char* token;
FILE *log, *trans1, *trans2, *init;
//Create pipes
p = pipe(pipe1);
if(p < 0)
{
printf("pipe error");
exit(0);
}
else
printf("successful pipe1 = %d\n", p);
p = pipe(pipe2);
if(p < 0)
{
printf("pipe error");
exit(0);
}
else
printf("successful pipe2 = %d\n", p);
p = pipe(pipe3);
if(p < 0)
{
printf("pipe error");
exit(0);
}
else
printf("successful pipe3 = %d\n", p);
//Store Manager
pid[0] = fork();
if(pid[0] == 0)
{
//Close unused channels
if(close(pipe1[1]) == -1)
printf("close error closing pipe1[1]\n");
if(close(pipe2[0]) == -1)
printf("close error closing pipe2[0]\n");
if(close(pipe3[0]) == -1)
printf("close error closing pipe3[0]\n");
//open INI.DAT
init = fopen(argv[1], "r");
if(init == NULL)
{
printf("INIT.DAT failed to open");
exit(0);
}
len = 0;
//Gets TABLE size
while(fgets(buff, MAXLINE, init) != NULL)
len++;
struct TABLE table[len];
i = 0;
init = fopen(argv[1], "r");
//Fills table
while(fgets(buff, MAXLINE, init) != NULL)
{
//id
token = strtok(buff, " ");
strcpy(table[i].id, token);
//value
token = strtok(NULL, " ");
table[i].value = atoi(token);
i++;
}
//Opens LOG.DAT
log = fopen(argv[2], "r+");
if(log == NULL)
{
printf("LOG.DAT failed to open");
exit(0);
}
//Send and receive messages
while(1)
{
check = 0;
//Quit when pipe is closed
if(read(pipe1[0], buff, MAXLINE) == -1)
break;
strcpy(strLog, "Store Manager received message: ");
strcat(strLog, buff);
fwrite(strLog, 1, sizeof(strLog), log);
//1 or 2
token = strtok(buff, " ");
oneOrTwo = atoi(token);
//pid
token = strtok(NULL, " ");
//U
token = strtok(NULL, " ");
//Update
if(strcmp(token, "U") == 0)
{
//id
token = strtok(NULL, " ");
for(i = 0; i < len; i++)
{
if(token == table[i].id)
{
check = 1;
index = i;
//value
token = strtok(NULL, " ");
table[i].value += atoi(token);
}
}
//Update failed
if(check == 0)
{
strcpy(strLog, "Store Manager sent message: Error updating table");
fwrite(strLog, 1, sizeof(strLog), log);
if(oneOrTwo == 1)
write(pipe2[1], "Error updating table", MAXLINE);
else
write(pipe3[1], "Error updating table", MAXLINE);
}
//Update succeeded
else
{
strcpy(strLog, "Store Manager sent message: U 0 ");
strcat(strLog, table[index].id);
strcat(strLog, " ");
sprintf(val, "%d", table[index].value);
strcat(strLog, val);
fwrite(strLog, 1, sizeof(strLog), log);
if(oneOrTwo == 1)
write(pipe2[1], strLog, MAXLINE);
else
write(pipe3[1], strLog, MAXLINE);
}
}
//Read
else
{
check = 0;
for(i = 0; i < len; i++)
{
//Read succeeded
if(token == table[i].id)
{
check = 1;
strcpy(strLog, "Store Manager sent message: R ");
sprintf(val, "%d", oneOrTwo);
strcat(strLog, val);
strcat(strLog, " ");
strcat(strLog, table[i].id);
strcat(strLog, " 0");
fwrite(strLog, 1, sizeof(strLog), log);
if(oneOrTwo == 1)
write(pipe2[1], strLog, MAXLINE);
else
write(pipe3[1], strLog, MAXLINE);
}
}
//Read failed
if(check == 0)
{
strcpy(strLog, "Store Manager sent message: Error reading table");
fwrite(strLog, 1, sizeof(strLog), log);
if(oneOrTwo == 1)
write(pipe2[1], "Error reading table", MAXLINE);
else
write(pipe3[1], "Error updareadingting table", MAXLINE);
}
}
}
//Close files and quit process
fclose(init);
fclose(log);
exit(0);
}
//P1
pid[1] = fork();
if(pid[1] == 0)
{
//Close unused channels
if(close(pipe1[0]) == -1)
printf("close error closing pipe1[0]\n");
if(close(pipe2[1]) == -1)
printf("close error closing pipe2[1]\n");
//Open LOG.DAT
log = fopen(argv[2], "r+");
if(log == NULL)
{
printf("LOG.DAT failed to open");
exit(0);
}
//Open TRANS1
trans1 = fopen(argv[3], "r");
if(log == NULL)
{
printf("LOG.DAT failed to open");
exit(0);
}
//Send and receive messages
while(fgets(buff, MAXLINE, trans1) != NULL)
{
strcpy(strLog, "Process 1 sent message: ");
strcat(strLog, buff);
fwrite(strLog, 1, sizeof(strLog), log);
write(pipe1[1], buff, MAXLINE);
read(pipe2[0], buff, MAXLINE);
strcpy(strLog, "Process 1 received message: ");
strcat(strLog, buff);
fwrite(strLog, 1, sizeof(strLog), log);
sleep(3);
}
//Close files and quit process
fclose(trans1);
fclose(log);
exit(0);
}
//P2
pid[2] = fork();
if(pid[2] == 0)
{
//Close unused channels
if(close(pipe1[0]) == -1)
printf("close error closing pipe1[0]\n");
if(close(pipe3[1]) == -1)
printf("close error closing pipe3[1]\n");
//Open LOG.DAT
log = fopen(argv[2], "r+");
if(log == NULL)
{
printf("LOG.DAT failed to open");
exit(0);
}
//Open TRANS2
trans2 = fopen(argv[4], "r");
if(log == NULL)
{
printf("LOG.DAT failed to open");
exit(0);
}
//Send and receive messages
while(fgets(buff, MAXLINE, trans1) != NULL)
{
strcpy(strLog, "Process 1 sent message: ");
strcat(strLog, buff);
fwrite(strLog, 1, sizeof(strLog), log);
write(pipe1[1], buff, MAXLINE);
read(pipe3[0], buff, MAXLINE);
strcpy(strLog, "Process 1 received message: ");
strcat(strLog, buff);
fwrite(strLog, 1, sizeof(strLog), log);
sleep(3);
}
//Close files and quit process
fclose(trans2);
fclose(log);
exit(0);
}
//Wait for processes to quit
for(i = 0; i < 3; i ++)
{
if(waitpid(pid[i], NULL, 0) == -1)
{
printf("waitpid error");
exit(0);
}
}
}
with these input files:
I
(NOT IN FILE) INIT.DAT
DISNEY 3
INTEL 56
Hate
(NOT IN FILE) TRANS1
R XXXX
R DISNEY
This
(NOT IN FILE) TRANS2
R INTEL
U INTEL 45
U DISNEY 21
U DISNEY 21
R DISNEY
U DISNEY 21
U DIY 21
Formatting
LOG.DAT is empty.
I have no idea why I'm getting this error, because even if I change INIT.DAT to INIT.txt or any other file format, it still doesn't work. It has to be an issue with my code, but I can't see it.
Thanks.

client server in c- file transfer issue for larger files

The below code works fine for smaller files where the last packet contains data less than maximum length, the function exit properly by displaying file received.
How ever if the last packet or buffer of file being transmitted contains exact number as the size of receiving buffer array 512 in my case. then th program keeps waiting for next packet.
All files with size multiple of 512 in my case stuck.
Below is the code:
CLIENT code for receiving:
void receiveFile() {
printf("inside receiveFile method\n");
char* fr_name = "final.txt";
int i;
FILE *fr = fopen(fr_name, "a");
int LENGTH = 512;
int fileLength=0;
char revbuf[LENGTH];
if (fr == NULL) {
printf("File %s Cannot be opened.\n", fr_name);
} else {
printf("starting to write the file\n");
bzero(revbuf, LENGTH);
int fr_block_sz = 0;
i=0;
while ((fr_block_sz = recv(4, revbuf, LENGTH, 0)) > 0) {
fileLength+=fr_block_sz;
i++;
printf("Received buffer: %d, %d\n",fr_block_sz,i);
int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);
if (write_sz < fr_block_sz) {
error("File write failed.\n");
}
bzero(revbuf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512) {
break;
}
}
if (fr_block_sz < 0) {
if (errno == EAGAIN) {
printf("recv() timed out.\n");
} else {
fprintf(stderr, "recv() failed due to errno = %d\n", errno);
}
}
printf("FILE RECEIVED....Total Bytes received:%d \n",fileLength);
}
fclose(fr);
}
Server for Receiving the file:
void sendFile() {
printf("inside sendFile method\n");
char* fs_name = "mb.txt";
int LENGTH = 512;
int sfileLength=0;
char sdbuf[LENGTH];
int i=0;
printf("[Client] Sending %s to the Server... \n", fs_name);
FILE *fs = fopen(fs_name , "r");
if (fs == NULL) {
perror("ERROR: File not found.\n");
exit(1);
}
bzero(sdbuf, LENGTH);
int fs_block_sz;
while ((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0) {
i++;
printf("Sent:%d , %d \n", fs_block_sz,i);
sfileLength+=fs_block_sz;
if (send(4, sdbuf, fs_block_sz, 0) < 0) {
fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n",
fs_name, errno);
break;
}
bzero(sdbuf, LENGTH);
}
printf("File sent.... Total Bytes:%d\n", sfileLength);
fclose(fs);
}
if (fr_block_sz == 0 || fr_block_sz != 512) {
break;
}
Remove this code. The first part of the test can never be true due to the 'while' condition, and the second part is unnecessary for the same reason.

Read Register via Modbus

I am trying to write a c program to read data for morningstar sunsaver MPPT.
This is the simple program I found in net. But my program is unable to read data from register.
#include <stdlib.h>
#include <errno.h>
#include "src/modbus.h"
int main(void)
{
modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;
ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N',8,1);
if (ctx == NULL) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for (i=0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
modbus_close(ctx);
modbus_free(ctx);
}
It does not work for me. I get the following error message:
Bad file descriptor
By reading the documentation from LibModBus, I think you're missing a call to modbus_connect.
Try connecting before reading registers:
ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N',8,1);
if (ctx == NULL) {
fprintf(stderr, "Creation failed: %s\n", modbus_strerror(errno));
return -1;
}
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
Also, remember to modbus_close and modbus_free your context before exiting due to further error conditions. For example:
rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
modbus_close(ctx);
modbus_free(ctx);
return -1;
}
It turned out to be trying to read from wrong Serial port.
Reading from /dev/ttyS3 worked.
I later realize that serial port are from /dev/ttyS0 .. /dev/ttyS9

Resources