LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
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 08-09-2007, 02:19 PM   #1
ilnli
Member
 
Registered: Jul 2004
Location: Pakistan
Distribution: Slackware 10.0, SUSE 9.1, RH 7, 7.3, 8, 9, FC2
Posts: 413

Rep: Reputation: 32
system() output


I need to execute a shell program in C but I also need to see what was the output of that program so how is it possible in C with sytem() or other function call?

regards,
Imran
 
Old 08-09-2007, 02:26 PM   #2
User Name.
Member
 
Registered: Aug 2006
Distribution: Ubuntu 8.04
Posts: 178

Rep: Reputation: 30
hello.sh:
Code:
#!/bin/sh

echo "hello world!"
hello.c:
Code:
#include <stdlib.h>

main()
{
        system("./hello.sh");
}
You need to chmod a+x hello.sh, then compile and execute hello.c, and then voilla!
 
Old 08-09-2007, 03:20 PM   #3
ilnli
Member
 
Registered: Jul 2004
Location: Pakistan
Distribution: Slackware 10.0, SUSE 9.1, RH 7, 7.3, 8, 9, FC2
Posts: 413

Original Poster
Rep: Reputation: 32
I want to save the output in a string then I need to analyze/parse that string, will it be possible?
 
Old 08-09-2007, 04:17 PM   #4
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
You can use popen and fgets to get the command output as a string.
 
Old 08-09-2007, 04:43 PM   #5
ilnli
Member
 
Registered: Jul 2004
Location: Pakistan
Distribution: Slackware 10.0, SUSE 9.1, RH 7, 7.3, 8, 9, FC2
Posts: 413

Original Poster
Rep: Reputation: 32
I'll be grateful to you guy if you can please give show me an example for that
 
Old 08-09-2007, 05:13 PM   #6
95se
Member
 
Registered: Apr 2002
Location: Windsor, ON, CA
Distribution: Ubuntu
Posts: 740

Rep: Reputation: 32
You can create a pipe, fork the program, then use dup2 in the child process to duplicate the write end to take the place of standard output (1), then call one of the exec* functions. The parent process can read from the read end of the pipe to get the output of the program. Here is an example, this calls a no argument command and converts the output to upper case.

Code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>

#define BUF_SIZE 256

int main(int argc, char *argv[]) {
	char * cmd;
	char buf[BUF_SIZE+1];
	int pipe_fd[2];
	int pid;
	FILE * in;
	int i;

	if (argc < 2) {
		printf("Usage: %s command\n", argv[0]);
		return 0;
	}

	cmd = argv[1];
	
	/* create a pipe */

	if (pipe(pipe_fd) != 0) {
		perror("pipe failed");
		return -1;
	}

	pid = fork();

	if (pid == 0) {
		/* child process */

		close(pipe_fd[0]);		/* no need to keep the read end
						   around */
		
		/* replace standard output */

		if (dup2(pipe_fd[1], 1) < 0) {
			perror("dup2 failed");
			close(pipe_fd[1]);
			return -1;
		}

		close(pipe_fd[1]);		/* no need for the original 
						   write end */

		if (execlp(cmd, cmd, NULL) == -1) {
			perror("execl failed");
		}

		close(1);
		return -1; 			/* only called if execl failed*/
	}

	/* server process */
	
	close(pipe_fd[1]); 			/* so the read end closes when 
					   	   the child process exits */

	in = fdopen(pipe_fd[0], "r");
	if (in == NULL) {
		fprintf(stderr, "Failed to open FILE from file descriptor\n");
		return -1;
	}


	while (fgets(buf, BUF_SIZE, in) != NULL) {
		for (i = 0; i < strlen(buf); i++) {
			buf[i] = toupper(buf[i]);
		}

		printf("%s", buf);
	}

	return 0;
}

Last edited by 95se; 08-12-2007 at 03:38 PM.
 
Old 08-10-2007, 07:09 AM   #7
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by ilnli
I'll be grateful to you guy if you can please give show me an example for that
Here's another example. It uses popen(), which is easier to use than a pipe(), dup(), fork() combination.

It scrolls a man page slowly in a terminal:
Code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MAXLINELEN 100
#define MAXCOMMAND 100
#define DISCARDSTDERR " 2>/dev/null"

int main(int argc, char *argv[])
{
    char line[MAXLINELEN + 1];
    char command[MAXCOMMAND + 1];
    FILE *pipe;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <name of man page>\n", argv[0]);
        return 1;
    }
    /* First construct a command line, (e.g. "man ls 2>/dev/null") with
     * safety checks for string length.
     */
    strncpy(command, "man", MAXCOMMAND);
    command[MAXCOMMAND] = '\0';
    if (strlen(command) + strlen(argv[1]) + strlen(DISCARDSTDERR) > MAXCOMMAND) {
        fprintf(stderr, "Error: Command would be too long (max = %d).\n", MAXCOMMAND);
        return 1;
    }
    strcat(command, " ");
    strcat(command, argv[1]);
    strcat(command, DISCARDSTDERR);  /* discard stderr: 2>/dev/null */

    /* Execute the command, setting up a pipe for getting its output. */
    pipe = popen(command, "r");
    if ((pipe = popen(command, "r")) == NULL) {
        perror("");
        return 1;
    }

    /* Read the doc from the pipe line-by-line, with a short delay */
    while (fgets(line, MAXLINELEN + 1, pipe) != NULL) {
        printf("%s", line);  /* fixed thx jlliagre */
        usleep(200000);
    }
    pclose(pipe);
    return 0;
}

Last edited by Hko; 08-11-2007 at 08:26 AM.
 
Old 08-10-2007, 08:53 AM   #8
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Although it shows a good example about how to use popen, beware that this last code is also a good example of what must not be done in term of security.

The issue is it doesn't check against malicious parameters. Should you expose this script to a hostile user, it can wipe out your files, install backdoors, etc ...
 
Old 08-11-2007, 08:21 AM   #9
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by jlliagre
Although it shows a good example about how to use popen, beware that this last code is also a good example of what must not be done in term of security.

The issue is it doesn't check against malicious parameters. Should you expose this script to a hostile user, it can wipe out your files, install backdoors, etc ...
Ah, yes. That is true. This line is really wrong:
Code:
printf(line);
It should have been (of course):
Code:
printf("%s", line);
Thanks for pointing at that.
Fixed in the my previous post.

Last edited by Hko; 08-11-2007 at 08:25 AM.
 
Old 08-11-2007, 11:18 AM   #10
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
You spotted that bug but there is another one which is larger and easier to abuse ...

Look closer !
 
Old 08-12-2007, 02:53 PM   #11
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by jlliagre View Post
You spotted that bug but there is another one which is larger and easier to abuse ...

Look closer !
Hmm, I'm not so sure about that.
Though arguably not in the most beautiful way, the program does check correctly if the argument will overflow the buffer.

Are you still sure? If so, please tell me where it is. Thx

Last edited by Hko; 08-12-2007 at 02:54 PM.
 
Old 08-12-2007, 03:11 PM   #12
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Okay. The weakness is simpler than a stack overflow.

Pass this argument including the quotes to your program: "ls;cp /etc/hosts /tmp" and have a look at /tmp ...
 
Old 08-12-2007, 03:26 PM   #13
95se
Member
 
Registered: Apr 2002
Location: Windsor, ON, CA
Distribution: Ubuntu
Posts: 740

Rep: Reputation: 32
Well, this is kind of silly, since it is just an example to help the OP, but you didn't include the + 1 in your bounds check for the space. You also should only have MAXLINELEN for the argument to fgets, not MAXLINELEN + 1. Assuming the command runs as the user who called it, then I can't see any other issues with it.

Edit: That said, I didn't check the return value of the fdopen in my example. But we're not trying to demonstrate security and best practices here :P

Last edited by 95se; 08-12-2007 at 03:44 PM.
 
Old 08-12-2007, 03:30 PM   #14
95se
Member
 
Registered: Apr 2002
Location: Windsor, ON, CA
Distribution: Ubuntu
Posts: 740

Rep: Reputation: 32
Quote:
Originally Posted by jlliagre View Post
Okay. The weakness is simpler than a stack overflow.

Pass this argument including the quotes to your program: "ls;cp /etc/hosts /tmp" and have a look at /tmp ...
If this program has normal permissions, then this isn't an issue. The user could do that anyway. Tricking the program to do it instead is just a more complicated way of doing it.
 
Old 08-12-2007, 03:30 PM   #15
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by jlliagre View Post
Okay. The weakness is simpler than a stack overflow.

Pass this argument including the quotes to your program: "ls;cp /etc/hosts /tmp" and have a look at /tmp ...
Yes, that does look ugly I must admit.
But, to my defense, there is no security danger in this (I think), since the user doing this "trick" with my program could as well do "cp /etc/hosts /tmp" without my program.

Correct?
 
  


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
Output system errors and wornings ? kmokrzcyki Linux - Software 1 06-22-2007 01:28 PM
PHP function system() - format the output fatrandy13 Programming 5 09-20-2006 08:53 AM
in C, Assigning output of system() to a variable Miaire Programming 4 01-30-2005 12:40 PM
standard output/system mail? gmon72 Linux - Newbie 2 10-13-2004 03:54 PM
standard output/system mail? gmon72 Linux - Newbie 1 10-13-2004 02:11 PM

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

All times are GMT -5. The time now is 05:25 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