system函数能够执行函数参数中的命令。函数的定义如下:
#include <stdlib.h> int system(const char* cmdstring);
当cmdstring为NULL:
如果shell可用则返回非0值,否则返回0.
因为system函数在其实现中调用了fork,exec和waitopid,分解开来相当于执行了:system函数有三种返回值:
1.如果fork失败或者waitpid返回出EINTR(EINTR为中断返回的错误类型)之外的错误,则system返回-1,而且errno中设
置了错误类型值。
2.如果exec失败(表示不能执行shell),则其返回值如同shell执行了exit(127)一样。
3.否则所有三个函数都执行成功,并且system的返回值是shell的终止状态,其格式已在waitpid中说明。
下面的程序调用system函数,并对返回值进行分析:
#include <stdio.h> #include <sys/wait.h> #include <stdlib.h> void pr_exit(int status){ printf("status = %d\n", status); if(WIFEXITED(status)){ printf("normal terminaton, exit status = %d\n", WEXITSTATUS(status)); }else if(WIFSIGNALED(status)){ printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status), #ifdef WCOREDUMP WCOREDUMP(status)?"(core file generated)" : ""); #else ""); #endif }else if(WIFSTOPPED(status)){ printf("child stopped, signal number = %d\n", WSTOPSIG(status)); } } int main(int argc, char* argv[]){ if(argc != 2){ printf("usage:./a.out [cmdstring]\n"); return -1; } int status; status = system(argv[1]); pr_exit(status); return 0; }执行上面的程序:
yan@yan-vm:~/apue$ ./a.out nosuchcmd
sh: 1: nosuchcmd: not found
status = 32512
normal terminaton, exit status = 127
nosuchcmd不是shell支持的命令,所以,shell命令返回了127(exec失败),对于system函数,返回值为127*256 = 32512;
因为shell的返回值是 system返回值的8~15位(所以在程序中返回超过255的错误代码是无意义的)。
yan@yan-vm:~/apue$ ./a.out "ls /a/b/c"
ls: cannot access /a/b/c: No such file or directory
status = 512
normal terminaton, exit status = 2
虽然没有这个/a/b/c目录,但是命令是成功执行了,所以没有返回127,而是返回了ls /a/b/c命令的错误代码2(2*256 = 512)。
yan@yan-vm:~/apue$ ./a.out "date"
Sat Jul 27 20:48:22 CST 2013
status = 0
normal terminaton, exit status = 0
system成功执行了date,date程序退出码为0。
使用system函数执行命令行参数(a.out):
#include <stdio.h> int main(int argc, char* argv[]){ if(argc < 2){ printf("usage:./a.out [cmdstring]\n"); return -1; } if(system(argv[1])<0){ perror("system\n"); return -1; } return 0; }打印程序的uid和euid(getuid):
#include <stdio.h> int main(void){ printf("real uid =%d, effective uid=%d.\n",getuid(),geteuid()); return 0; }执行结果:
yan@yan-vm:~/apue$ ./a.out /home/yan/apue/getuid
real uid =1000, effective uid=1000. //使用普通用户打印的uid和euid是正常的。
yan@yan-vm:~/apue$ su
Password:
root@yan-vm:/home/yan/apue# chown root a.out //将程序的所有者改为root
root@yan-vm:/home/yan/apue# chmod u+s a.out //设置程序的setuid标志
root@yan-vm:/home/yan/apue# ll a.out
-rwsrwxr-x 1 root yan 7443 Jul 27 22:54 a.out* //确认成功设置
root@yan-vm:/home/yan/apue# exit //退出root用户
exit
yan@yan-vm:~/apue$ ./a.out /home/yan/apue/getuid
real uid =1000, effective uid=0. //euid变成了root
我们给予a.out超级用户权限在system中执行了fork和exec后仍然保持了下来。
如果一个进程正以特殊的权限(setuid或setgid)运行,它又想生成一个程序,则它应该直接使用fork和exec,而且fork以后,exec之前
要改回到普通权限,setuid或setgid的程序决不应调用system函数。