当前位置: 首页 > news >正文

Unix环境高级编程(四)数据系统文件和信息

  本章主要介绍了Unix系统的正常运行要使用的与系统有关的数据文件和信息。如:口令文件,阴影文件、组文件、附加组、系统标识、时间和日期历程。

  口令文件,即Unix系统用户数据库,存储在/etc/passwd中,是一个ASCII文件,包含的字段信息在<pwd.h>定义的passwd数据结构中。  

  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); //关闭文件

  可以用getpwent来实现getpwuid和getpwnam函数。写个程序查看root用户的相关信息及查看口令文件中所有用户的用户名,程序如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <pwd.h>
 5 
 6 int main() 7 { 8 struct passwd *ppwd; 9 struct passwd *ptr; 10 //获取root用户信息 11 ppwd = getpwnam("root"); 12 if(ppwd == NULL) 13 { 14 perror("getpwnam() error"); 15 exit(-1); 16 } 17 printf("root user information as follow:\n"); 18 printf("user_name is: %s\n",ppwd->pw_name); 19 printf("user_passwd is: %s\n",ppwd->pw_passwd); 20 printf("user_uid is: %d\n",ppwd->pw_uid); 21 printf("user_gid is: %d\n",ppwd->pw_gid); 22 printf("user_gecos is: %s\n",ppwd->pw_gecos); 23 printf("user_dir is: %s\n",ppwd->pw_dir); 24 printf("user_shell is: %s\n",ppwd->pw_shell); 25 printf("*****************************\n"); 26 //反转口令文件,从文件头开始 27 setpwent(); 28 printf("Print all user name:\n"); 29 //遍历读取口令文件 30 while((ptr = getpwent())!= NULL) 31 { 32 printf("%s\t",ptr->pw_name); 33 } 34 putchar('\n'); 35 //关闭口令文件 36 endpwent(); 37 return 0; 38 }

测试结果如下:

  阴影文件,存放加密口令,至少包含有用户名和加密口令。类似于口令文件,Unix在<shadow.h>都文件中针对阴影文件也提供类似的操作函数,但是只有超级用户(root)才能调用访问阴影文件的函数。阴影文件位于/etc/shadow文件中,文件结构及操作函数如下:

struct spwd {
    char *sp_namp;     /* Login name */
    char *sp_pwdp;     /* Encrypted password */
    long  sp_lstchg;   /* Date of last change (measured in days since 1970-01-01 00:00:00 +0000 (UTC)) */
    long  sp_min;      /* Min # of days between changes */
    long  sp_max;      /* Max # of days between changes */
    long  sp_warn;     /* # of days before password expire to warn user to change it */
    long  sp_inact;    /* # of days after password expire until account is disabled */
    long  sp_expire;   /* Date when account expires (measured in days since 1970-01-01 00:00:00 +0000 (UTC)) */
    unsigned long sp_flag;  /* Reserved */
};

struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
写个程序查看root用户的加密口令及所有用户的用户名及加密口令如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <shadow.h>
 5 
 6 int main()  7 {  8 struct spwd *pspwd;  9 struct passwd *ptr; 10 pspwd = getspnam("root"); 11 if(pspwd == NULL) 12  { 13 perror("getspnam() error"); 14 exit(-1); 15  } 16 printf("root user information as follow:\n"); 17 printf("user_name is: %s\n",pspwd->sp_namp); 18 printf("user_passwd is: %s\n",pspwd->sp_pwdp); 19 printf("*****************************\n"); 20  setspent(); 21 while((pspwd = getspent()) != NULL) 22  { 23 printf("user_name is: %s\n",pspwd->sp_namp); 24 printf("user_passwd is: %s\n",pspwd->sp_pwdp); 25  } 26  endspent(); 27 return 0; 28 }

只能在超级用户下运行此程序,在普用户下提升权限不够。执行结果如下所示:

组文件,即组数据库文件,存储在/etc/group中,结构及操作函数包含在<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 */
};

struct group *getgrnam(const char *name);
struct group *getgrgid(gid_t gid);
搜索整个文件组函数:
struct group *getgrent(void);
void setgrent(void);
void endgrent(void);
写个程序,打印出组id为0的组名称及遍历整个组文件,输出组名称及组id。程序如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <grp.h>
 5 #include <errno.h>
 6  7 int main()  8 {  9 struct group *pgrg; 10 struct group *ptr; 11 gid_t gid = 0; 12 char *username = NULL; 13 //根据gid进行查询 14 pgrg = getgrgid(gid); 15 if(pgrg == NULL) 16  { 17 perror("getgrgid() error"); 18 exit(-1); 19  } 20 printf("group name is: %s\n",pgrg->gr_name); 21 printf("group passwd is: %s\n",pgrg->gr_passwd); 22 printf("group gid is: %d\n",pgrg->gr_gid); 23  setgrent(); 24 //遍历整个组文件 25 while((ptr = getgrent()) != NULL) 26  { 27 printf("group name is: %s\t",ptr->gr_name); 28 printf("group gid is: %d\n",ptr->gr_gid); 29  } 30  endgrent(); 31 return 0; 32 }

程序执行结果如下所示:

  附加组,一个用户可以属于多个组,这样可以参加多项工作,优点是不必显式地经常更改组。用户登录时候,系统按照口令文件记录项中的数值组ID,赋给实际组ID,可以在任何时候通过newgrp更改组ID。为了获取和设置附加组ID,提供操作函数如下:

int getgroups(int size, gid_t list[]);  //将各个附加组ID填写到数组grouplist中
int setgroups(size_t size, const gid_t *list); //由超级用户调用,以便为调用进程设置附加组ID表
int initgroups(const char *user, gid_t group); //调用setgroups,确定其组的成员关系

  其他数据文件  除了口令文件和组文件外,Linux也使用很多其他文件,一般情况下,这些文件都至少支持三个函数:
(1)get函数:读文件中的下一个记录项。
(2)set函数:将文件偏移量设置到文件起始处。
(3)end函数:关闭系统文件。
  如果该文件支持关键字检索,例如口令文件支持基于用户名和用户ID的检索,因此实现了接口getpwnam和getpwuid函数,就会支持相应的函数。

 

存取系统数据文件的类似例程
说明数据文件头文件结构附加的关键字查找函数
口令/etc/passwd<pwd.h>passwdgetpwnam 、getpwuid
/etc/group<grp.h>groupgetpwnam、getpwuid
阴影/etc/shadow<shadow.h>spwdgetspnam
主机/etc/hosts<netdb.h>hostentgethostbyname、gethostbyaddr
网络/etc/networks<netdb.h>netentgetnetbyname、getnetbyaddr
协议/etc/protocols<netdb.h>protoentgetprotobyname、getprotobyaddr
服务/etc/services<netdb.h>serventgetservbyname、getservbyad

  系统标识,uname函数返回与当前主机和操作系统有关的信息,函数字在<sys/utsname.h>头文件中定义。utsname结构信息和操作函数如下:

  struct utsname {
      char sysname[];    /* Operating system name (e.g., "Linux") */
      char nodename[];   /* Name within "some implementation-defined network" */
      char release[];    /* OS release (e.g., "2.6.28") */
      char version[];    /* OS version */
      char machine[];    /* Hardware identifier */
   #ifdef _GNU_SOURCE
      char domainname[]; /* NIS or YP domain name */
    #endif
  };

  int uname(struct utsname *buf);

写个程序获取本机当前主机和操作系统信息,程序如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/utsname.h>
 5 #include <errno.h>
 6  7 int main()  8 {  9 struct utsname name; 10 if(uname(&name) == -1) 11  { 12 perror("uname() error"); 13 exit(-1); 14  } 15 printf("system name is: %s\n",name.sysname); 16 printf("node name is: %s\n",name.nodename); 17 printf("release is: %s\n",name.release); 18 printf("version is: %s\n",name.version); 19 printf("machine is: %s\n",name.machine); 20 return 0; 21 }

 

程序执行结果如下:

  时间和日期,Unix内核提供的基本时间服务是计算自国际标准时间公元1970年1月1日00:00:00以来经过的秒数,基本数据类型是time_t,称为日历时间,包括时间和日期,将时间和日期作为一个量值进行保存。类型定义如下:

#ifndef __TIME_T
#define __TIME_T     /* 避免重复定义 time_t */
typedef long     time_t;    /* 时间值time_t 为长整型的别名*/
#endif
相关操作函数有:
#include <time.h>

time_t time(time_t *t);  //返回当前时间及日期

#include <sys/time.h>

int gettimeofday(struct timeval *tv, struct timezone *tz); //相比time提供更高的分辨率,微妙级

int settimeofday(const struct timeval *tv, const struct timezone *tz);

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};
struct timezone {
    int tz_minuteswest;     /* minutes west of Greenwich */
    int tz_dsttime;         /* type of DST correction */
};

取得了这种以秒计的整型时间后,通常调用另外一个时间函数将其转化为人们可读的时间和日期。时间的结构及操作函数有:

struct tm {
    int tm_sec;         /* seconds */
    int tm_min;         /* minutes */
    int tm_hour;        /* hours */
    int tm_mday;        /* day of the month */
    int tm_mon;         /* month */
    int tm_year;        /* year */
    int tm_wday;        /* day of the week */
    int tm_yday;        /* day in the year */
    int tm_isdst;       /* daylight saving time */
};

char *asctime(const struct tm *tm);
char *ctime(const time_t *timep);
struct tm *gmtime(const time_t *timep);  //转换为国际标准时间
struct tm *localtime(const time_t *timep); //转换为本地实际
time_t mktime(struct tm *tm);
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm); //对tm进行格式化输出到一个字符串
函数之间的关系如下图:

写一个程序巩固时间函数,程序如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <time.h>
 5 #include <errno.h>
 6 #include <string.h>  7  8 int main()  9 { 10  time_t now; 11 struct tm *ptime; 12 char *ptstr; 13 char timebuf[100]; 14 memset(timebuf,0,100); 15 //获取时间,秒数 16 now = time(&now); 17 printf("Global time is:\n"); 18 //转化为国际时间 19 ptime = gmtime(&now); 20 ptime->tm_year += 1900; 21 ptime->tm_mon += 1; 22 printf("%d-%d-%d %d:%d:%d\n",ptime->tm_year,ptime->tm_mon,ptime->tm_mday, 23 ptime->tm_hour,ptime->tm_min,ptime->tm_sec); 24 printf("Local time is:\n"); 25 //转化为本地时间 26 ptime = localtime(&now); 27 ptime->tm_year += 1900; 28 ptime->tm_mon += 1; 29 printf("%d-%d-%d %d:%d:%d\n",ptime->tm_year,ptime->tm_mon,ptime->tm_mday, 30 ptime->tm_hour,ptime->tm_min,ptime->tm_sec); 31 //将tm结构转换为字符串 32 ptstr = asctime(ptime); 33 printf("tm time stirng is: %s",ptstr); 34 //将time_t类型转换为字符串 35 ptstr = ctime(&now); 36 printf("time_t time string is: %s",ptstr); 37 //date 格式化输出时间 38 strftime(timebuf,100,"%YYear %mMonth %dDay %A %X",ptime); 39 printf("time buf is:%s\n",timebuf); 40 return 0; 41 }

程序执行结果如下所示:

 总结:加深对Unix的系统数据文件及时间日期的认识,能够调用系统函数获取系统相关数据。

转载于:https://www.cnblogs.com/alantu2018/p/8465969.html

相关文章:

  • 算法初级之二
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • 人民日报发声,区块链成“兵家必争之地”,或成“国家战略”
  • iOS下JS与OC互相调用(八)--Cordova详解+实战
  • itextsharp display:none无效的bug
  • SaaS型平台产品的POS营销经营策略
  • BeanUtils工具类的使用
  • Linux配置虚拟网站主机
  • 阿里云ECS服务器安装jdk
  • 素材哪里找?一个好的图库
  • POJ1631 LIS模板
  • pyqt5 QGraphicsView颜色动画问题(不兼容,运行不了动画)
  • Java Eclipse和MyEclipse快捷键
  • linux 使用fdisk分区扩容,看介绍命令(未完)
  • 微信小程序—智能小蜜(基于智能语义解析olami开放平台)
  • 网络传输文件的问题
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Computed property XXX was assigned to but it has no setter
  • iOS 系统授权开发
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • RxJS: 简单入门
  • SSH 免密登录
  • 创建一种深思熟虑的文化
  • 从重复到重用
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 两列自适应布局方案整理
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 区块链技术特点之去中心化特性
  • 设计模式 开闭原则
  • 王永庆:技术创新改变教育未来
  • 用Python写一份独特的元宵节祝福
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 在weex里面使用chart图表
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​马来语翻译中文去哪比较好?
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (Python第六天)文件处理
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (强烈推荐)移动端音视频从零到上手(上)
  • (一)Dubbo快速入门、介绍、使用
  • (转)大型网站架构演变和知识体系
  • (转)一些感悟
  • (轉貼) UML中文FAQ (OO) (UML)
  • .NET CLR基本术语
  • .net core 连接数据库,通过数据库生成Modell
  • .net core控制台应用程序初识
  • .Net IE10 _doPostBack 未定义
  • .NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 WeakDictionary)
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .NetCore项目nginx发布
  • .Net的DataSet直接与SQL2005交互
  • .NET关于 跳过SSL中遇到的问题