最基础的用户管理(一) - GenesisOS

目录

一.前言

二.Linux发行版的用户管理 

三.GenesisOS的用户管理

四.动手实践

code.h

GError.c

GError.h 

usr_db.c

usr_db.h

Makefile 

五.结尾


 

一.前言

上次说要使用Waland来构建基础图形,但想了想,先是完成一些简单基础的内容才是正道

本文里的代码是在 Ubuntu23.04 里完成的,使用了C与Rust混合编写

二.Linux发行版的用户管理 

Linux发行版中的用户管理是操作系统管理的一个重要部分,它涉及到用户账户的创建、配置、维护和删除。

  1. 安全性:

    不同用户可以拥有不同的权限和访问控制,通过用户管理,管理员能够确保只有授权用户才可以访问特定资源和敏感信息。这有助于保护系统和数据不被未授权访问。
  2. 资源控制:

    系统资源(如 CPU、内存、存储和网络等)的分配和使用可以通过用户管理进行监控和控制,以确保资源得到公平合理的分配。
  3. 活动审计:

    用户管理使得系统管理员能够追踪和监视用户活动,这有助于发现并解决安全事件,进行合规审计。
  4. 多用户环境:

    Linux 支持多用户使用,在同一系统上可以有多个用户共享资源而不相互干扰,用户管理提供了用户隔离和资源分配的机制。
  5. 方便系统管理:

    通过用户管理,管理员可以批量管理用户(如添加、删除、修改用户信息),提高系统管理的效率。

可以看出用户管理对的重要性

三.GenesisOS的用户管理

目前是这样设计的:

可能看起来有点简单,先这样

四.动手实践

值得注意的是,我们的数据存储在/etc里,是一个数据库,这一点与其他发行版不同,后面将实现权限设置,以确保该数据库只能被系统应用所访问

使用数据库,我认为有几个优点:

  • 数据持久性:数据库能够存储数据,即使系统重启或出现故障,数据依然存在。
  • 并发访问:多个用户可以同时访问和操作数据库中的数据,数据库管理系统负责处理并发问题。
  • 数据完整性:数据库管理系统通常会提供机制以确保数据的完整性和一致性。
  • 灵活查询:通过使用 SQL,用户可以灵活地查询和分析数据。

当然,不同设计有不同看法,以上均为个人观点,接下来我们来看以下代码 

code.h
#ifndef GENESISOS_CODE_H
#define GENESISOS_CODE_H

#define WRONG       -2
#define UNDONE      -1
#define UNEXIST      0
#define DONE         1
#define EXIST        2

#endif //GENESISOS_CODE_H

定义了一些能用得到的状态,字面意思,应该不用解释...

GError.c
#include <GError.h>

int Warning(const char* app, const char* value)
{
    printf("\033[31m%s(Warning): %s\n\033[0m", app, value);
    return 0;
}

int Error(const char* app, const char* value)
{
    printf("\033[31m%s(Error): %s\n\033[0m", app, value);
    exit(1);
}

实现了两个函数,用于警告与错误输出 ,其实就是为了方便处理

GError.h 
#ifndef GENESISOS_GERROR_H
#define GENESISOS_GERROR_H

#include <code.h>
#include <stdio.h>
#include <stdlib.h>

int Error(const char* app, const char* value);
int Warning(const char* app,const char* value);

#endif //GENESISOS_GERROR_H
usr_db.c
#include <usr_db.h>

const char* new_usr_table_i = "CREATE TABLE usr ("
                              "usr_name     CHAR(50)    NOT NULL,"
                              "password     CHAR(50)    NOT NULL,"
                              "uid          INT         NOT NULL,"
                              "home         CHAR(50)    NOT NULL,"
                              "shell        CHAR(50)    NOT NULL,"
                              "things       CHAR(200)   NOT NULL,"
                              "account      CHAR(100),"
                              "account_s    CHAR(3)     NOT NULL"
                              ");"
                              "CREATE TABLE lia ("
                              "usr_name     CHAR(50)    NOT NULL,"
                              "uid          INT         NOT NULL,"
                              "home         CHAR(50)    NOT NULL,"
                              "shell        CHAR(50)    NOT NULL"
                              ");";
const char* lia_del_all_i = "DELETE FROM lia;";
const char* lia_del_i = "DELETE FROM lia WHERE usr_name = ?;";
const char* lia_check_i = "SELECT 1 FROM lia WHERE usr_name = ? LIMIT 1;";
const char* check_usr_db_i = "SELECT 1 FROM usr WHERE usr_name = ? LIMIT 1;";
const char* check_usr_password_i = "SELECT password FROM usr WHERE usr_name = ?;";
const char* lia_add_i = "INSERT INTO lia (usr_name,uid,home,shell) VALUES (?,?,?,?);";
const char* get_usr_info_db_i = "SELECT uid, home, shell FROM usr WHERE usr_name = ?;";
const char* add_usr_db_i = "INSERT INTO usr (usr_name,password,uid,home,shell,things,account,account_s) VALUES (?,?,?,?,?,?,?,?);";

char *app = "usrcontrol";


int new_usr_table() {
    sqlite3 *db;
    char msg[100];

    if (sqlite3_open(DB, &db) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        Error(app,msg);
    }

    char *errMsg;
    if (sqlite3_exec(db, new_usr_table_i, NULL, NULL, &errMsg) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "%s", errMsg);
        sqlite3_free(errMsg);
        Error(app,msg);
    }

    sqlite3_close(db);
    return DONE;
}

int add_usr_db(const char* name, const char* password, int uid, const char* home, const char* shell, const char* things) {
    sqlite3 *db;
    sqlite3_stmt *stmt;
    char msg[100];

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database, please check the system integrity or initialize the database with 'usrcontrol -i'!");
    }

    if (sqlite3_prepare_v2(db, add_usr_db_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 2, password, -1, SQLITE_TRANSIENT);
    sqlite3_bind_int(stmt, 3, uid);
    sqlite3_bind_text(stmt, 4, home, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 5, shell, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 6, things, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 7, "", -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 8, "NO", -1, SQLITE_TRANSIENT);

    if (sqlite3_step(stmt) != SQLITE_DONE) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return DONE;
}

int check_usr_db(const char* name, const char* password) {
    sqlite3 *db;
    sqlite3_stmt *stmt;
    char msg[100];
    int state = UNDONE;

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database, please check the system integrity or initialize the database with 'usrcontrol -i'!");
    }

    if (sqlite3_prepare_v2(db, check_usr_db_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "Error preparing statement: %s", sqlite3_errmsg(db));
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
    if (sqlite3_step(stmt) != SQLITE_ROW) {
        snprintf(msg, sizeof(msg), "The target user does not exist: %s", name);
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_finalize(stmt);

    if (sqlite3_prepare_v2(db, check_usr_password_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "Error preparing statement for password check: %s", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        state = DONE;
    } else {
        state = UNDONE;
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return state;
}

int get_usr_info_db(const char* name, const char* password, int *uid, char **home, char **shell) {
    sqlite3 *db;
    sqlite3_stmt *stmt;
    char msg[100];
    int state = UNDONE;

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database for reading user info!");
    }

    if (sqlite3_prepare_v2(db, get_usr_info_db_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_close(db);
        Error(app,msg);
    }

    if (check_usr_db(name, password) != DONE){
       return UNDONE;
    }

    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        *uid = sqlite3_column_int(stmt, 0);
        *home = strdup((const char *)sqlite3_column_text(stmt, 1));
        *shell = strdup((const char *)sqlite3_column_text(stmt, 2));
        state = DONE;
    } else {
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        return UNDONE;
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return state;
}

int lia_check(const char* name){
    sqlite3 *db;
    sqlite3_stmt *stmt;
    char msg[100];
    int state = UNEXIST;

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database, please check the system integrity or initialize the database with 'usrcontrol -i'!");
    }

    if (sqlite3_prepare_v2(db, lia_check_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "Error preparing statement: %s", sqlite3_errmsg(db));
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
    if (sqlite3_step(stmt) != SQLITE_ROW) {
        state = UNEXIST;
    } else {
        state = EXIST;
    }
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return state;
}

int lia_add(const char* name, const char* password){
    sqlite3 *db;
    sqlite3_stmt *stmt;
    int uid = 0;
    char *home = NULL;
    char *shell = NULL;
    char msg[100];
    int state = UNDONE;

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database for reading user info!");
    }

    if (sqlite3_prepare_v2(db, lia_add_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_close(db);
        Error(app,msg);
    }

    if (get_usr_info_db(name, password, &uid, &home, &shell) != DONE) {
        return UNDONE;
    }

    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
    sqlite3_bind_int(stmt, 2, uid);
    sqlite3_bind_text(stmt, 3, home, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 4, shell, -1, SQLITE_TRANSIENT);
    state = DONE;

    if (sqlite3_step(stmt) != SQLITE_DONE) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    free(home);
    free(shell);
    return state;
}

int lia_del(const char* name){
    sqlite3 *db;
    sqlite3_stmt *stmt;
    char msg[100];
    int state = UNDONE;

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database for reading user info!");
    }

    if (sqlite3_prepare_v2(db, lia_del_i, -1, &stmt, NULL) != SQLITE_OK) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_close(db);
        Error(app,msg);
    }

    if (lia_check(name) != EXIST){
        sqlite3_close(db);
        Error(app,"The user is not logged in!");
    }

    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
    state = DONE;

    if (sqlite3_step(stmt) != SQLITE_DONE) {
        snprintf(msg, sizeof(msg), "%s", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        Error(app,msg);
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return state;
}

int lia_del_all(){
    sqlite3 *db;
    char msg[100];
    char *errMsg = 0;

    if (sqlite3_open_v2(DB, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
        Error(app,"Unable to open the database for reading user info!");
    }

    if (sqlite3_exec(db, lia_del_all_i, 0, 0, &errMsg) != SQLITE_OK){
        snprintf(msg, sizeof(msg), "%s", errMsg);
        sqlite3_free(errMsg);
        sqlite3_close(db);
        Error(app,msg);
    }
    sqlite3_close(db);
    return DONE;
}

这是今天最重要的,应该容易理解,调用sqlite3,初始化数据库,准备语句,绑定参数,提交更改,关闭数据库

这只是一个最基础的部分,提供的函数,不能够服务与usrcontrol,下次在记录更多代码。

注意,Error()函数已经提供了exit(1),所以Error()后的代码不会被执行。

usr_db.h
#ifndef GENESISOS_USR_DB_H
#define GENESISOS_USR_DB_H

#include <code.h>
#include <GError.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>

#define DB "./usr.db"

extern char *app;
extern const char* lia_add_i;
extern const char* lia_del_i;
extern const char* lia_check_i;
extern const char* add_usr_db_i;
extern const char* lia_del_all_i;
extern const char* check_usr_db_i;
extern const char* new_usr_table_i;
extern const char* get_usr_info_db_i;
extern const char* check_usr_password_i;

int lia_del_all();
int new_usr_table();
int lia_del(const char* name);
int lia_check(const char* name);
int lia_add(const char* name, const char* password);
int check_usr_db(const char* name,const char* password);
int get_usr_info_db(const char* name, const char* password, int *uid, char **home, char **shell);
int add_usr_db(const char* name,const char* password,int uid,const char* home,const char* shell,const char* things);

#endif //GENESISOS_USR_DB_H

对usr_db.c的声明,DB这个定义之后会进行修改,目前为了方便,先这样写着。

Makefile 
# 定义变量
CC = gcc
CFLAGS = -Wall -I./ -I./../sys_api
LDFLAGS = -lsqlite3

# 源文件
SRCS = usr_db.c ../sys_api/GError.c
OBJS = $(SRCS:.c=.o)

# 输出的可执行文件名
TARGET = usrcontrol

# 默认目标
all: $(TARGET)

# 链接目标
$(TARGET): $(OBJS)
	$(CC) -o $@ $^ $(LDFLAGS)

# 编译源文件为目标文件
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# 清理目标文件和可执行文件
clean:
	rm -f $(OBJS) $(TARGET)

.PHONY: all clean

对了,说起makefile,你应该这样放置文件

.
├── sys_api
│   ├── code.h
│   ├── GError.c
│   └── GError.h
└── usr
    ├── Makefile
    ├── usr.db
    ├── usr_db.c
    └── usr_db.h

五.结尾

这只是一个雏形(可能雏形都算不上),但只有经过不断尝试,完善,才会更好。

这次的代码我把他们上传到了Gitee:冰之/GenesisOSicon-default.png?t=N7T8https://gitee.com/mf2022/genesis-os.git

对了,这里面的代码都经过测试,都可以去编写main()函数去调用的 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值