区分execl与system——应用程序中执行命令
相关函数:fork, execle, execlp, execv, execve, execvp
表头文件:#include <unistd.h>
函数定义:int execl(const char *path, const char *arg, ...);
函数说明:execl()用来执行参数path字符串所代表的文件路径, 接下来的参数代表执行该文件时传递的argv[0],argv[1].....是后一个参数必须用空指针NULL作结束
返回值 :成功则不返回值, 失败返回-1, 失败原因存于errno中
错误代码:参execve()
范例:
/* 执行 /bin/ls -al /ect/passwd */
#include <unistd.h>
main()
{
execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *) 0);
}
int main()
{
char args[]=" -l";
execl("/bin/ls","ls","-al","/etc/",NULL);
return 0;
}
cc execl.c -o execl
[cnscn@test c]$ ./execl
-rw-r--r-- 1 root root 2218 Jan 13 11:36 /etc/passwd
system:
相关函数
fork,execve,waitpid,popen
表头文件
#i nclude<stdlib.h>
定义函数
int system(const char * string);
函数说明
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
返回值
=-1:出现错误
=0:调用成功但是没有出现子进程
>0:成功退出的子进程的id
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值>。 如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
附加说明
在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。
范例
#i nclude<stdlib.h>
main()
{
system(“ls -al /etc/passwd /etc/shadow”);
}
执行结果:
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
-r--------- 1 root root 572 Sep 2 15 :34 /etc/shado
例2:
char tmp[];
sprintf(tmp,"/bin/mount -t vfat %s /mnt/usb",dev);
system(tmp);
其中dev是/dev/sda1。
system源码
#include
#include
#include
#include
int system(const char * cmdstring)
{
pid_t pid;
int status;
if(cmdstring == NULL){
return (1);
}
if((pid = fork())<0){
status = -1;
}
else if(pid == 0){
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
-exit(127); //子进程正常执行则不会执行此语句
}
else{
while(waitpid(pid, &status, 0) < 0){
if(errno != EINTER){
status = -1;
break;
}
}
}
return status;
}
先分析一下原理,然后再看上面的代码大家估计就能看懂了:
当system接受的命令为NULL时直接返回,否则fork出一个子进程,因为fork在两个进程:父进程和子进程中都返回,这里要检查返回的pid,fork在子进程中返回0,在父进程中返回子进程的pid,父进程使用waitpid等待子进程结束,子进程则是调用execl来启动一个程序代替自己,execl("/bin/sh", "sh", "-c", cmdstring,(char*)0)是调用shell,这个shell的路径是/bin/sh,后面的字符串都是参数,然后子进程就变成了一个shell进程,这个shell的参数是cmdstring,就是system接受的参数。在windows中的shell是command,想必大家很熟悉shell接受命令之后做的事了。
如果上面的你没有看懂,那我再解释下fork的原理:当一个进程A调用fork时,系统内核创建一个新的进程B,并将A的内存映像复制到B的进程空间中,因为A和B是一样的,那么他们怎么知道自己是父进程还是子进程呢,看fork的返回值就知道,上面也说了fork在子进程中返回0,在父进程中返回子进程的pid。
execl是编译器的函数(在一定程度上隐藏具体系统实现),在linux中它会接着产生一个linux系统的调用execve, 原型见下:
int execve(const char * file,const char **argv,const char **envp);
看到这里你就会明白为什么system()会接受父进程的环境变量,但是用system改变环境变量后,system一返回主函数还是没变,原因从system的实现可以看到,它是通过产生新进程实现的,从我的分析中可以看到父进程和子进程间没有进程通信,子进程自然改变不了父进程的环境变量。
区分execl与system——应用程序中执行命令相关推荐
- C语言system函数(C语言程序中执行命令行)
需包含头文件:C 标准库 - <stdlib.h> 文章目录 描述 声明 参数 返回值 实例1 实例2:列出 windows 机上当前目录下所有的文件和目录 描述 C 库函数 int sy ...
- 命令逐行显示_在LoadRunner中执行命令行程序之:popen()取代system()
>>>推荐阅读<<< 1.性能测试学习笔记-场景设计 2.性能测试的重要意义 3.性能分析流程及方法 4.应用系统性能调优之性能分析 在LoadRunner中执行命 ...
- gettext 国际化_如何使用Gettext在Phoenix应用程序中执行本地化
gettext 国际化 by Anastasia 由Anastasia 如何使用Gettext在Phoenix应用程序中执行本地化 (How to perform localization in Ph ...
- angular发布代码有缓存_如何在Angular应用程序中执行请求?
全文共5358字,预计学习时长16分钟 来源:Pexels 本文将讨论如何在Angular应用程序中执行请求. 1. 使用拦截器来装饰请求 2. HttpClient 与HttpBackend的对比 ...
- 程序中调用命令行命令,不显示那个黑黑的DOS窗口
From: http://hi.baidu.com/yanqiuge/item/5da466c3d3f18453ad00ef1d 在程序中使用命令行时,会有黑黑的DOS窗口,很不爽,在网上查了一下,写 ...
- 什么鬼?我能通过依赖混淆攻击在 Halo 游戏服务器中执行命令,微软不 care?!...
聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士 研究员可以利用依赖混淆攻击在 Halo Microsoft 服务器中执行命令,但微软安全响应中心 (MSRC) 表示并非问题. 神秘依赖关 ...
- shell脚本中执行命令_如何在Shell脚本中执行命令?
shell脚本中执行命令 Shell is a command-line interpreter that allows the user to interact with the system. I ...
- 在c++程序中执行DOS命令
转自博客:http://blog.csdn.net/ypist/article/details/8485049 #1,system()方式 在C盘根目录下新建文件夹,名称为12: system(&qu ...
- 在Web应用程序中执行常见搜索场景的服务器端方法
目录 介绍 例子 添加搜索模型 修改Home控制器 修改Home视图 介绍 应用程序中需要的一个常见场景是针对某个搜索值搜索数据模型.由于http协议的性质(无状态): 搜索结果的提交将再次呈现页面. ...
最新文章
- 由谈退格键的实现来学习字符编码
- DeepLearning based on PaddlePaddle系列一
- Git push大文件失败的处理
- 为什么前端工程师的工作很难找?
- 中职计算机基础课教学策略研究,计算机-研究教学方法中职学校计算机基础课程教学策略的论文开题报告-优度********网...
- pyqt5多进程 python_Python 多进程大全
- CRI 与 ShimV2:一种 Kubernetes 集成容器运行时的新思路
- Introduction to Conditional Random Fields
- HTML做一个个人博客页面(纯html代码)
- UVa Problem 10247 Complete Tree Labeling (完全树标号)
- matlab示波器有毛刺,在使用示波器时如何消除毛刺?
- Java 计算两个日期时间差(天数、时、分、秒、毫秒)
- 红外对管信号处理电路(滞回比较器)
- 嵌入式linux内核移植
- OSF Jonathan Bryce:Open Infrastructure开启开放协作新时代
- 用session和mysql实现购物车_Session和Cookie实现购物车
- 解决Unable to find the module utility `modprobe`错误
- “唯一艺术数字藏品“小程序被下架,数字藏品服务边界在哪
- hihoCoder #1135 : Magic Box
- 重庆移动4G资费出炉 600M流量售50元
热门文章
- 小白必学教程Python编码
- MySQL 5.7.12新增MySQL Shell命令行功能
- 第四章——SQLServer2008-2012资源及性能监控(1)
- Android学习之适配器SimpleCursorAdapter
- SSAS实践问题记录--OLAP 存储引擎中存在错误: 处理时找到重复的属性键
- C盘的“压缩驱动器以节约磁盘空间”有用吗
- JavaSE Collections类 , Iterator迭代器 , 增强for循环
- cf1042d 树状数组逆序对+离散化
- SQL http://www.myfeng.cn/?T3009
- ComBox、listBox、checklistBox控件