c - 获取二维动态分配字符串数组中单个字符串的长度

标签 c unix etcpasswd

我正在尝试在我的 UNIX 系统中查找用户所属的所有组,并且针对每个用户。实现必须在 C 中。这是我的代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>


static void error_fatal(char* msg) 
{ perror(msg); exit(EXIT_FAILURE); }

int main(int argc, char** argv) {

    struct group* grp;
    struct passwd* pwd;
    char *name;
    int i = 0;

    setpwent();

    while((pwd = getpwent()) != NULL){

        if(  ( name = (char*) malloc( (strlen(pwd->pw_name)+1)*sizeof(char))) == NULL  ) error_fatal("malloc");
        strcpy(name, pwd->pw_name);
        printf("%s:\n", name); 

        setgrent();
        while( (grp = getgrent()) != NULL ) {
            for( i=0; i < (sizeof(grp->gr_mem)/sizeof(grp->gr_mem[0])); i++ ){
                if( /*strlen(&grp->gr_mem[i][0]) == strlen(name) && */ !strcmp(grp->gr_mem[i], name) )
                     printf("%s\n", name);
}                           }

        endgrent(); 
        free(name);

}
    endpwent();

    return 0;
}

但我在“root:”输出后出现段错误。 我很确定问题出在访问/etc/group 文件第四个字段中的成员列表(有关详细信息,请参见 man 5 group)。

所以,基本上我的问题是找出每个组有多少成员,所以我的计数器(程序中的 i,最后一个 for 循环)会有很好的上限。

最佳答案

你的问题在这里:

for( i=0; i < (sizeof(grp->gr_mem)/sizeof(grp->gr_mem[0])); i++ ){

struct group 定义为:

       struct group {
           char   *gr_name;        /* group name */
           char   *gr_passwd;      /* group password */
           gid_t   gr_gid;         /* group ID */
           char  **gr_mem;         /* NULL-terminated array of pointers
                                      to names of group members */
       };

您假设 gr_mem 是一个数组,但它不是。它是指向数组第一个元素的指针。所以 sizeof(grp->gr_mem)/sizeof(grp->gr_mem[0]) 给你一个指针的大小,在你的系统上可能是 8。因此,如果用户的组数少于 8 个,您将最终读取到数组 gr_mem 指向开头的末尾。

因为gr_mem指向的数组是NULL终止的,发现终止符告诉你什么时候循环结束:

for( i=0; grp->gr_mem[i]; i++ ){

关于c - 获取二维动态分配字符串数组中单个字符串的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53675486/

相关文章:

c - Do While 不在 CUDA 内核中工作

Linux 用户名/etc/passwd 列表

python - 使用Python设置来报告/etc/passwd文件中列出的shell

Linux 自定义 NSS 模块, `_nss_SERVICE_getspnam_r` 被调用但 `_nss_SERVICE_getpwnam_r` 未被调用

c - 线程的缓存在退出时是否刷新到主内存?

c - 分支到 PendSV 时覆盖数据

c - 从串行端口 Linux C 读取 NULL 字符

regex - 在 GNU tar 中使用正则表达式

linux - Cronjob 运行时返回错误

c++ - 如何从 Unix 命令行安装 c 和 c++ 编译器,然后与 Eclipse 一起使用?