我正在尝试查找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组)。
所以,基本上我的问题是找出每个组有多少个成员,所以我的计数器(程序中的i,最后一个for循环)将具有很好的上限。
答案 0 :(得分:1)
您的问题在这里:
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++ ){
答案 1 :(得分:0)
运行您的代码,我发现您的问题在grp->gr_mem[i] == NULL
调用中使用之前没有验证strcmp
:
if (grp->gr_mem[i] == NULL)
continue;
在 strcmp
呼叫之前添加这些行对我来说是有效的。
此外,不要忘记释放正在使用的内存。我不知道这是否是您的完整代码,但是在这里您应该考虑在while循环中使用free(name)
。