APUE学习笔记——第六章系统数据文件和信息

1、口令文件

该文件主要是针对unix中的/etc/passwd文件,该文件中存储用户名、用户密码、用户ID、用户主组ID,用户的昵称、用户的家目录、用户Shell这7个信息,但是用户密码现在已经不存储在该文件下,因为该文件所有人都能有读权限,所以不安全,密码改存在/etc/shadow文件中。

Linux中该文件的数据形式:xkey:x:700:100:xkey's color:/home/xkey:/bin/bash

#include <pwd.h>头文件定义了passwd的数据结构(Linux下支持的数据信息):

struct passwd {
      char   *pw_name;       /* username */
      char   *pw_passwd;     /* user password */
      uid_t   pw_uid;        /* user ID */
      gid_t   pw_gid;        /* group ID */
      char   *pw_gecos;      /* user information */
      char   *pw_dir;        /* home directory */
      char   *pw_shell;      /* shell program */
};

获取口令文件函数,分别是根据用户ID和用户名:

struct passwd *getpwuid(uid_t uid);   //根据用户ID
struct passwd *getpwnam(const char *name);  //根据用户名
查看整个口令文件,需要对口令文件进行遍历:

struct passwd *getpwent(void); //返回口令文件中的下一个记录项
void setpwent(void); //反绕文件,从文件头开始
void endpwent(void); //关闭文件

#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>

int main(){
    struct passwd *pwd;
    pwd = getpwnam("xkey");
    printf("username is: %s\n",pwd->pw_name);
    printf("userid is: %d\n",pwd->pw_uid);
    printf("groupid is: %d\n",pwd->pw_gid);
    printf("usergecos is: %s\n",pwd->pw_gecos);
    printf("usershell is: %s\n",pwd->pw_shell);
    printf("userhome is: %s\n",pwd->pw_dir);
    printf("userpasswd is: %s\n",pwd->pw_passwd);

    // /etc/passwd
    setpwent();
    while((pwd = getpwent()) != NULL){
        if(strcmp(pwd->pw_name,"root") == 0) {
            printf("username is: %s\n",pwd->pw_name);
            printf("userid is: %d\n",pwd->pw_uid);
            printf("groupid is: %d\n",pwd->pw_gid);
            printf("usergecos is: %s\n",pwd->pw_gecos);
            printf("usershell is: %s\n",pwd->pw_shell);
            printf("userhome is: %s\n",pwd->pw_dir);
            printf("userpasswd is: %s\n",pwd->pw_passwd);
            break;
        }
    }
    endpwent();
    return 0;
}

2、阴影文件
该文件中才实际存储用户加密后的密码,阴影文件在/etc/shadow

xkey:$6$EDjnGJ7f$H6Q27GTL3TY84UDJxHWcldHRtFD8xCGX4sU.bxz6GTTJz0Z8P33mE3O9ZU3PgiJpAnn81EwoRcz3M/04ZZxfk.:15775:0:99999:7:::

拿此帐号来说明,字段间以冒号分隔,

第一个字段是账户名;

第二个字段是加密后的密码;

第三个是最近一次修改密码的日期,15775是修改密码的日期与1970年1月1日的相距的天数;

第四个字段是密码不可以被改动的日期,若为0则表示可以随时更改;

第五个字段是密码需要重新更改的天数,99999就表示99999天后强制修改密码;

第六个字段是密码需要修改的提前警告的天数,7就表示在强制修改密码的日期到的前7天提醒用户

第七个字段是密码过期后可以宽限的天数

第八个字段是帐号的失效日期

第九个字段保留

这里通过第七和第八个字段的联合使用就能让一个帐号失效。

#include <shadow.h>中定义spwd数据结构:

struct spwd {
    char *sp_namp;
    char *sp_pwdp;
    long  sp_lstchg;
    long  sp_min;
    long  sp_max;
    long  sp_warn;
    long  sp_inact;
    long  sp_expire;
    unsigned long sp_flag;
};
函数:

struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
#include <shadow.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(){
    struct spwd *shd;
    shd = getspnam("xkey");
    printf("username is: %s\n",shd->sp_namp);
    printf("user passwd is: %s\n",shd->sp_pwdp);
    printf("user change pwd last: %d\n",shd->sp_lstchg);
    printf("user allowed change pwd min days: %d\n",shd->sp_min);
    printf("user must be change pwd days: %d\n",shd->sp_max);
    printf("warning days: %d\n",shd->sp_warn);
    printf("user account inactive days: %d\n",shd->sp_inact);
    printf("account expire days: %d\n",shd->sp_expire);
    
    //setspent();
    //getspent();
   // endspent();
}
此函数要在root权限下运行,因为/etc/shadow文件只有root有权限读取。

3、组文件

在/etc/group中,#include <grp.h>中定义了其数据结构

struct group {
    char   *gr_name;       /* group name */
    char   *gr_passwd;     /* group password */
    gid_t   gr_gid;        /* group ID */
    char  **gr_mem;        /* group members */
};
按照组名或组ID来获取组信息
struct group *getgrnam(const char *name);
struct group *getgrgid(gid_t gid);
搜索整个文件组函数:
struct group *getgrent(void);
void setgrent(void);
void endgrent(void);
这里需要指出的是,组密码不存储在/etc/group中,而是存储在/etc/gshadow中

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grp.h>

int main(){
    struct group *grp;
    grp = getgrnam("users");
    printf("group name: %s\n",grp->gr_name);
    printf("group id: %d\n",grp->gr_gid);
    printf("group pwd: %s\n",grp->gr_passwd);
    int len = sizeof(grp->gr_mem)/sizeof(char*);
    printf("%d	%d\n",sizeof(grp->gr_mem),sizeof(char*));
    char *p[]={"a","bc","cbf"};
    printf("%d\n",sizeof(p));
    printf("group members: %d\n",len);
    while(*grp->gr_mem!=NULL){
        printf("%s\n",*grp->gr_mem++);
        len --;
    }
    //setgrent();
    //getgrent();
    //endgrent();
    return 0;
}

4、其他数据文件

  其他数据文件  除了口令文件和组文件外,Linux也使用很多其他文件,一般情况下,这些文件都至少支持三个函数:
(1)get函数:读文件中的下一个记录项。
(2)set函数:打开相应的数据文件,然后反绕该文件。
(3)end函数:关闭系统文件。
存取系统数据文件的类似例程
说明 数据文件 头文件 结构 附加的关键字查找函数
口令 /etc/passwd <pwd.h> passwd getpwnam 、getpwuid
/etc/group <grp.h> group getpwnam、getpwuid
阴影 /etc/shadow <shadow.h> spwd getspnam
主机 /etc/hosts <netdb.h> hostent gethostbyname、gethostbyaddr
网络 /etc/networks <netdb.h> netent getnetbyname、getnetbyaddr
协议 /etc/protocols <netdb.h> protoent getprotobyname、getprotobyaddr
服务 /etc/services <netdb.h> servent getservbyname、getservbyad


5、系统标识

#include <utsname.h>

int uname(struct utsname *name)

数据结构

struct utsname {
  char sysname[];
  char nodename[];
  char release[];
  char version[];
  char machine[];
};
#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(){
    struct utsname name;
    uname(&name);
    printf("%s\n%s\n%s\n%s\n",name.sysname,name.nodename,name.release,name.version);
    printf("%s\n",name.machine);
    char host[32];
    gethostname(host,32);//得到主机名函数
    printf("%s\n",host);
    return 0;
}

6、时间和日期例程

UNIX中的基本时间服务是计算从1970年1月1日00:00:00以来的秒数,此秒数是通过数据类型time_t表示的。

#include <time.h>

time_t  time(time_t *calptr)

与time函数相比gettimeofday拥有更高的精度。

#include <sys/time.h>

int gettimeofday(struct timeval *tv, struct timezone *tz)

timeval结构体
struct  timeval{
    long  tv_sec;/*秒*/
    long  tv_usec;/*微妙*/
};
timezone结构体
struct  timezone{
    int tz_minuteswest;/*和greenwich(格林尼治)时间差了多少分钟*/
    int tz_dsttime;/*type of DST correction*/
}

时间转换图例:


a、日历时间转换为以年月日时分秒表示的时间,将该事件存放在tm结构体中

struct tm {
    int tm_sec;         /* seconds[0-60] */
    int tm_min;         /* minutes [0-59]*/
    int tm_hour;        /* hours [0-23]*/
    int tm_mday;        /* day of the month [1-31]*/
    int tm_mon;         /* month [0-11]*/
    int tm_year;        /* year since 1900*/
    int tm_wday;        /* day of the week [0-6]*/
    int tm_yday;        /* day in the year [0-365]*/
    int tm_isdst;       /* daylight saving time flags: < 0, 0 , > 0*/
};
#include<time.h>

struct tm *localtime(const time_t *calptr)

struct tm *gmtime(const time_t *calptr)

b、年月日时分秒表示的时间转换为日历时间

#include<time.h>

time_t mktime(struct tm *tmptr)

c、日历或tm时间转换为字符串

#include <time.h>

char *asctime(const struct tm *tmptr)

char *ctime(const time_t *calptr)

d、格式化输出到一个字符串

#include <time.h>

size_t strftime(char *buf, size_t size, const char *format,const struct tm *tmptr); //对tm进行格式化输出到一个字符串,具体的参数太多不列举

#include <time.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(){
    time_t now;
    now = time(&now);
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv,&tz);
    printf("%d\n",now);
    printf("seconds: %d, microseconds: %d\n",tv.tv_sec,tv.tv_usec);
    printf("Greenwich: %d, DST: %d\n",tz.tz_minuteswest,tz.tz_dsttime);
    char *str;
    str = ctime(&now);
    puts(str);
   
    struct tm *gmnow;
    struct tm *localnow;
    gmnow = gmtime(&now);
    localnow = localtime(&now);
    printf("%d\n",gmnow->tm_mday);
    printf("%d\n",localnow->tm_year+1900);
    printf("%d\n",gmnow->tm_yday);
    printf("%d\n",localnow->tm_isdst);

    struct tm mtime;
    mtime.tm_sec = 60;
    mtime.tm_min = 34;
    mtime.tm_hour = 12;
    mtime.tm_mday = 23;
    mtime.tm_mon = 3; 
    mtime.tm_year = 111;
    now = mktime(&mtime);
    printf("%d\n",now);
    puts(ctime(&now));
    puts(asctime(&mtime));

    char buf[64];
    memset(buf,0,sizeof(buf));
    strftime(buf,sizeof(buf),"%x %X, %B %A",&mtime);
    puts(buf);
    return 0;

}



  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值