file address:
https://files.cnblogs.com/files/blogs/773707/tunctl.zip?t=1699629591&download=true
strtol
是 C 语言标准库中的一个函数,用于将字符串转换为长整型数(long
)。
long strtol(const char *str, char **endptr, int base);
str
:要转换的字符串。endptr
:指向字符指针的指针,用于存储转换结束后剩余的字符串的地址。如果这个参数为NULL
,则忽略这个信息。base
:表示数字的进制,可以是 2 到 36 之间的任何值,或者是 0。如果为 0,则根据字符串的前缀来确定进制(0x 或 0X 表示十六进制,0 表示八进制,其它为十进制)。
strtol
返回转换后的长整型数。如果发生错误,返回 0
并设置 errno
。
下面是一个简单的示例,演示如何使用 strtol
:
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[] = "12345";
char *endptr;
long num = strtol(str, &endptr, 10);
if (*endptr != '\0') {
printf("Conversion failed. Remaining string: %s\n", endptr);
} else {
printf("Converted number: %ld\n", num);
}
return 0;
}
此示例将字符串 "12345" 转换为长整型数 12345
,并打印转换结果。如果转换失败,它会打印剩余的字符串。
getgrnam
是 C 语言标准库中的一个函数,用于通过组名获取对应的组结构。该函数的声明如下:
#include <grp.h>
struct group *getgrnam(const char *name);
name
:要查找的组名。
getgrnam
函数返回一个指向 group
结构体的指针,该结构体包含了有关组的信息,包括组名、组 ID、组的用户列表等。如果未找到对应的组,返回 NULL
。
下面是一个简单的示例,演示如何使用 getgrnam
函数:
#include <stdio.h>
#include <grp.h>
int main() {
const char *group_name = "users";
struct group *grp = getgrnam(group_name);
if (grp != NULL) {
printf("Group information for %s:\n", group_name);
printf("Group name: %s\n", grp->gr_name);
printf("Group ID: %d\n", grp->gr_gid);
// Print user list
printf("Group members:\n");
for (int i = 0; grp->gr_mem[i] != NULL; i++) {
printf(" %s\n", grp->gr_mem[i]);
}
} else {
printf("Group %s not found.\n", group_name);
}
return 0;
}
此示例通过组名 "users" 获取组的信息,并打印组名、组 ID 以及组成员的列表。如果未找到组,它会打印相应的消息。
这里的 "bd:f:npt:u:g:h"
是 getopt
函数的第三个参数,即期望的选项字符串。它定义了你的程序可以接受的命令行选项,并指明哪些选项需要参数。
解释一下这个字符串:
b
:表示一个短选项-b
,没有参数。d:
:表示一个短选项-d
,后面需要一个参数。f:
:表示一个短选项-f
,后面需要一个参数。n
:表示一个短选项-n
,没有参数。p
:表示一个短选项-p
,没有参数。t:
:表示一个短选项-t
,后面需要一个参数。u:
:表示一个短选项-u
,后面需要一个参数。g:
:表示一个短选项-g
,后面需要一个参数。h
:表示一个短选项-h
,没有参数。
这个字符串告诉 getopt
函数你的程序支持哪些短选项,以及这些选项是否需要参数。在代码中,getopt
会根据这个字符串解析命令行参数,并将下一个选项字符返回给 opt
变量。
例如,如果你的命令行参数是 -d some_device -u some_user -g some_group
,那么在 while
循环中,getopt
会逐个返回 d
、u
、g
,然后你可以通过 optarg
获取相应的参数值。
getpwnam
函数是用于通过用户名获取用户信息的函数。该函数的声明如下:
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwnam(const char *name);
函数接受一个用户名作为参数,返回一个指向 struct passwd
结构的指针。struct passwd
结构包含了有关用户的信息,例如用户名、用户 ID、组 ID、用户的主目录等。
下面是一个简单的例子,演示如何使用 getpwnam
函数:
#include <stdio.h>
#include <pwd.h>
int main() {
const char *username = "your_username";
struct passwd *pwd = getpwnam(username);
if (pwd != NULL) {
printf("User Information:\n");
printf("Username: %s\n", pwd->pw_name);
printf("User ID: %d\n", (int)pwd->pw_uid);
printf("Group ID: %d\n", (int)pwd->pw_gid);
printf("Home Directory: %s\n", pwd->pw_dir);
} else {
printf("User not found.\n");
}
return 0;
}
请将 "your_username"
替换为你想要查询的实际用户名。在实际应用中,你可能需要检查返回的指针是否为 NULL
,以确定用户是否存在。
argv += optind;
argc -= optind;
这两行代码用于更新命令行参数,以便忽略已经被处理的选项。optind 是 getopt 函数的全局变量,表示下一个要处理的参数的索引。argv 是一个指向命令行参数数组的指针,而 argc 是命令行参数的个数。
在处理命令行参数时,getopt 会逐个获取选项,并将 optind 更新为下一个要处理的参数的索引。optind 的初值通常为 1。optind 之前的参数是程序名,通常不包含选项。
argv += optind; 将 argv 向后移动,指向下一个要处理的参数。argc -= optind; 则减去已经处理的参数个数,以保持 argc 的正确值。这两行代码的目的是调整 argv 和 argc,以便后续的代码只处理用户输入的实际参数,而不包括程序名和已经处理过的选项。
ioctl
是一个用于设备 I/O 控制的系统调用,它可以在不同类型的设备上执行各种操作。在C语言中,ioctl
函数的原型如下:
int ioctl(int fd, unsigned long request, ...);
fd
是指向打开设备的文件描述符。request
是控制命令的整数,用于指定要执行的操作。...
是一个可选的参数列表,用于传递命令所需的任何参数。
ioctl
的使用通常涉及到与具体设备相关的命令和参数。在你提供的代码中,ioctl
主要用于配置 TUN/TAP 设备的属性,例如设置设备的所有者、组、持久性等。
在你的代码中的一些 ioctl
使用示例:
ioctl(tap_fd, TUNSETIFF, (void *) &ifr); // 设置 TUN/TAP 设备的接口
ioctl(tap_fd, TUNSETOWNER, owner); // 设置 TUN/TAP 设备的所有者
ioctl(tap_fd, TUNSETGROUP, group); // 设置 TUN/TAP 设备的组
ioctl(tap_fd, TUNSETPERSIST, 1); // 设置 TUN/TAP 设备为持久性
这些调用通过 ioctl
来与 TUN/TAP 设备进行通信,执行相应的配置和控制操作。