- 浏览: 144208 次
-
文章分类
最新评论
UNIX 中有个和用户登录密切相关的口令文件 /etc/passwd,POSIX.1 定义了下面两个可获取口令文件项的函数。
getpwuid 函数由 ls 程序使用,它将 i 节点中的数字用户 ID 映射为用户登录名。而在键入登录名时,getpwnam 函数由 login 程序使用。这两个函数都返回一个指向 passwd 结构的指针,该结构包含了组成 /etc/passwd 文件的各个字段,它通常是函数内部的静态变量,所以只要调用任一相关函数,其内容就会被重写。
如果要查看的只是登录名或用户 ID,那么这两个函数能满足要求,而如果要查看整个口令文件时,则可使用 XSI 扩展中提供的下列 3 个函数。
调用 getpwent 时,它返回口令文件中的下一个记录项。每次调用此函数都会重写 passwd 结构。在第一次调用时,它就会打开它所使用的各个文件。函数 setpwent 打开(如果文件尚未打开)并反绕它所使用的文件,endpwent 则关闭这些文件。在使用 getpwent 查看完口令文件后,一定要调用 endpwent 关闭来这些文件。因为 getpwent 知道什么时间应当打开它所使用的文件(第一次被调用时),但是却不知道何时关闭它们。
下面是一个利用这 3 个函数实现的一个 getpwnam 程序。
在函数开始处调用 setpwent 是自我保护性的措施,以便确保如果在此之前已经调用 getpwent 打开了有关文件的情况下,反绕这些文件使它们定位到开始处。getpwnam 和 getpwuid 完成后不应使有关文件仍处于打开状态,所以要调用 endpwent 关闭它们。
不过为了安全,加密口令一般是存放在阴影口令文件 /etc/shadow 中,该文件至少要包含用户名和加密口令,与该口令相关的其它信息也可存放在该文件中。一般用户是不可以读取该文件的,仅有少数几个程序需要访问加密口令,如 login 和 passwd 等,这些程序常常是设置用户 ID 为 root 的程序。在 Linux 3.2.0 和 Solaris 10 中,与访问口令文件的一组函数相类似,有另一组函数可用于访问阴影口令文件(在 FreeBSD 8.0 和 Mac OS X 10.6.8 中,没有阴影口令结构,附加的账户信息存放在口令文件中)。
UNIX 中的每个账户除了这些个人信息外,还拥有所属组的相关信息,这些信息保存在 /etc/group 文件中。UNIX 也提供了类似上面的一组函数来操作该文件。
当用户登录时,系统就按口令文件记录项中的数值组 ID 赋给他实际组 ID(可以在任何时候使用 newgrp 更改组 ID,执行不带参数的 newgrp 则可返回到原来的组)。在 4.2 BSD 引入了附属组 ID 的概念后,一个账户还可属于多至 16(由 NGROUPS_MAX 规定)个另外的组。所以文件访问权限检查时不仅将进程的有效组 ID 与文件的组 ID 相比较,而且也将所有附属组 ID 与文件的组 ID 进行比较。
可使用下面 3 个函数来获取和设置附属组 ID。
getgroups 将进程所属用户的各附属组填写到数组 grouplist 中,填写入的附属组 ID 数最多为 gidsetsize 个,实际填写的附属组 ID 数由函数返回。特殊地,如若 gidsetsize 为 0,则函数只返回附属组 ID 数,而不修改 grouplist(这使得调用者可以确定 grouplist 的长度,以便进行分配)。
setgroups 可由超级用户调用以便为调用进程设置附属组 ID 表。grouplist 是组 ID 数组,而 ngroups 说明了数组中的元素数,ngroups 的值不能大于 NGROUPS_MAX。
通常,只有 initgroups 函数调用 setgroups,initgroups 使用 getgrent 等函数读整个组文件,然后对 username 确定其组的成员关系,然后调用 setgroups,以便为该用户初始化附属组 ID 表。除了在组文件中找到 username 是成员的所有组,initgroups 也在附属组 ID 表中包括了 basegid,basegid 是 username 在口令文件中的组 ID。只有 login 等少数几个程序会调用 initgroups 函数。
除了口令文件和组文件外,UNIX 系统还使用很多其他文件。比如,记录各网络服务器所提供服务的数据文件 /etc/services,记录协议信息的数据文件 /etc/protocols,以及记录网络信息的数据文件 /etc/networks 等。这些数据文件一般都至少提供了类似的 get、set 和 end 函数。如果数据文件支持某种形式的键搜索,则也提供类似于口令文件中的 getpwnam 和 getpwuid 之类的可搜索具有指定键的记录的例程。下表列出了 UNIX 常用的这类例程。
#include <pwd.h> struct passwd *getpwuid(uid_t uid); struct passwd *getpwnam(const char *name); /* 返回值:若成功,都返回指针;否则,都返回 NULL */ struct passwd{ char *pw_name; // 用户名 char *pw_passwd; // 加密口令 uid_t *pw_uid; // 数值用户 ID gid_t *pw_gid; // 数值组 ID char *pw_gecos; // 注释字段 char *pw_dir; // 初始工作目录 char *pw_shell; // 初始 shell(用户程序) char *pw_class; // 用户访问类 time_t *pw_change; // 下次更改口令时间 time_t *pw_expire; // 账户有效期时间 };
getpwuid 函数由 ls 程序使用,它将 i 节点中的数字用户 ID 映射为用户登录名。而在键入登录名时,getpwnam 函数由 login 程序使用。这两个函数都返回一个指向 passwd 结构的指针,该结构包含了组成 /etc/passwd 文件的各个字段,它通常是函数内部的静态变量,所以只要调用任一相关函数,其内容就会被重写。
如果要查看的只是登录名或用户 ID,那么这两个函数能满足要求,而如果要查看整个口令文件时,则可使用 XSI 扩展中提供的下列 3 个函数。
#include <pwd.h> struct passwd *getpwent(void); /* 返回值:若成功,返回指针;若出错或到达文件尾端,返回 NULL */ void setpwent(void); void endpwent(void);
调用 getpwent 时,它返回口令文件中的下一个记录项。每次调用此函数都会重写 passwd 结构。在第一次调用时,它就会打开它所使用的各个文件。函数 setpwent 打开(如果文件尚未打开)并反绕它所使用的文件,endpwent 则关闭这些文件。在使用 getpwent 查看完口令文件后,一定要调用 endpwent 关闭来这些文件。因为 getpwent 知道什么时间应当打开它所使用的文件(第一次被调用时),但是却不知道何时关闭它们。
下面是一个利用这 3 个函数实现的一个 getpwnam 程序。
#include <pwd.h> #include <stddef.h> #include <string.h> struct passwd * getpwnam(const char *name){ struct passwd *ptr; setpwent(); while((ptr=getpwent()) != NULL){ if(strcmp(name, ptr->pw_name) == 0) break; } endpwent(); return ptr; // ptr is NULL if no match found. }
在函数开始处调用 setpwent 是自我保护性的措施,以便确保如果在此之前已经调用 getpwent 打开了有关文件的情况下,反绕这些文件使它们定位到开始处。getpwnam 和 getpwuid 完成后不应使有关文件仍处于打开状态,所以要调用 endpwent 关闭它们。
不过为了安全,加密口令一般是存放在阴影口令文件 /etc/shadow 中,该文件至少要包含用户名和加密口令,与该口令相关的其它信息也可存放在该文件中。一般用户是不可以读取该文件的,仅有少数几个程序需要访问加密口令,如 login 和 passwd 等,这些程序常常是设置用户 ID 为 root 的程序。在 Linux 3.2.0 和 Solaris 10 中,与访问口令文件的一组函数相类似,有另一组函数可用于访问阴影口令文件(在 FreeBSD 8.0 和 Mac OS X 10.6.8 中,没有阴影口令结构,附加的账户信息存放在口令文件中)。
#include <shadow.h> struct spwd *getspnam(const char *name); struct spwd *getspent(void); /* 返回值:若成功,都返回指针;否则,都返回 NULL */ void setspent(void); void endspent(void); struct spwd{ char *sp_namp; // 用户登录名 char *sp_pwdp; // 加密口令 int sp_lstchg; // 上次更改口令以来经过的时间 int sp_min; // 经多少天后允许修改 int sp_max; // 要求更改尚余天数 int sp_warn; // 超期警告天数 int sp_inact; // 账户不活动之前尚余天数 int sp_expire; // 账户超期天数 unsigned int sp_flag; // 保留 };
UNIX 中的每个账户除了这些个人信息外,还拥有所属组的相关信息,这些信息保存在 /etc/group 文件中。UNIX 也提供了类似上面的一组函数来操作该文件。
#include <grp.h> struct group *getgrgid(gid_t gid); struct group *getgrnam(const char *name); /* 返回值:若成功,都返回指针;否则,都返回 NULL */ struct group *getgrent(void); /* 返回值:若成功,返回指针;若出错或到达文件尾端,返回 NULL */ void setgrent(void); void endgrent(void); struct group{ char *gr_name; // 组名 char *gr_passwd; // 加密口令 int gr_gid; // 数值组 ID char **gr_mem; // 指向各用户名指针的数组,以 null 指针结尾 };
当用户登录时,系统就按口令文件记录项中的数值组 ID 赋给他实际组 ID(可以在任何时候使用 newgrp 更改组 ID,执行不带参数的 newgrp 则可返回到原来的组)。在 4.2 BSD 引入了附属组 ID 的概念后,一个账户还可属于多至 16(由 NGROUPS_MAX 规定)个另外的组。所以文件访问权限检查时不仅将进程的有效组 ID 与文件的组 ID 相比较,而且也将所有附属组 ID 与文件的组 ID 进行比较。
可使用下面 3 个函数来获取和设置附属组 ID。
#include <unistd.h> int getgroups(int gidsetsize, gid_t grouplist[]); /* 返回值:若成功,返回附属组 ID 数量;否则,返回 -1 */ #include <grp.h> // on Linux #include <unistd.h> // on FreeBSD, Mac OS X, and Solaris int setgroups(int ngroups, const gid_t groupslist[]); #include <grp.h> // on Linux and Solaris #include <unistd.h> // on FreeBSD and Mac OS X int initgroups(const char *username, gid_t basegid); /* 返回值:若成功,都返回 0;否则,都返回 -1 */
getgroups 将进程所属用户的各附属组填写到数组 grouplist 中,填写入的附属组 ID 数最多为 gidsetsize 个,实际填写的附属组 ID 数由函数返回。特殊地,如若 gidsetsize 为 0,则函数只返回附属组 ID 数,而不修改 grouplist(这使得调用者可以确定 grouplist 的长度,以便进行分配)。
setgroups 可由超级用户调用以便为调用进程设置附属组 ID 表。grouplist 是组 ID 数组,而 ngroups 说明了数组中的元素数,ngroups 的值不能大于 NGROUPS_MAX。
通常,只有 initgroups 函数调用 setgroups,initgroups 使用 getgrent 等函数读整个组文件,然后对 username 确定其组的成员关系,然后调用 setgroups,以便为该用户初始化附属组 ID 表。除了在组文件中找到 username 是成员的所有组,initgroups 也在附属组 ID 表中包括了 basegid,basegid 是 username 在口令文件中的组 ID。只有 login 等少数几个程序会调用 initgroups 函数。
除了口令文件和组文件外,UNIX 系统还使用很多其他文件。比如,记录各网络服务器所提供服务的数据文件 /etc/services,记录协议信息的数据文件 /etc/protocols,以及记录网络信息的数据文件 /etc/networks 等。这些数据文件一般都至少提供了类似的 get、set 和 end 函数。如果数据文件支持某种形式的键搜索,则也提供类似于口令文件中的 getpwnam 和 getpwuid 之类的可搜索具有指定键的记录的例程。下表列出了 UNIX 常用的这类例程。
![](http://dl2.iteye.com/upload/attachment/0126/5338/48343d61-f10a-364d-b736-47ce98e15b32.png)
发表评论
-
打开伪终端设备
2018-07-09 20:50 1264在伪终端概述一节中已对 PTY进行了初步的介绍。尽管 ... -
伪终端概述
2018-06-02 11:05 1566伪终端就是指,一个应用程序看上去像一个终端,但事实上它 ... -
终端窗口大小和 termcap
2018-05-29 22:39 808多数 UNIX 系统都提供了一种跟踪当前终端窗口大小的 ... -
终端规范模式和非规范模式
2018-05-29 00:25 973终端规范模式很简单:发一个读请求,当一行已经输入后,终 ... -
终端标识
2018-05-23 11:18 576尽管控制终端的名字在多数 UNIX 系统上都是 /de ... -
波特率和行控制函数
2018-05-22 07:53 954虽然大多数终端设 ... -
终端属性和选项标志
2018-05-20 07:40 715tcgetattr 和 tcsetattr ... -
终端特殊输入字符
2018-05-17 06:33 826终端支持下表所示的特殊输入字符。 为了更改 ... -
终端 I/O 综述
2018-05-10 07:56 450终端设备可认为是由内核中的终端驱动程序控制的。每个终端 ... -
POSIX 信号量
2018-05-09 00:03 588在XSI IPC通信之信 ... -
XSI IPC 通信之共享存储
2018-04-25 07:18 956在XSI IPC通信之消息队列和XSI IPC通信之信 ... -
XSI IPC通信之信号量
2018-04-17 23:38 628在XSI IPC通信之消 ... -
XSI IPC通信之消息队列
2018-04-15 10:54 508消息队列是消息的链接表,存储在内核中,由消息队列标识符 ... -
XSI IPC 相似特征介绍
2018-02-08 23:48 491有 3 种称作 XSI IPC ... -
IPC 通信之 FIFO
2018-02-06 22:55 432FIFO 也被称为命名管道,未命名的管道只能在两个相关 ... -
IPC 通信之管道
2018-01-30 22:22 401管道是 UNIX 系统 IPC 的最古老但也是最常用的 ... -
readv/writev 函数及存储映射 I/O
2018-01-19 00:57 911readv 和 writev 函数可用于在一次函数调用 ... -
POSIX 异步 I/O
2018-01-16 21:33 467POSIX 异步 I/O 接口为对不同类型的文件进行异 ... -
fcntl 记录锁
2018-01-06 23:48 639记录锁的功能是:当有进程正在读或修改文件的某个部分时, ... -
守护进程惯例
2018-01-06 23:52 447UNIX 系统中,守护进程遵循下列通用惯例。 ...
相关推荐
以下是一些主要的C文件操作函数的详细说明: 1. `clearerr(stream)`:这个函数用于清除文件流的错误标志和结束标志。当你发现文件流可能存在错误但不希望立即关闭文件时,可以调用`clearerr()`,它不会产生任何实际...
C语言文件操作函数大全 C语言中文件操作函数是指程序中对文件进行读、写、关闭、检测等操作的函数。这些函数都是C语言标准库stdio.h中的一部分,用于实现文件的输入/输出操作。 1. clearerr() 函数 函数说明:...
C语言文件操作函数是C语言标准库中用于进行文件读写、控制和管理的一组函数,这些函数为程序提供了访问和操作磁盘文件的能力。在进行C语言文件操作时,通常要涉及到几个基本步骤,包括打开文件、读写文件、关闭文件...
在 Windows 操作系统中,文件操作可以分为文件的创建、打开、读取、写入、关闭等几个过程。 首先,需要了解文件操作的基本概念。文件操作的基本概念包括文件的创建、文件的打开、文件的读取、文件的写入、文件的...
这里我们详细讨论几个重要的C语言文件操作函数。 1. `clearerr()` 函数:这个函数用于清除文件流的错误标志。当你调用`clearerr(stream)`时,它会将指定文件流`stream`的错误状态清零,这意味着之后的文件操作将...
本文将全面总结C语言中的文件操作函数,帮助你深入理解和掌握这些核心概念。 1. **文件操作的基础** - **文件流的概念**:在C语言中,文件被看作是字节流,我们通过`stdio.h`库中的函数来处理这些字节流。 - **...
以上介绍了FatFs文件系统的两个核心函数:`f_mount` 和 `f_open`。通过这些函数,开发人员可以轻松地在嵌入式系统中实现基本的文件系统操作。此外,FatFs还提供了其他许多实用的API函数,如`f_close`、`f_read`、`f_...
C语言文件操作函数大全 本文档总结了C语言中常用的文件操作函数,包括文件流错误旗标清除、文件关闭、文件描述词转换、文件流是否读到文件尾检查、缓冲区更新、从文件中读取一个字符、从文件中读取一字符串等操作。...
Linux 操作系统中的文件操作函数是指在 C 语言中用来处理文件的函数,这些函数都是通过头文件 `stdio.h` 定义的。下面是常用的文件操作函数: 1. `clearerr` 函数:清除文件流的错误旗标 `clearerr` 函数的功能是...
在 Linux 操作系统中,C 语言提供了多种文件读写函数,包括非标准文件读写函数和标准文件读写函数。下面将对这两种类型的文件读写函数进行详细介绍。 非标准文件读写函数 非标准文件读写函数主要用于读写二进制...
`fclose()`函数则用于结束文件操作,释放系统资源。 4. **文件读取和写入**:`fread()`和`fwrite()`用于从文件读取和写入数据,而`fgets()`和`fprintf()`则适用于读取和写入字符串。在写入时,需要确保有足够的磁盘...
在Linux操作系统中,文件操作是日常任务的核心部分。文件操作主要通过系统调用和应用程序编程接口(API)来实现,这些接口提供了与操作系统内核交互的途径。在Linux中,系统调用是一组特殊的接口,允许用户程序请求...
本报告详细介绍了 Linux 操作系统下的二级文件系统设计报告,涵盖了文件系统的设计目的、设计容、实验环境、设计思路、数据结构、主要函数等方面的内容,旨在帮助读者更好地理解文件系统的基本功能和实现机制。
5. **关闭文件**:完成文件操作后,调用`close()`函数关闭文件流,释放资源。 6. **文件删除**:在操作系统层面,可以使用`remove()`函数删除文件。在模拟文件系统时,我们需要维护一个文件元数据结构,如文件名、...
【Linux 文件操作系统】是Linux操作系统中的核心组成部分,它负责管理和控制系统的文件系统,提供对文件的创建、读取、写入、删除等基本操作。在Linux环境下,C语言编程经常被用于实现对文件系统的交互,因为C语言...
Windows操作系统提供了大量的API函数,使得程序员能够实现各种复杂的任务,如文件操作、网络通信、用户界面构建等。本篇文章将围绕“介绍API函数的中文帮助文件”这一主题,深入探讨API函数的基本概念、使用方法以及...
除了这些基本的文件操作函数,Delphi还提供了其他高级功能,如目录操作(如`DirectoryExists`、`CreateDir`、`DeleteDir`)、文件属性查询(如`GetFileAttributes`、`SetFileAttributes`)以及文件搜索(如`Find...
这个系统能够完成基本的文件操作,如创建、删除、读取和写入。 首先,我们需要理解文件系统的概念。文件系统是操作系统用于组织和存储数据的一种方式,它定义了文件如何在磁盘或其他存储介质上存储和检索。在单级...
在计算机科学领域,图形文件操作函数是用于处理各种图像文件的核心工具。这些函数涉及读取、写入、编辑和转换图像文件,使我们能够在不同应用和系统之间共享和使用图像。在本文中,我们将深入探讨“图形方面文件操作...