在口令文件当中,常见的字段有(以root为例):node
root(用户名):x(加密口令):0(uid):0(gid):root(注释字段):/root(用户所在根目录):/bin/bash(用户的shell所在目录)
注意:这里的加密口令只是一个占位符号,真正的加密口令存于阴影文件当中,阴影口令文件不该是通常用户能够读取的。仅有少数几个程序须要存取加密口令,例如login(1)
和passwd(1)
,这些程序经常是设置用户ID为root的程序。用了阴影口令后,普通文件/etc/passwd
可由各用户自由读取。linux
在linux下,如下代码会输出加密口令(从阴影口令文件中拉取):shell
#include "apue.h" #include <shadow.h> int main(){ struct spwd *ptr; if((ptr = getspnam("sysublackbear")) == NULL){ err_sys("getspnam error"); } printf("sp_pwdp = %s\n", ptr->sp_pwdp == NULL || ptr->sp_pwdp[0] == 0 ? "(null)":ptr->sp_pwdp); return 0; }
uname
并输出utsname
结构中的全部字段,将该输出与uname -a
命令的输出结果做比较。本题难度并不大,注意记得函数赋值给一个指向结构体的指针时记得向内存分配一块空间,不然调用uname()
函数时会失败。数组
代码以下:bash
#include "apue.h" #include <sys/utsname.h> int main() { struct utsname* ptr; //在调用函数uname时先开辟一块新的空间,若是将指针设为NULL,下面函数不会运行成功,由于系统没有为其开辟内存空间 ptr = (struct utsname*)malloc(sizeof(struct utsname)); int temp; if(temp = uname(ptr) == -1){ err_sys("uname error"); } //写成uname -a 的形式 printf("%s %s %s %s %s\n",ptr->sysname == NULL ? "(NULL)" : ptr->sysname, ptr->nodename == NULL ? "(NULL)" : ptr->nodename, ptr->release == NULL ? "(NULL)" : ptr->release, ptr->version == NULL ? "(NULL)" : ptr->version, ptr->machine == NULL ? "(NULL)" : ptr->machine ); return 0; }
strftime
将输出结果转换为相似于date
命令的默认输出。将环境变量TZ设置为不一样的值,观察输出结果。代码以下:函数
#include "apue.h" #include <time.h> int main() { time_t caltime; struct tm *tm; char line[MAXLINE]; //获取当前时间 if((caltime = time(NULL)) == -1){ err_sys("time error"); } //将当前时间转换为对应的日历时间,存到tm结构体中 if((tm = localtime(&caltime)) == NULL){ err_sys("localtime error"); } //再将日历时间打印成date的格式 if(strftime(line,MAXLINE,"%a %b %d %X %Z %Y\n",tm) == 0){ err_sys("strftime error"); } //打印字符串(将字符数组输出到stdout流当中) fputs(line,stdout); return 0; }