天天看点

C语言和Shell交互

From:http://www.open-china.net/blog/96362.html

1、system(执行shell命令)

相关函数fork,execve,waitpid,popen

头文件:stdlib.h

函数原型:int system(const char * string);

函数说明:system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随机返回原调用的进程。在调用system()期间SIGCHLD信号会被暂时搁置,SIGNT和SIGQUIT信号则会被忽略。

返回值:如果system()在调用/bin/sh时失败则返回127,其他失败原因返回1。若参数string为空指针(NULL),则返回非零值。如果system()调用成功则最后会返回

执行shell命令后的返回值,但是此返回值也有可能为system()调用/bin/sh失败所返回的127,因此最好能再检查errno来确认执行成功。

    附加说明,在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量

可能会造成系统安全的问题。

范例:

#include <stdlib.h>

main()

{

    system("ls -al /etc/passwd /etc/shadow");

}

From:http://www.cplusplus.com/reference/clibrary/cstdlib/system/

system

int system(const char * command);

Execute system command

    Invokes the command processor to execute a command.Once the command execution has terminated, the processor gives the control back to the program, returning an int value, whose interpretation is system-dependent.

The function call also be used with NULL as argument to check whether a command processor exists.

Parameters

command

    C string containing the system command to be executed.

Return Value

    The value returned when the argument passed is not NULL, depends on the running environment specifications. In many systems, 0 is used to indicate that the command was successfully executed and other values to indicate some sort of error.

    When the argument passed is NULL, the function returns a nonzero value if the command processor is available, and zero otherwise.

Portability

    The behavior and return value are platform-dependent.

Example

/* system example : DIR */

#include <stdio.h>

int main()

    int i;

    printf("Checking if processor is available...");

    if(system(NULL)) puts("OK");

    else exit(1);

    printf("Executing command DIR...\n");

    i = system("dir");

    printf("The value returned was: %d.\n", i);

    return 0;

2、popen(建立管道I/O)

相关函数:pipe,mkfifo,pclose,fork,system,fopen

头文件:stdio.h

函数原型:FILE * popen(const char * command, const char * type);

函数说明popen()会调用fork()产生子进程,然后从子进程调用/bin/sh -c来执行参数command的命令。参数type可使用"r"代表读取,"w"代表写入。依照此type值,popen()会建立管道连到子程序的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使用文件指针(FILE*)操作的函数也都可以使用,

除了fclose()以外。

返回值:若成功则返回文件指针,否则返回NULL,错误原因存于errno中。错误代码:EINVAL参数type不合法。

注意事项:在编写具有SUID/SGID权限的程序时请尽量避免使用popen(),popen()会继承环境变量,通过环境变量可能会造成系统安全的问题。

    FILE * fp;

    char buffer[80];

    fp = popen("cat /etc/passwd", "r");

    fgets(buffer, sizeof(buffer), fp);

    printf("%s", buffer);

    pclose(fp);

执行 root:x:0 0: root:/root: /bin/bash

From:http://linux.about.com/library/cmd/blcmdl3_popen.htm

Linux/Unix Command: popen

Command Library

NAME

popen, pclose - process I/O

SYNOPSIS

FILE * popen(const char * command, const char * type);

int pclose(FILE * stream);

DESCRIPTION

    The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.

    The command argument is a pointer to a null-terminated string containing a shell command line. This command is passed to /bin/sh using the -c flag; interpretation, if any, is performed by the shell.The mode argument is a pointer to a null-terminated string which must be either 'r' for reading or 'w' for writing.

    The return value from the popen() is a normal standard I/O stream in all respects save that it must be closed with pclose() rather than fclose(). Writing to such a stream writes to the standard input of the command; the command's standard output is the same as that of the process that called popen(), unless this is altered by the command itself. Conversely, reading from a "popened" stream reads the command's standard output, and the command's standard input is the same as that of the process that called popen.

    Note that output popen streams are fully buffered by default.

    The pclose function waits for the associated process to terminate and returns the exit status of the command as returned by wait4.

RETURN VALUE

    The popen function returns NULL if the fork(2) or pipe(2) call fail, or if it cannot allocate memory.

    The pclose function returns -1 if wait4 returns an error, or some other error is detected.

ERRORS

    The popen function does not set errno if memory allocation fails. If the underlying fork() or pipe() fails, errno is set appropriately. If the mode argument is invalid, and this condition is detected, errno is set to EINVAL.

    if pclose() cannot obtain the child status, errno is set to ECHILD.

3、使用vfork()新建子进程,然后调用exec函数族

#include <unistd.h>

    char * argv[] = {"ls", "-al", "etc/passwd", (char*)};

    if(vfork() == 0)

    {

        execv("/bin/ls", argv);

    }

    else

        printf("This is the parent proces");

个人感觉第二种方式最好了。

int main(void)

  FILE * file = popen("ls", "r");

  int i;

  for(i=0; ;++i)

  {

    char buffer[1024+4];

    fgets(buffer, 1024, file);

    if(feof(file)) break;

  }

  printf("%d\n", i);

  pclose(file);

  return 0;

其实,最简单的方式是使用stdin和stdout。

main.c

  char buffer[1024];

  scanf("%s", buffer);

  printf("Hello, %s!", buffer);

gcc main.c -o hello

echo Jim | ./hello | wc -l

结果是:1

system、popen、stdin/stdout是异步,但是表现出同步的性质。

popen、stdin/out使用流技术,将异步的高校和同步的易用结合在了一起。

继续阅读