c - C 中的登录模拟器,取消引用不完整类型错误

标签 c unix pointers authentication

作为学校计算机实验室的预备任务,我们被要求编写一个 C 程序来模拟 UNIX 中的登录过程。该程序应该从终端读取用户名和密码,将其与本地文件中的哈希值进行比较,该文件应该类似于/etc/passwd。

这是我得到的:

/*
 * Program mylogin.c
 *
 * This program prompts the user for a login name and password
 *
 */

#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <string.h>

/* define some error constants */
#define NOUSER -1

/* define max size of a username */
#define USERNAME_SIZE 32
#define PASSWORD_SIZE 32
#define HASH_SIZE 32
#define FAILED_LIMIT 5
#define AGE_LIMIT 10

int read_username(char *username)
{

    printf("login: ");
    fgets(username,USERNAME_SIZE,stdin);

    /* remove the CR included by getline() */
    username[strlen(username)-1]='\0';
    return(0);
}

int read_password(char *password)
{

    printf("password: ");
    fgets(password,PASSWORD_SIZE,stdin);
    //getpass(password);

    /* remove the CR included by getline() */
    password[strlen(password)-1]='\0';
    return(0);
}

int user_exists(const char *username)
{
    struct pwdb_passwd *pw_entry;

    pw_entry=getpwnam(username);
    return((pw_entry)!=NULL);
}

int main(int argc,char **argv)
{
    char username[USERNAME_SIZE];
    char* password;

    /* write "login:" and read user input */
    read_username(username);
    read_password(password);

    if (!user_exists(username))
    {
        printf("Unknown user or authentication\n");
        main(argc, argv);
    }
    struct pwdb_passwd *pw_entry = getpwnam(username);
    char* hashed_password = crypt(password,pw_entry->pw_passwd);
    if(strcmp(hashed_password,  pw_entry->pw_passwd)==0)
    {
        if((pw_entry->pw_failed)<FAILED_LIMIT)
        {
            printf("User authenticated successfully\n");
            pw_entry->pw_age++;
            pw_entry->pw_failed = 0;
            pwdb_update_user(pw_entry);
        }else{
            printf("User account locked\n");
            main(argc, argv);
        }
    }
    else
    {
        printf("Unknown user or authentication\n");
        pw_entry->pw_failed++;
        if(pw_entry->pw_failed>5){
            printf("Too many failed attempts. Username now locked\n");
        }
        pwdb_update_user(pw_entry);
        main(argc, argv);
    }
    return(0);
}

struct pwdb_passwd 已在文件 pwdb_lib.c 和 pwdb_lib.h 中定义,这些文件已写入。

当我编译该程序时,出现一些错误。例如,在第 73 行,我得到:“错误:取消引用指向不完整类型的指针”

我不明白为什么。它似乎不喜欢 pw_entry->pw_passwd 之类的东西。更重要的是,在 Windows 下使用 Code::Blocks(使用 gcc)编译时遇到的错误与在 Ubuntu 下使用 gcc 编译时遇到的错误不同。我觉得这很奇怪。我怀疑这可能是因为我导入了 pwd.h 并且它只存在于 Linux 而不是 Windows 上。这可能是对的吗?我尝试创建自己的 pwd.h 文件并将其保存在同一目录中,但仍然不起作用。转移到 ubuntu 计算机,我没有从 pwd.h 中得到错误,而是得到以下错误:“取消引用指向不完整类型的指针”

我的代码有什么问题吗?

我还怀疑 user_exists 函数中存在内存泄漏,但我不确定它是否会影响整个程序。

最佳答案

即使 pwdb_lib.c 已经编写,您仍需要将其包含在源文件中。

添加

#include "pwdb_lib.h"

到您的源代码并确保针对 pwdb_lib.c

进行编译/链接

通过#include此文件,您可以让源文件了解其中的定义,而无需提供实现。最后,当您使用 pwdb_lib.c 编译程序(或者链接其目标文件,如果您正在做的话)时,您可以让包含这些定义的任何源知道它们的实现位置(从而赋予他们使用它们的能力)。

关于c - C 中的登录模拟器,取消引用不完整类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14962835/

相关文章:

c++ - 错误 : Pointer to incomplete class type is not allowed. 我该怎么做?

c - C 中整数的错误乘法

c - C 中全局结构变量的最佳使用

unix - 在sed中使用正则表达式时跳过前n行?

bash - 在每行中查找特定单词并在 unix shell 脚本中显示结果

c++ - 在同一 if 语句中检查 nullptr 和有效索引

c - C 中的 SQLite 绑定(bind) blob 提前终止

python - 使用 "clinic"时如何为 python 模块创建新函数?

bash - 使用自定义记录分隔符和字段分隔符格式化文本输出的 awk 命令

c - 为什么我不能打印地址 0 的值?