I'm trying to write a function that will kill instances by program name in string
unsigned int kill_all_program_instances(const char * program_name){
int res;
char buf[1024];
string first;
string second;
int lSize, pid , pos;
string command="pidof ";
FILE *fd;
memset(buf,'\0',sizeof(buf));
fd=popen((command+program_name).c_str(),"r");
unsigned int mypid = getpid();
if(fd != NULL){
fseek (fd , 0 , SEEK_END);
lSize = ftell(fd);
rewind (fd);
if (lSize <= 0)
{
printf("lsize is %d\n",lSize);
pclose(fd);
return 0;
}
.....
}
This is just the beginning of the function, but I always get -1 for lSize.
I ran
pidof chromium-browse
and got
26487 19353 16993 11504 10960 10880 10868 10829 10825 10805 8607 8263 8154 8089 7764 3965 3950
however when I run
kill_all_program_instances('chromium-browse')
I still get -1 for lSize.
Any idea whats wrong with my code?
Thanks
Aside from the comment/answer about detecting errors for popen (which doesn't seem correct), I do believe the actual problem is that you are trying to use fseek/ftell on a pipe, which is not a valid operation. A pipe is not a "file" in the conventional sense, it's a stream of data where each data item can only be read once.
Just read using fscanf() or something similar, until it gives you an EOF.
popen() communicates with the spawned process using pipes. pipes are not seekable.
You simply cannot use fseek/ftell on the FILE* returned by popen, they will always fail.
Related
I'm trying to establish an inter process communication on Linux using named pipes. At first glance my code seems to work, but I noticed that sometimes data written to the pipe by the "main" process is read twice by the "child" process (in fact it's two separate programs).
Program 1 (write only, starts first) is a legacy program. The below code is implemented in a onclick-function for a button on a GUI. When I press the button the data string shall be sent via pipe to another program. Code:
main.h
const char * FSCpipe = "/tmp/fscpipe";
int counter = 1;
main()
::mkfifo(FSCpipe, 0666);
OnClick-Function
QString data = "179.45";
int fd;
char msg[10];
fd = ::open(FSCpipe, O_WRONLY | O_NONBLOCK);
for(int i = 0; i < data.length(); i++) {
msg[i] = data.at(i).toLatin1();
}
msg[data.length()] = '\0';
::write(fd, msg, strlen(msg)+1);
::close(fd);
qDebug() << QString("Counter: %1").arg(counter);
counter++;
Program 2 (only read, starts second) is started in a new terminal. Code:
int main(int argc, char **argv)
{
int fd;
const char * FSCpipe = "/tmp/fscpipe";
char data[10];
size_t nbytes;
nbytes = sizeof(data);
while(1) {
fd = open(FSCpipe, O_RDONLY);
ssize_t bytesread = read(fd, data, nbytes);
printf("received: %s\n", data);
close(fd);
printf("Counter: %d ", counter);
printf("chars: %d\n", bytesread);
counter++;
}
return(0);
}
Sometimes I noticed a strange behaviour, feeling like there is more data read then written. So I implemented independent counter in both programs. When I press the button in program 1, the data is send via the pipe and the counter increments. When program 2 receives and outputs the data in the terminal, its counter is also incremented. After some clicks on the button in program 1, I can see a higher counter value in program 2, indicating that it reads more often then program 1 writes. Why is that ?
Apart from that, the data string should contain special characters encoded in UTF-8, like this:
QString data = "197,45 \xc2\xb5m";
How should I convert the string to send it correctly via pipe?
Thank you for helping me!
I found some helpful information here, stating:
"If all file descriptors referring to the write end of a pipe have been closed, then an attempt to read(2) from the pipe will see end-of-file (read(2) will return 0)"
I took out fd = ::open(...); and ::close(fd); from my onclick-function in program 1 and put them into the mainwindow-constructor and the mainwindow-close-function respectively. So the write end is always opened and program 2 works as intended.
Thank you all for your help.
According to Linux Programmer's Manual, poll can wait for one of a set of file descriptors to become ready to perform I/O.
According to my understanding, if I add POLLIN to events, poll will return with a > 0 integer, when there is at least one fd which is ready to be read.
Consider the following code, In this code, I want the program echos my input immediately after I typed the character \n.
int main(){
char buffer[maxn];
while (true) {
struct pollfd pfd[1];
std::memset(pfd, 0, sizeof pfd);
pfd[0].fd = STDIN_FILENO;
pfd[0].events = POLLIN;
int ret = poll(pfd, 1, 1000);
if (ret < 0) {
}
else if (ret == 0) {
}
else {
if ((pfd[0].revents & POLLIN) == POLLIN) {
int n;
n = fscanf(stdin, "%s", &buffer);
if(n > 0){
printf("data from stdin: %s\n", buffer);
}
}else if((pfd[1].revents & POLLHUP) == POLLHUP){
break;
}
}
}
}
When I type
aa bb cc dd
I thought fscanf hasn't retrieved all data from stdin, because it only reads aa. So when the loop restarts, stdin's fd should still be ready. As a consequence, (pfd[0].revents & POLLIN) == POLLIN still stands, so I thought we can see the following output
data from stdin: aa
data from stdin: bb
data from stdin: cc
data from stdin: dd
However, actually only the first line is printed. I got strange here, I think this is similar with epoll's Edge-triggered mode. However, poll is level-triggered.
So can you explain why this happens with fscanf?
Polling works at the file descriptor level while fscanf works at the higher file handle level.
At the higher level, the C runtime library is free to cache the input stream in such a way that it would affect what you can see at the lower level.
For example (and this is probably what's happening here), the first time you fscanf your word aa, the entire line is read from the file descriptor and cached, before that first word is handed back to you.
A subsequent fscanf (with no intervening poll) would first check the cache to get the next word and, if it weren't there, it would go back to the file descriptor to get more input.
Unfortunately, the fact that you're checking for a poll event before doing this is causing problems. As far as the file descriptor level goes, the entire line has been read by your first fscanf so no further input is available - poll will therefore wait until such information does become available.
You can see this in action if you change:
n = fscanf(stdin, "%s", buffer);
into:
n = read(STDIN_FILENO, buffer, 3);
and change the printf to:
printf("data from stdin: %*.*s\n", n, n, buffer);
In that case, you do get the output you expect as soon as you press the ENTER key:
data from stdin: aa
data from stdin: bb
data from stdin: cc
data from stdin: dd
Just keep in mind that sample code is reading up to three characters (like aa<space>) rather than a word. It's more to illustrate what the problem is rather than give you the solution (to match your question "Can you explain why this happens?").
The solution is not to mix descriptor and handle based I/O when the caching of the latter can affect the former.
I am trying to use the system calls read() and write(). The following program creates a file and writes some data into it. Here is the code..
int main()
{
int fd;
open("student",O_CREAT,(mode_t)0600);
fd=open("student",O_WRONLY);
char data[128]="Hi nikhil, How are u?";
write(fd,data,128);
}
Upon the execution of the above program i got a file with name student created with size as 128 bytes.
int main()
{
int fd=open("student",O_WRONLY);
char data[128];
read(fd,data,128);
cout<<(char*)data<<endl;
}
But the output i get is junk characters....why is this so?
I wrote a small read program to read data from the file. Her is the code.
But the output
Don't read from a file that you've open in O_WRONLY mode!
Do yourself a favor and always check the return values of IO functions.
You should also always close file descriptors you've (successfully) opened. Might not matter for trivial code like this, but if you get into the habit of forgetting that, you'll end up writing code that leaks file descriptors, and that's a bad thing.
You're not checking whether read() returns an error. You should do so, because that's probably the case with the code in your question.
Since you're opening the file write-only in the first place, calling read() on it will result in an error. You should open the file for reading instead:
char data[128];
int fd = open("student", O_RDONLY);
if (fd != -1) {
if (read(fd, data, sizeof(data)) != -1) {
// Process data...
}
close(fd);
}
Well, one of the first things is that your data is not 128 bytes. Your data is the string: "Hi nikhil, How are u?", which is way less than 128 bytes. But you're writing 128 bytes from the array to the file. Everything after the initial string will be random junk from memory as the char array is only initialized with 21 bytes of data. So the next 107 bytes is junk.
I'm running some commands with the C++ system() function:
int system ( const char * command );
How can I collect the standard output from the issued commands?
To be specific, I want to collect the output of the issued command (for example, the directory listing output from issuing the dir command).
Are you looking for returned value (as in "exit status") of the executed command, or for its output (as in "what did it print")?
If the latter, use popen() and pclose() instead.
If the former, look at the return value from system() (and use the documentation for waitpid() to interpret it).
system() returns an int, so just grab it: int rvalue = system(command);
I believe the exact details of what system() will return are system-specific, though.
There are typically two ways for a system program to "return" a value: by writing to stdout, and by returning a status integer at the end of the program. (there are often more ways to return results, eg. by writing to a file or into a database, but I assume those are out of scope here).
For receiving the status code, just check the return value of the system function.
For receiving the output, either redirect it into a file, and read the file afterwards, or use popen.
The return value of system is (ironically) system-dependent, but in POSIX systems (including Linux, etc), it's the same as for wait -- low 8 or 16 bits are the exit status of the child (probably what you mean by "value returned by"), higher bits indicating what kind of signal terminated the child, if any. The URL to the manpage I've given supplies the preprocessor macros you can use to pry apart that return value!
There is no such thing as a "return string" of a program, as you've now clarified in a comment is what you desire; as another answer already mentioned, if you want the text which gets output by the other program, you should use popen instead of system.
Inspired by bmorin's attempt, but working and tested, this snippet will take a char* command and return a char* containing the results of executing that command...
// Calling function must free the returned result.
char* exec(const char* command) {
FILE* fp;
char* line = NULL;
// Following initialization is equivalent to char* result = ""; and just
// initializes result to an empty string, only it works with
// -Werror=write-strings and is so much less clear.
char* result = (char*) calloc(1, 1);
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return NULL;
}
while(getline(&line, &len, fp) != -1) {
// +1 below to allow room for null terminator.
result = (char*) realloc(result, strlen(result) + strlen(line) + 1);
// +1 below so we copy the final null terminator.
strncpy(result + strlen(result), line, strlen(line) + 1);
free(line);
line = NULL;
}
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}
I looked into just editing bmorin's code, but would have had to change most lines, so a separate answer seemed more appropriate. Apologies if not. (Amongst other problems, bmorin's code didn't actually accumulate the lines; it printed them to stdout, where I presume they would not be wanted, since system() would have done that; and it returned void in one error path, when the function must return a char*, so the code wouldn't compile. Perhaps most egregious, it freed the result just before returning it.)
system() is declared and defined in libc. You can either read the first link I provided, or do man system at a command prompt in your shell.
I suggest the popen() functions, as said by other people as well,
but this problem is platform specific. the popen() function is
available on operating systems that use the POSIX API. I am not
sure if this command would work on other APIs like WIN32
Here is a code snippet (in plain C) executing a command with popen and returning its output:
char* exec(const char* command) {
FILE* fp;
char* result = NULL;
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout);
}
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}
I'm using the following code to try to read the results of a df command in Linux using popen.
#include <iostream> // file and std I/O functions
int main(int argc, char** argv) {
FILE* fp;
char * buffer;
long bufSize;
size_t ret_code;
fp = popen("df", "r");
if(fp == NULL) { // head off errors reading the results
std::cerr << "Could not execute command: df" << std::endl;
exit(1);
}
// get the size of the results
fseek(fp, 0, SEEK_END);
bufSize = ftell(fp);
rewind(fp);
// allocate the memory to contain the results
buffer = (char*)malloc( sizeof(char) * bufSize );
if(buffer == NULL) {
std::cerr << "Memory error." << std::endl;
exit(2);
}
// read the results into the buffer
ret_code = fread(buffer, 1, sizeof(buffer), fp);
if(ret_code != bufSize) {
std::cerr << "Error reading output." << std::endl;
exit(3);
}
// print the results
std::cout << buffer << std::endl;
// clean up
pclose(fp);
free(buffer);
return (EXIT_SUCCESS);
}
This code is giving me a "Memory error" with an exit status of '2', so I can see where it's failing, I just don't understand why.
I put this together from example code that I found on Ubuntu Forums and C++ Reference, so I'm not married to it. If anyone can suggest a better way to read the results of a system() call, I'm open to new ideas.
EDIT to the original: Okay, bufSize is coming up negative, and now I understand why. You can't randomly access a pipe, as I naively tried to do.
I can't be the first person to try to do this. Can someone give (or point me to) an example of how to read the results of a system() call into a variable in C++?
You're making this all too hard. popen(3) returns a regular old FILE * for a standard pipe file, which is to say, newline terminated records. You can read it with very high efficiency by using fgets(3) like so in C:
#include <stdio.h>
char bfr[BUFSIZ] ;
FILE * fp;
// ...
if((fp=popen("/bin/df", "r")) ==NULL) {
// error processing and return
}
// ...
while(fgets(bfr,BUFSIZ,fp) != NULL){
// process a line
}
In C++ it's even easier --
#include <cstdio>
#include <iostream>
#include <string>
FILE * fp ;
if((fp= popen("/bin/df","r")) == NULL) {
// error processing and exit
}
ifstream ins(fileno(fp)); // ifstream ctor using a file descriptor
string s;
while (! ins.eof()){
getline(ins,s);
// do something
}
There's some more error handling there, but that's the idea. The point is that you treat the FILE * from popen just like any FILE *, and read it line by line.
Why would std::malloc() fail?
The obvious reason is "because std::ftell() returned a negative signed number, which was then treated as a huge unsigned number".
According to the documentation, std::ftell() returns -1 on failure. One obvious reason it would fail is that you cannot seek in a pipe or FIFO.
There is no escape; you cannot know the length of the command output without reading it, and you can only read it once. You have to read it in chunks, either growing your buffer as needed or parsing on the fly.
But, of course, you can simply avoid the whole issue by directly using the system call df probably uses to get its information: statvfs().
(A note on terminology: "system call" in Unix and Linux generally refers to calling a kernel function from user-space code. Referring to it as "the results of a system() call" or "the results of a system(3) call" would be clearer, but it would probably be better to just say "capturing the output of a process.")
Anyway, you can read a process's output just like you can read any other file. Specifically:
You can start the process using pipe(), fork(), and exec(). This gives you a file descriptor, then you can use a loop to read() from the file descriptor into a buffer and close() the file descriptor once you're done. This is the lowest level option and gives you the most control.
You can start the process using popen(), as you're doing. This gives you a file stream. In a loop, you can read using from the stream into a temporary variable or buffer using fread(), fgets(), or fgetc(), as Zarawesome's answer demonstrates, then process that buffer or append it to a C++ string.
You can start the process using popen(), then use the nonstandard __gnu_cxx::stdio_filebuf to wrap that, then create an std::istream from the stdio_filebuf and treat it like any other C++ stream. This is the most C++-like approach. Here's part 1 and part 2 of an example of this approach.
I'm not sure you can fseek/ftell pipe streams like this.
Have you checked the value of bufSize ? One reason malloc be failing is for insanely sized buffers.
Thanks to everyone who took the time to answer. A co-worker pointed me to the ostringstream class. Here's some example code that does essentially what I was attempting to do in the original question.
#include <iostream> // cout
#include <sstream> // ostringstream
int main(int argc, char** argv) {
FILE* stream = popen( "df", "r" );
std::ostringstream output;
while( !feof( stream ) && !ferror( stream ))
{
char buf[128];
int bytesRead = fread( buf, 1, 128, stream );
output.write( buf, bytesRead );
}
std::string result = output.str();
std::cout << "<RESULT>" << std::endl << result << "</RESULT>" << std::endl;
return (0);
}
To answer the question in the update:
char buffer[1024];
char * line = NULL;
while ((line = fgets(buffer, sizeof buffer, fp)) != NULL) {
// parse one line of df's output here.
}
Would this be enough?
First thing to check is the value of bufSize - if that happens to be <= 0, chances are that malloc returns a NULL as you're trying to allocate a buffer of size 0 at that point.
Another workaround would be to ask malloc to provide you with a buffer of the size (bufSize + n) with n >= 1, which should work around this particular problem.
That aside, the code you posted is pure C, not C++, so including is overdoing it a little.
check your bufSize. ftell can return -1 on error, and this can lead to nonallocation by malloc with buffer having a NULL value.
The reason for the ftell to fail is, because of the popen. You cant search pipes.
Pipes are not random access. They're sequential, which means that once you read a byte, the pipe is not going to send it to you again. Which means, obviously, you can't rewind it.
If you just want to output the data back to the user, you can just do something like:
// your file opening code
while (!feof(fp))
{
char c = getc(fp);
std::cout << c;
}
This will pull bytes out of the df pipe, one by one, and pump them straight into the output.
Now if you want to access the df output as a whole, you can either pipe it into a file and read that file, or concatenate the output into a construct such as a C++ String.