how to get the responding result of executing shell command in C? - c

Update: I tried to print the return value of system(). If ssh failed, it will return 65280, if it succeed ,it returns 0.
I want to ssh to another machine from my laptop,I write a C program, it access to that machine and touch a file on that machine. But sometimes the network is not stable or maybe that machine is down. Therefore, ssh will failed. How could I know the ssh failed in that program ? Sometime ssh to that machine succeed, but touch that file failed, how to distinguish them in the C program? How could I know that shell command failed is because of ssh failed not touch ? I don't want to stare at the screen, I want the program to check that automatically.
here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(int argc,const char *argv[])
{
while(1)
{
system("ssh liulyix#localhost -p 22210 'touch script/rebooter.sh'");
sleep(5);
}
}

Read the man page for system.
The proto type is
int system (constant char *command)
The return values are
-1 system was unable to execute the command because of say a fork failure. Look at the man page for execve and look at the error number which may raised. All these errnos are reasons why system will return -1.
All other returns ed values are the exit code of the command. 0 implies success, all other values imply the command crashed with EXIT_FAILURE.

Using function popen() will be more easy:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(int argc,const char *argv[])
{
FILE *fp;
fp = popen("ssh liulyix#localhost -p 22210 'touch script/rebooter.sh'", "r");
while(1)
{
char *line; char buf[1024];
line = fgets(buf, 1024, fp);
if (line == NULL) break;
printf("%s", line);
}
pclose(fp);
return 0;
}

Related

Why am I not getting an output when reading from a file descriptor?

I am trying to read from a file and print it for the user to read. My task is similar to the UNIX 'cat' command but my code does not print anything.
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h> //for printf
int main(int argc, char *argv[])
{
int fd;
char buffer;
if(argc==1)
fd=open(argv[1],O_RDONLY);
else
if (fd=open(argv[1],O_RDONLY) ==0){
printf("Error opening");
return(0);
}
while((read(fd,&buffer,1)) != -1){
read(fd,&buffer,1);
write(STDOUT_FILENO,buffer, 1);
}
return(0);
}
You're reading from the wrong FD due to a precedence issue. if (fd=open(argv[1],O_RDONLY) ==0) is parsed as if (fd=(open(argv[1],O_RDONLY) ==0)). You wanted it to be parsed as if ((fd=open(argv[1],O_RDONLY)) ==0) instead, so write that.
Other problems:
0 is a legitimate FD. You should check against -1 instead to see if open failed.
If argc is 1, then argv[1] is a null pointer, which you shouldn't try to open.
Calling read twice in a row instead of just once means you're going to throw away every other character.
write expects a pointer, so pass it &buffer too like you do with read. Remember it's not printf.
read can return 0 when you get to EOF, and right now that will send your program into an infinite loop printing the final character.

Segmentation Fault with mkfifo

I've got a problem with the following code:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(int argc, char*argv[]){
FILE * tube;
char chaine[10];
mkfifo("glue", 0666);
tube = fopen("glue", "r");
while(1){
fgets(chaine, 10, tube);
printf("%s\n", chaine);
}
}
It's a program that mimics a server behavior, however when I run it on my Ubuntu Machine, either Windows 10 Ubuntu subsystem or the normal OS, the mkfifo line returns this error:
Segmentation Fault(core dumped)
Pls Help!
EDIT:
Forgot to send the version with the mkfifo test:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(int argc, char*argv[]){
FILE * tube;
char chaine[10];
int errValue = mkfifo("glue", 0666);
perror("mkfifo");
if( errValue < 0){
printf("Error: %d\n", errValue);
exit(EXIT_FAILURE);
}
tube = fopen("glue", "r");
while(1){
fgets(chaine, 10, tube);
printf("%s\n", chaine);
}
}
The output of the program is:
mkfifo: Operation not permitted
Error: -1
And the one of umask is:
0000
And thank you immensely everyone for participating in this post!!:)
EDIT, PROBLEM SOLVED THANKS TO achal and everyone, thank you sooo much:
-One problem, the core one, was in using a 0022 umask instead of an 0002, thanks achal for this solution.
-The second problem was me using the Ubuntu subsystem for windows and try to run the program from CLI while it was located on the Windows desktop, windows doesn't give pipe permissions for the desktop apparently.
-The solution was to switch to my Ubuntu boot and change the umask and then it worked perfectly:)
Thanks to achal and everyone who participated in this post.
PROBLEM SOLVED.
mkfifo() is a IPC mechanism useful for create a FIFO for communicating same or different process.
man pages of mkfifo() says "The mkfifo() system call creates a new fifo file with name path. The access permissions are specified by mode and restricted by the umask(2) of the calling process"
As you mentioned in comments in your terminal umask value was 0000 means no permission that's why mkfifo() fails, so modify umask value using CLI according your requirement.
xyz#xyz-PC:~$ umask 0002
xyz#xyz-PC:~/s_flow$ umask
0002
and modify your code as
int main(int argc, char*argv[]){
FILE * tube;
char chaine[10];
int errValue = mkfifo("glue", 0666);
perror("mkfifo");
if( errValue < 0){
printf("Error: %d\n", errValue);
exit(EXIT_FAILURE);
}
tube = fopen("glue", "r");
if(tube == NULL)
{
printf("error in opening file :\n");
return 0;
}
while(1){
fgets(chaine, 10, tube);
printf("%s\n", chaine);
}
}
Once umask value is set, execute your program.
I hope it helped lot

How many ways are there to execute system command in C program for windows

I am using MS visual studio 2008, for C coding.
I know we can use
"int system(const char *command)" to execute commands.
Is there any other method to execute system commands in C program.
Also I need to store output of executed command in a variable.
system() function execute command and send output to stdout , is there any way to read from stdout and store in variable.
So my ultimate goal is to execute system command in C program for windows (using visual studio) and store output of that command in a variable.
Any suggestions ?
Standard C libraries give you only one way to execute external command in OS, so use int system(const char *command).
You can save output of this command to text file, and then read this file from you program.
For example:
#include <stdio.h>
#include <stdlib.h>
#define TMP_FILE_NAME "TMP_FOLDER_CONTENT.txt"
int main(int argc, char *argv[])
{
system("dir C:\* > "TMP_FILE_NAME);
FILE * fdir = fopen(TMP_FILE_NAME, "r");
char buff[100];
if (fdir)
{
while (1) {
if (fgets(buff, 100, fdir) == NULL) break;
printf("%s", buff);
}
}
fclose(fdir);
remove(TMP_FILE_NAME);
return 0;
}
Where dir is a program to be executed, C:\* - argument of the program, and > - redirection of standard output for that command after which filename TMP_FOLDER_CONTENT.txt will be substituted.
Also you can check returned value, as:
int errorcode = system("dir C:\* > "TMP_FILE_NAME);
printf("Command executed and returned a value %d\n", errorcode);
or taking into account command you use, change the logic of your program, e.g.:
int errorcode = system("dir C:\* > "TMP_FILE_NAME);
if( errorcode )
{
return errorcode;
}
UPDATE:
Alternatively, you could use pipes in C++, for example as shown in the answer to question How to execute a command and get output of command within C++ using POSIX?
you can do as #VolAnd said or also if you don't care about/don't want the output of the command to be in stdout and you also don't want anything else to be printed to stdout you can use freopen to set stdout to a file of your choice.

Why the FIFOs server cannot receive the data from client? use named-pipes

I just do a experiment of named-pipes in Ubuntu,but the server cannot receive the string which I input in the client,how can I solve it ? when I press Ctrl+C in the client,the sever can receive some characters.
Server
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<unistd.h>
#include<linux/stat.h>
#define FIFO_FILE "sampleFIFO"
int main()
{
FILE *fp;
char readbuf[80];
umask(0);
mknod(FIFO_FILE,S_IFIFO|0666,0);
while(1)
{
fp = fopen(FIFO_FILE,"r");
fgets(readbuf,80,fp);
printf("Received:%s\n",readbuf);
fclose(fp);
}
return(0);
}
Client
#include<stdio.h>
#include<stdlib.h>
#define FIFO_FILE "sampleFIFO"
int main(int argc,char *argv[])
{
FILE *fp;
char buf[80];
if((fp = fopen(FIFO_FILE,"w")) == NULL)
{
perror("error");
exit(1);
}
while(1)
{
memset(buf,0,sizeof(buf));
fgets(buf,80,stdin);
fputs(buf,fp);
}
fclose(fp);
return(0);
}
Your client code breaks the loop only when interrupted — you should test the return value from fgets() and use that to break the loop on EOF.
There's no guarantee with a FIFO as the output that fp is line buffered; you could add fflush(fp) after the fputs() call.
There's no need to use memset() as shown.
Since the client does not use its command line arguments, its main() should be int main(void).
Your primary problem is the fflush() one, I believe; the others are more nearly cosmetic.
As was noted by Joachim Pileborg, the server is not completely problem free.
The server code in the question, although inefficient, will serve an arbitrary number of clients. However, you really need nested loops. The outer loop repeatedly opens the FIFO; the inner reads the contents of the FIFO. When the inner loop reaches EOF, it is time to close the stream and reopen it. Again, you need to test the return value from fgets() to ensure that you actually read data. You should also consider how you make the server exit, and whether the server should remove the FIFO it creates.

How to find the value of kernel.shmmax from C code

I want to get the value of kernel.shmmax in C code (which I query on centos5.0, centos6.0 and ubuntu10.04 using the shell command "$ sysctl -q kernel.shmmax").
I used the following code to find it:
#include <sys/sysctl.h>
const int SHM_ERROR=1;
main(){
int name[] = {KERN_SHMMAX};
int namelen = 1;
int oldval[1];
size_t oldlen = sizeof(oldval);
int rv = sysctl(name, namelen, (void*) oldval, &oldlen, NULL, 0);
if (rv!=0) {
fprintf(stderr, "while quering for shared memory size, sysctl returned error: %s\n", strerror(errno));
return SHM_ERROR;
}
else{
return 0;
}
}
After running the code above I get the following error:
while quering for shared memory size, sysctl returned error: Not a directory
I am clueless about why I am getting this error. I googled for it and found there is some issue with the paths into which library tries to look into.
I tried running the above code with GDB but the code doesn't steps into the function sysctl, otherwise I could have provided you more information.
Data point:
I am easily able to set and get kernel.shmmax from command line on all the operating systems mentioned using the following commands:
$ sysctl -q kernel.shmmax
$ sysctl -w kernel.shmmax=1000000000
Thanks
You shouldn't be calling sysctl from userspace code. From the man page:
Glibc does not provide a wrapper for this system call; call it using
syscall(2).
Or rather... don't call it: use of this system call has long been
discouraged, and it is so unloved that it is likely to disappear in a
future kernel version. Remove it from your programs now; use the
/proc/sys interface instead.
So give this a shot instead:
#include <stdio.h>
#define SHMMAX_SYS_FILE "/proc/sys/kernel/shmmax"
int main(int argc, char **argv)
{
unsigned int shmmax;
FILE *f = fopen(SHMMAX_SYS_FILE, "r");
if (!f) {
fprintf(stderr, "Failed to open file: `%s'\n", SHMMAX_SYS_FILE);
return 1;
}
if (fscanf(f, "%u", &shmmax) != 1) {
fprintf(stderr, "Failed to read shmmax from file: `%s'\n", SHMMAX_SYS_FILE);
fclose(f);
return 1;
}
fclose(f);
printf("shmmax: %u\n", shmmax);
return 0;
}
I install strace and see that sysctl looks at /proc/sys/kernel/shmmax with open() call instead of _sysctl() call or syscall() call.

Resources