LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-10-2010, 06:10 AM   #1
HarryBoy
Member
 
Registered: Apr 2008
Distribution: MontaVista Linux Version 4.0.1, Professional Edition
Posts: 215

Rep: Reputation: 16
Working with the 'system' call


I have the following code:

Code:
#include <stdio.h>
#include <stdlib.h>

int main()
{
    system("ps -ef | grep myprocessname");

    return 0;
}
When I run this program it outputs the following list of running processes:
Code:
root     10279 10275  0 13:02 ?        00:00:00 myprocessname myvar1=value1 myvar2=value2
root     10341 10337  1 13:02 ?        00:00:00 myprocessname myvar1=value1 myvar2=value2
blah..
blah..
What I want to really do is instead of writing the output to screen I want to read the output and parse the various values value1, value2 etc.

What is the best way to do this?
 
Old 12-10-2010, 08:37 AM   #2
HarryBoy
Member
 
Registered: Apr 2008
Distribution: MontaVista Linux Version 4.0.1, Professional Edition
Posts: 215

Original Poster
Rep: Reputation: 16
When I run the following:
Quote:
int data_processed = 0;
int file_pipes[2];
char buffer[BUFSIZ -1];
pid_t child;
memset(buffer, '\0', sizeof(buffer));

if(pipe(file_pipes) == 0)
{
child = fork();
if(child < 0)
{
printf("Failed to fork child process\n");
return 1;
}
else if(child == 0)
{
printf("Child process forked\n");
(void)execl("/bin/ps", "ps -ef | grep myProgram ", (char *)0);
return 1;
}
else
{
printf("Parent process\n");
data_processed = read(1, buffer, BUFSIZ);
printf("%d bytes read: %s\n",data_processed, buffer);
}

}
I get:
Quote:
root@MyLinuxMachine myFiles ./myProgram
Parent process
Child process forked
PID TTY TIME CMD
3637 ttyp0 00:00:00 bash
11003 ttyp0 00:00:00 myProgram
11004 ttyp0 00:00:00 ps

1 bytes read:
What am I doing wrong here? I want to read from the stdout of the ps program.

thanks

Last edited by HarryBoy; 12-10-2010 at 09:40 AM.
 
Old 12-10-2010, 09:30 AM   #3
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Hi.
I'd suggest to use `popen()' instead of `system()', e.g.
Code:
#include <stdio.h>

int main()
{
	FILE *data = popen("ps -Af | grep udev","r");
	char c;
	while( (c=fgetc(data)) !=EOF )
		putchar(c);

	pclose(data);
	return 0;
}
You can read and parse the `data' stream as you wish. For example:
Code:
#include <stdio.h>
#include <string.h>

#define BUFLEN 500

void parse(char * line)
{
	char *p1, *p2, *e;
begin:
	e = index(line, '=');
	if(e) { p2=e+1; *e='\0'; }
	else return;
	
	p1 = rindex(line, ' ');
	if(!p1) p1=line;
	else p1++;

	e=p2;
	while(!(strchr(" \t\n\0", *e))) e++;
	if(*e != '\0') { line = e+1; *e='\0'; }

	printf("var: [%s]\nval: [%s]\n", p1, p2);

	goto begin;
}
int main()
{
	FILE *data = popen("ps -Af | grep =","r");
	char buf[BUFLEN]; 

	while(! feof(data) )
	{
		fgets(buf, BUFLEN, data);
		puts(buf);
		parse(buf);
	}
	pclose(data);
	return 0;
}

Last edited by firstfire; 12-10-2010 at 09:33 AM.
 
Old 12-10-2010, 09:46 AM   #4
HarryBoy
Member
 
Registered: Apr 2008
Distribution: MontaVista Linux Version 4.0.1, Professional Edition
Posts: 215

Original Poster
Rep: Reputation: 16
Hi firstfire, thanks for your reply. I have to use the system due to my project.
Your parse function will come in useful thanks.
I have got the following working:

Code:
 int data_processed = 0;
    int pipes[2];

    char buffer[BUFSIZ -1];
    pid_t child;
    memset(buffer, '\0', sizeof(buffer));

    if(pipe(pipes) == 0)
    {
        child = fork();

        if(child < 0)
        {
            printf("Failed to fork child process\n");
            return 1;
        }
        else if (child == 0)//Child process
        {
            dup2( pipes[1], STDOUT_FILENO );    
            close( pipes[0] );
            execl( "/bin/ls", "ls",(char *)0);  
        }
        else
        {
            dup2( pipes[0], STDIN_FILENO );
            close( pipes[1] );
            data_processed = read(pipes[0], buffer, BUFSIZ);
            printf("%d bytes read: %s\n",data_processed, buffer);

        }

    }
Not that this using the 'ls' command. I used this jsut to get it working. My Parent now prints out the ls output.
I cannot for the life of me get the ps -ef command working.
I have used the following:
Quote:
execl("/bin/ps", "ps -ef | grep myprocess", (char *)0);
execl("/bin/ps -ef","ps", (char *)0);
execl("/bin/ps -ef | grep myprocess","ps", (char *)0);
execl("/bin/ps", "ps", buffer, (char *)0);
But none gives me what I expect.

Do you know what I'm doing wrong?

Thanks
 
Old 12-10-2010, 05:03 PM   #5
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Hi.
Try this:
Code:
execl( "/bin/ps", "ps", "-ef",(char *)0);
You should supply execl() with a path to the program binary and a list of arguments to that program. Inside of `ps' this list is accessed via `char **argv'.
Here is an excerpt from `man exec':
Code:
       int execl(const char *path, const char *arg, ...);
                . . . . . . . . . . . . . . . . . .
       The  initial  argument for these functions is the pathname of a file
       which is to be executed.

       The const char *arg and subsequent ellipses  in  the  execl(),  exe‐
       clp(),  and execle() functions can be thought of as arg0, arg1, ...,
       argn.  Together they describe a list of  one  or  more  pointers  to
       null-terminated  strings  that represent the argument list available
       to the executed program.  The first argument, by convention,  should
       point  to the filename associated with the file being executed.  The
       list of arguments must be terminated by a NULL pointer,  and,  since
       these  are  variadic  functions,  this pointer must be cast (char *)
       NULL.
Note that you can not just "pipe" the data from ps to grep using exec because this involves running two processes and establishing a data channel between them, while exec is a low-level function only able to "run" one process. That's why
Code:
execl("/bin/ps", "ps -ef | grep myprocess", (char *)0);
execl("/bin/ps -ef | grep myprocess","ps", (char *)0);
did not work.

On the other hand `system(char *command)' and `popen()' are higher-level functions which pass given command to the shell, where actual processing is done (including redirections):
Code:
system("command") is equivalent to /bin/sh -c "command"

Last edited by firstfire; 12-10-2010 at 05:28 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
calling a system call inside a system call suresh.j Linux - Kernel 1 08-03-2010 09:28 PM
System call not working anil007523 Linux - Kernel 1 07-24-2010 08:09 AM
How to call system call from usb driver's code Mr.J Linux - Kernel 4 09-29-2008 03:47 AM
How can i make centos 4.5's system call using vDSO(call *%gs:0x10) instead of int80 tclwp Red Hat 3 08-06-2007 12:07 AM
new system call not working.... mmars Programming 2 10-23-2003 05:41 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:26 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration