UNIX再学习 -- 系统数据文件和信息
UNIX 系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件 /etc/passwd 和组文件 /ect/group 就是经常被多个程序频繁使用的两个文件。用户每次登陆 UNIX 系统,以及每次执行 ls -l 命令时都要使用口令文件。
一、口令文件
1、口令文件简介
/* The passwd structure. */
struct passwd
{char *pw_name; /* Username. */char *pw_passwd; /* Password. */__uid_t pw_uid; /* User ID. */__gid_t pw_gid; /* Group ID. */char *pw_gecos; /* Real name. */char *pw_dir; /* Home directory. */char *pw_shell; /* Shell program. */
};
由于历史原因,口令文件是 /etc/passwd,而且是一个 ASCII 文件。
# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
tarena:x:1000:1000:tarena,,,:/home/tarena:/bin/bash
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
各字段含义就不讲了,关于这些登录项,请注意下列各点:
# finger -p tarena
Login: tarena Name: tarena
Directory: /home/tarena Shell: /bin/bash
Last login Tue Aug 2 11:40 2016 (CST) on pts/3 from ubuntu.local
No mail.
POSIX.1 定义了两个获取口令文件项的函数,在给出用户登录名或者数值用户ID后,这两个函数就能查询相关项。
2、函数 getpwuid 和 getpwnam
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
(1)函数解析
这两个函数都返回一个指向 passwd 结构的指针,该结构已由这两个函数在执行时填入信息。passwd 结构通常是函数内部的静态变量,只要调用任一相关函数,其内容就会被重写。
(2)示例说明
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>int main (void)
{struct passwd *pwd;if ((pwd = getpwuid (1000)) == NULL)perror ("fail to getpwuid"), exit (1);printf("%s,%s,%ld,%ld,%s,%s,%s\n",pwd->pw_name, pwd->pw_passwd,pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); if ((pwd = getpwnam ("tarena")) == NULL)perror ("fail to getpwnam"), exit (1);printf("%s,%s,%ld,%ld,%s,%s,%s\n",pwd->pw_name, pwd->pw_passwd,pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); return 0;
}
输出结果:
tarena,x,1000,1000,tarena,,,,/home/tarena,/bin/bash
tarena,x,1000,1000,tarena,,,,/home/tarena,/bin/bash
3、函数 getpwent、setpwent 和 endpwent
#include <pwd.h>
struct passwd* getpwent(void);
void setpwent(void);
void endpwent(void);
(1)函数解析
用于查看 登录名和用户 ID。
(2)示例说明
#include <pwd.h>
#include <sys/types.h>
#include <stdio.h>int main (void)
{struct passwd *user;setpwent ();while ((user = getpwent ()) != NULL){if (strcmp ("tarena", user->pw_name) == 0)break;}printf ("%s:%d:%d:%s:%s:%s\n",user->pw_name,user->pw_uid,user->pw_gid,user->pw_gecos,user->pw_dir,user->pw_shell);endpwent ();return 0;
}
输出结果:
tarena:1000:1000:tarena,,,:/home/tarena:/bin/bash
(3)示例总结
在函数开始处调用 setpwent 是自我保护性的措施,以便确保如果调用者在此之前已经调用 getpwent 打开了有关文件情况下,反绕有关文件使他们定位到文件开始处。getpwnam 和 getpwuid 完成后不应使有关文件仍处于打开状态。所以应调用 endpwent 关闭它们。
#include<pwd.h>
#include<sys/types.h>
#include <stdio.h>
int main (void)
{struct passwd *user;int i;for(i = 0; i < 4; i++) {user = getpwent ();printf ("%s :%d :%d :%s:%s:%s\n", user->pw_name, user->pw_uid, user->pw_gid,user->pw_gecos, user->pw_dir, user->pw_shell);}
// setpwent();user = getpwent ();printf ("=============================\n");printf ("%s :%d :%d :%s:%s:%s\n", user->pw_name, user->pw_uid, user->pw_gid,user->pw_gecos, user->pw_dir, user->pw_shell);endpwent();return 0;
}
输出结果:
root :0 :0 :root:/root:/bin/bash
daemon :1 :1 :daemon:/usr/sbin:/bin/sh
bin :2 :2 :bin:/bin:/bin/sh
sys :3 :3 :sys:/dev:/bin/sh
=============================
sync :4 :65534 :sync:/bin:/bin/sync
二、阴影口令
加密口令是经单向加密算法处理过的用户口令副本。因为此算法是单向的,所以不能从加密口令猜测到原来的口令。
/* Structure of the password file. */
struct spwd{char *sp_namp; /* Login name. */char *sp_pwdp; /* Encrypted password. */long int sp_lstchg; /* Date of last change. */long int sp_min; /* Minimum number of days between changes. */long int sp_max; /* Maximum number of days between changes. */long int sp_warn; /* Number of days to warn user to changethe password. */long int sp_inact; /* Number of days the account may beinactive. */long int sp_expire; /* Number of days since 1970-01-01 untilaccount expires. */unsigned long int sp_flag; /* Reserved. */};
阴影口令文件是 /etc/shadow
# cat /etc/shadow
root:$6$MNQKabSO$UcLm09JPH7JdppbRZBrj4XoWUQIWRhqhwdzJ9F2mGlwSXo5V.ylP4.gaReQSw3sZSSuczM1iqnMKBrwnbDlgz/:17131:0:99999:7:::
tarena:$6$kea9L4dJ$PeK8uyZ8MesNW6zG1fMMnJIol4icj0nLKAg7Vq78sLJJhEs1Sr6M/VpxBvy.kGeMVDr2SC/EN8Utx5OSIx8Fs/:16630:0:99999:7:::
nobody:*:15453:0:99999:7:::
1、阴影口令函数
#include <shadow.h>
struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
返回值:成功返回指针,失败返回 NULL
(1)函数功能
(2)示例说明
#include <stdio.h>
#include <shadow.h>
#include <stdlib.h>int main (void)
{ struct spwd* spwd; if ((spwd = getspnam("tarena")) == NULL) perror("getspnam"), exit (1); printf("%s,%s,%ld,%ld,%ld,%ld,%ld,%ld,%lu\n",spwd->sp_namp,spwd->sp_pwdp,spwd->sp_lstchg,spwd->sp_min,spwd->sp_max,spwd->sp_warn,spwd->sp_inact,spwd->sp_expire,spwd->sp_flag); setspent(); while ((spwd = getspent()) != NULL){if (strcmp ("tarena", spwd->sp_namp) == 0)break;}printf("%s,%s,%ld,%ld,%ld,%ld,%ld,%ld,%lu\n",spwd->sp_namp,spwd->sp_pwdp,spwd->sp_lstchg,spwd->sp_min,spwd->sp_max,spwd->sp_warn,spwd->sp_inact,spwd->sp_expire,spwd->sp_flag); endspent(); return 0;
}
输出结果:
tarena,$6$kea9L4dJ$PeK8uyZ8MesNW6zG1fMMnJIol4icj0nLKAg7Vq78sLJJhEs1Sr6M/VpxBvy.kGeMVDr2SC/EN8Utx5OSIx8Fs/,16630,0,99999,7,-1,-1,4294967295
tarena,$6$kea9L4dJ$PeK8uyZ8MesNW6zG1fMMnJIol4icj0nLKAg7Vq78sLJJhEs1Sr6M/VpxBvy.kGeMVDr2SC/EN8Utx5OSIx8Fs/,16630,0,99999,7,-1,-1,4294967295
2、思考
$sudo passwd root
Enter new UNIX password: <--- 新的Root用户
Password: <--- 输入你当前用户davinci的密码
密码
Retype new UNIX password: <--- 重复新的Root用户密码
passwd:已成功更新密码
(1)可以写个程序验证密码是不是 root:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> int main(void)
{ char *passwd; char key[] = "root"; passwd = crypt(key, "$6$MNQKabSO$"); printf("root: %s\n", passwd); return 0;
}
编译:gcc test -lcrypt
输出结果:
root: $6$MNQKabSO$UcLm09JPH7JdppbRZBrj4XoWUQIWRhqhwdzJ9F2mGlwSXo5V.ylP4.gaReQSw3sZSSuczM1iqnMKBrwnbDlgz/
(2)示例总结
#define _XOPEN_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
char *crypt(const char *key, const char *salt);#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <crypt.h>
char *crypt_r(const char *key, const char *salt, struct crypt_data *data);Link with -lcrypt.
返回值:返回一个以 NULL 结尾的密码字符串
注意,编译时需要链接 -lcrypt,否则会出现 undefined reference to `crypt' 错误。
1)参数解析
必需。规定要编码的字符串。
第二个参数:密钥
可选。用于增加被编码字符数目的字符串,以使编码更加安全。如果未提供 salt 参数,则每次调用该函数时会随机生成一个。
(3)参数 salt 为两个字符组成的字符串,由 a-z,A-Z,0-9,".",和 "/" 所组成。
2)函数功能
#include <unistd.h>
char *getpass( const char *prompt);
函数功能:
返回值:
附加说明:
示例说明:
//示例一
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <crypt.h>
int main()
{ char passwd[13]; char *key; char slat[2]; key = getpass("Input first passward:"); slat[0] = key[0]; slat[1] = key[1]; strcpy(passwd,crypt(key,slat)); key = getpass("Input second passward:"); slat[0] = passwd[0]; slat[1] = passwd[1]; printf("After crypt(),1st passwd:%s\n",passwd); printf("After crypt(),2st passwd:%s\n",passwd); return 0; }
编译:
# gcc test.c -lcrypt输出结果:
Input first passward://root
Input second passward://root
After crypt(),1st passwd:roK20XGbWEsSM
After crypt(),2st passwd:roK20XGbWEsSM
三、组文件
/* The group structure. */
struct group{char *gr_name; /* Group name. */char *gr_passwd; /* Password. */__gid_t gr_gid; /* Group ID. */char **gr_mem; /* Member list. */};
其中,字段 gr_mem 是一个指针数组,其中每个指针指向一个属于该组的用户名。该数组以 null 指针结尾。
# cat /etc/group
root:x:0:
tarena:x:1000:
#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);
四、附属组 ID
#include <sys/types.h>
#include <unistd.h>
int getgroups(int size, gid_t list[]);#include <grp.h>
int setgroups(size_t size, const gid_t *list);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
setgroups(): _BSD_SOURCE#include <sys/types.h>
#include <grp.h>
int initgroups(const char *user, gid_t group);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
initgroups(): _BSD_SOURCE
1、函数解析
五、其他数据文件
一般情况下,对于每个数据文件至少有 3 个函数:
六、系统标识
1、uname 函数,返回与主机和操作系统有关的信息。
#include <sys/utsname.h>
int uname(struct utsname * name);
返回值:成功返回非负值,失败返回 -1
(1)参数解析
/* Structure describing the system and machine. */
struct utsname{/* Name of the implementation of the operating system. */char sysname[_UTSNAME_SYSNAME_LENGTH];/* Name of this node on the network. */char nodename[_UTSNAME_NODENAME_LENGTH];/* Current release level of this implementation. */char release[_UTSNAME_RELEASE_LENGTH];/* Current version level of this release. */char version[_UTSNAME_VERSION_LENGTH];/* Name of the hardware type the system is running on. */char machine[_UTSNAME_MACHINE_LENGTH];#if _UTSNAME_DOMAIN_LENGTH - 0/* Name of the domain of this node on the network. */
# ifdef __USE_GNUchar domainname[_UTSNAME_DOMAIN_LENGTH];
# elsechar __domainname[_UTSNAME_DOMAIN_LENGTH];
# endif
#endif};
(2)示例说明
#include <stdio.h>
#include <sys/utsname.h>
#include <stdlib.h>int main (void)
{struct utsname uts;if (uname (&uts) == -1)perror ("fail to uname"), exit (1);elseprintf ("%s %s %s %s %s\n", uts.sysname, uts.nodename, uts.release, uts.version, uts.machine);return 0;
}
输出结果:
Linux ubuntu 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686
(3)Linux 下的 uname 命令
选项:
-a或--all:显示全部的信息;
-m或--machine:显示电脑类型;
-n或-nodename:显示在网络上的主机名称;
-r或--release:显示操作系统的发行编号;
-s或--sysname:显示操作系统名称;
-v:显示操作系统的版本;
-p或--processor:输出处理器类型或"unknown";
-i或--hardware-platform:输出硬件平台或"unknown";
-o或--operating-system:输出操作系统名称;
--help:显示帮助;
--version:显示版本信息。
示例:
# uname -a
Linux ubuntu 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686 i686 i386 GNU/Linux
2、gethostname 函数
#include <unistd.h>
int gethostname(char * name, int namelen);
返回:若成功则为0,若出错则为-1
(1)函数解析
HOST_NAME_MAX - _SC_HOST_NAME_MAX
Max length of a hostname, not including the terminating null byte, as returned by gethostname(2). Must not be less than _POSIX_HOST_NAME_MAX (255).
而 uname 函数,查看结果为:#define _UTSNAME_LENGTH 65 即最大名字长度为 65
# grep "_UTSNAME_LENGTH" * -rn
i386-linux-gnu/sys/utsname.h:33:# define _UTSNAME_SYSNAME_LENGTH _UTSNAME_LENGTH
i386-linux-gnu/sys/utsname.h:36:# define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH
i386-linux-gnu/sys/utsname.h:39:# define _UTSNAME_RELEASE_LENGTH _UTSNAME_LENGTH
i386-linux-gnu/sys/utsname.h:42:# define _UTSNAME_VERSION_LENGTH _UTSNAME_LENGTH
i386-linux-gnu/sys/utsname.h:45:# define _UTSNAME_MACHINE_LENGTH _UTSNAME_LENGTH
i386-linux-gnu/sys/utsname.h:77:# define SYS_NMLN _UTSNAME_LENGTH
i386-linux-gnu/bits/utsname.h:24:#define _UTSNAME_LENGTH 65
i386-linux-gnu/bits/utsname.h:29:#define _UTSNAME_DOMAIN_LENGTH _UTSNAME_LENGTH
(2)示例说明
#include <stdio.h>
#include <unistd.h>int main (void)
{char name[65];gethostname(name, sizeof(name));printf("hostname = %s\n", name);return 0;
}
输出结果:
hostname = ubuntu
(3)Linux 下的 hostname 命令
选项:
-v:详细信息模式;
-a:显示主机别名;
-d:显示DNS域名;
-f:显示FQDN名称;
-i:显示主机的ip地址;
-s:显示短主机名称,在第一个点处截断;
-y:显示NIS域名。
示例:
# hostname
ubuntu
七、时间和日期例程
八、未讲部分
UNIX再学习 -- 系统数据文件和信息相关推荐
- 《unix环境高级编程》笔记4——系统数据文件和信息
文章目录 系统数据文件和信息 口令文件 获取口令文件 getwpuid getpwnam 阴影口令 组文件 附属组ID 查看附属组ID 其他文件 登录账户记录: 系统标识 uname gethostn ...
- 6.1 引言-系统数据文件和信息
6.1 引言-系统数据文件和信息 Unix系统的正常运行需要使用大量与系统有关的数据文件,例如,口令字文件/etc/passwd和组文件/etc/group就是经常由多种程序使用的两个文件.用户每次登 ...
- Unix环境高级编程-系统数据文件和信息
unix口令文件/etc/passwd 包含了下表所示的字段: 系统定义了两个获取口令文件项的函数,在给出用户登录名或数值用户ID后,这两个函数能够查看相关项. struct passwd *getp ...
- APUE第6章 系统数据文件和信息
6.1 引言 UNIX系统的正常运作需要使用大量与系统有关的数据文件,例 如,口令文件/etc/passwd和组文件/etc/group就是经常被多个程序频繁 使用的两个文件.用户每次登录UNIX系统 ...
- UNIX环境高级编程——系统数据文件和信息
6.1 引言 UNIX系统的正常运行需要使用大量与系统有关的数据文件,这些文件都是ASCII文本文件,并且使用标准I/O库读这些文件. 6.2 口令文件 UNIX口令文件是/etc/passwd,每一 ...
- linux系统数据文件和信息--unix环境高级编程读书笔记
linux系统中的数据文件有很多,在这一章里介绍的主要内容是和系统有关的一系列文件,包括passwd,shadow,group,utmp,wtmp以及一些系统的相关信息和时间的相关操作. 1.pass ...
- 《UNIX环境高级编程》六系统数据文件和信息读书笔记
UNIX系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件/etc/passwd和组文件/etc/group等. 1.口令文件 口令文件的各字段包含在pwd.h>中定义的passwd ...
- 第6章 系统数据文件和信息
口令文件 用户: 基础密码文件:/etc/passwd 密码文件:/etc/shadow 组: 基础密码文件:/etc/group 密码文件:/etc/gshadow /etc/passwd 内容:用 ...
- 第6章系统数据文件和信息总结
1 口令文件的shell字段 如果是空,则使用系统默认的shell,一般是/bin/sh /dev/null:阻止对应的用户名登陆系统 /bin/false:同样是阻止特定用户登录,以不成功状态终止 ...
最新文章
- python 减少可调用对象的参数个数
- python abs()函数是什么意思?
- [蓝桥杯][算法训练VIP]方格取数(双线程dp)
- 声音均衡器怎么调好听_汽车10段音效最佳设置,手把手教你调节车载音响均衡器...
- 信息学奥赛一本通C++语言——1065:奇数求和
- mysql hibernate 分页查询_Hibernate + MySQL 分页类的实现
- 20211205:力扣第270场周赛(上)
- 测试人生 | 三十而已,何需惧怕 年薪40W+涨薪幅度超40%
- linux 扫描媒体库,如何扫描出Android系统媒体库中视频文件
- 樊昌信 通信原理第七版 第九章思考题
- 关于Win10 driver irql not less or equal ndis.sys的个人解决过程
- pcap报文80211-8023区别
- DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection翻译
- c语言运行环境的熟悉实验报告,c语言实验报告
- Centos8安装GitLab14.2开源代码托管工具
- 叽歪网CEO:创业路上也要学会忙中偷闲
- sql 注入 预防_SQL注入:检测和预防
- C Primer Plus 第十二章 课后答案
- vue3:父子组件传值
- VSCode快捷键冲突?关掉微软拼音的简繁体切换热键即可