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、其他数据文件
说明 | 数据文件 | 头文件 | 结构 | 附加的关键字查找函数 |
口令 | /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;
}