通过获取IP和网关的代码来学习popen().str*系列等函数的使用
/*********************************************************************************
* Copyright: (C) 2017 LingYun Lab.
* All rights reserved.
*
* Filename: ifcfg.c
* Description: This file
*
* Version: 1.0.0(05/16/2017)
* Author: lingyun <lingyun@email.com>
* ChangeLog: 1, Release initial version on "05/16/2017 06:59:54 PM"
*
********************************************************************************/
#include <string.h>
#include <stdio.h>
#include <errno.h>
#define DEBUG
#define IPADDR_LEN 16//定义这个宏的长度为16
#define NIC "eth0"//定义NIC为“eth0”
int get_nic_ipaddr(char *nic, char *ipaddr, char *netmask);//声明函数
int main (int argc, char **argv)
{
char ipaddr[IPADDR_LEN];
char netmask[IPADDR_LEN];
if( get_nic_ipaddr(NIC, ipaddr, netmask) < 0 )//如果函数的返回值小于0,就表示获取失败
{
printf("get IP address for network card %s failure\n", NIC);
return -1;
}
printf("Network card [%s] IPaddr: <%s> Netmask: <%s>\n", NIC, ipaddr, netmask);//打印ip和netmask信息
return 0;
} /* ----- End of main() ----- */
/* Description: This function used to get NIC $nic IP address and netmask
* Input args: nic: get which Network interface card ipaddress or netmask
* Output args: ipaddr: the NIC IP address netmask: the NIC netmask
* Return Value: 0: Success <0: Failure
*/
int get_nic_ipaddr(char *nic, char *ipaddr, char *netmask)
{
FILE *fp;
char command[32];
char buf[256];
char *p1;
char *p2;
int rv = -1;
#ifdef DEBUG
printf("time: %s %s %s %d %s()\n", __DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__ );
#endif
if( !nic || !ipaddr )//判断这两个参数是否定义
{
printf("invalid input arguments\n");//输入的参数无效
return -1;
}
snprintf(command, sizeof(command), "ifconfig %s", nic);//把"ifconfig eth0"命令存放到command数组里
printf("command: %s\n", command);//打印command中的字符串
fp=popen(command, "r");//打开一个进程执行命令command,r表示可以读取该进程下的标准输出内容,fp指向该进程
if( NULL == fp)
{
printf("popen() for command %s failure: %s\n", command, strerror(errno));//popen失败
return -2;
}
while( fgets(buf, sizeof(buf), fp) )//把fp指向的进程中的内容存储到buf中
{
if( NULL!= (p1=strstr(buf, "inet addr:")) )//用strstr函数在buf中查找inet addr的位置,记录在p1中
{
p2 = strchr(p1, ':');//如果找到inet addr ,就继续找":",把位置记录在p2中
if(p2 == NULL)//如果p2为空,则没有ip信息
break;
p2++;//找到":"之后,p2指向":"后的字符串的地址
p1 = strchr(p2, ' ');//在p2中查找"空格",把地址记录在p1中
if(p1 == NULL)
break;
strncpy(ipaddr, p2, p1-p2);//把从p2地址开始到p1-p2大小的内容拷贝到ipaddr中,就是把找到的ip信息保存到ipaddr中
rv = 0;
if( netmask )//继续查找子网掩码信息
{
testip.c
rv = -1;
p2 = strrchr(p1, ':');//我们知道netmask的信息在ip之后,所以从p1记录的地址继续找":",把地址记录在p2中
if(p2 == NULL)
break;
p2++;//p2指向":"之后的字符
p1 = strchr(p2, '\n');//在p2中找换行符"\n",把地址记录在p1中
if(p1 == NULL)
break;
strncpy(netmask, p2, p1-p2);//把从p2开始,p1-p2大小的内容拷贝到netmask中,就是保存子网掩码
rv = 0;
}
}
}
pclose(fp);//关闭打开的进程
return rv;
}
在写代码时,功能复杂的代码,在主函数main()内只负责调用相关函数,比较简洁,对应功能的函数要在开头进行声明,在编写时做一些说明,有助于整理程序。
一、popen()函数
popen()计算机科学中的进程I/O函数,与pclose函数一起使用,必须由 pclose 来终止
头文件
#include <stdio.h>
函数说明
FILE * popen ( const char * command , const char * type );
int pclose ( FILE * stream );
type 参数只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 "r" 则文件指针连接到 command 的标准输出;如果 type 是 "w" 则文件指针连接到 command 的标准输入。
command 参数是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用-c 标志,shell 将执行这个命令。
二、snprintf()函数
int snprintf(char *restrict buf, size_t n, const char * restrict format, ...);
函数说明: 最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。
函数返回值: 若成功则返回欲写入的字符串长度,若出错则返回负值。
将可变个参数(...)按照format格式化成字符串,然后将其复制到str中。
三、fgets()
函数原型:
char *fgets(char *buf, int bufsize, FILE *stream);
参数:
*buf: 字符型指针,指向用来存储所得数据的地址。
bufsize: 整型数据,指明存储数据的大小。
*stream: 文件结构体指针,将要读取的文件流。
从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0'),如果文件中的该行,不足bufsize个字符,则读完该行就结束。如若该行(包括最后一个换行符)的字符数超过bufsize-1,则fgets只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续读该行。函数成功将返回buf,失败或读到文件结尾返回NULL。
四、str*系列
头文件
#include<string.h>
strstr()
strstr(string,search [, bool $before_needle = false ])
strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
string 规定被搜索的字符串。
search 规定所搜索的字符串
strchr()
strchr函数原型:extern char *strchr(const char *s,char c);
查找字符串s中首次出现字符c的位置。
strrchr()
strrchr(string,char)
查找字符在指定字符串中从左面开始的最后一次出现的位置,如果成功,返回该字符以及其后面的字符,如果失败,则返回 NULL。
string 规定被搜索的字符串。
char 规定要查找的字符。如果该参数是数字,则搜索匹配数字 ASCII 值的字符。如果该参数多于一个字符,则以第一个字符为准。
关于rv要做几点说明,在写程序时,很多时候为了能够及时排除bug,要明确知道程序的每一步执行的情况就要用到rv,返回值来判断,尤其是涉及到子函数,因为很多时候主函数只是调用子函数,它不能具体掌握子函数的执行情况,这个时候返回值就会派上用场。
还有就是csdn博客格式有些问题,代码排版不太好。有时间我再来改吧。