近来读书,做些笔记,来年好翻翻。
本文所使用的操作系统为 CentOS7.0,如果不想装双系统的可以装虚拟机,可以参考这里:
http://blog.csdn.net/alex_my/article/details/38142229
system data files and infomation
1 password file
终端上输入cat /etc/passwd
可以看见很多相关信息。
也可以通过以下函数:
#include <sys/types.h>
#include <pwd.h>
struct passwd* getpwnam(const char* name);
struct passwd* getpwuid(uid_t uid);
int getpwnam_r(const char* name, struct passwd* pwd, char* buf, size_t buflen, struct passwd** result);
int getpwuid_r(uid_t uid, struct passwd* pwd, char* buf, size_t buflen, struct passwd** result);
结构体passwd(<pwd.h>):
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 */
};
如果不能理解每个成员的意思,可以通过man 5 passwd查阅。
getpwuid和getpwnam的程序用例:
#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
static void PrintfPwd(const passwd* pwdInfo)
{
if(!pwdInfo)
return;
printf("name: \t%s\n", pwdInfo->pw_name);
printf("passwd: \t%s\n", pwdInfo->pw_passwd);
printf("uid: \t%d\n", pwdInfo->pw_uid);
printf("gid: \t%d\n", pwdInfo->pw_gid);
printf("gecos: \t%s\n", pwdInfo->pw_gecos);
printf("dir: \t%s\n", pwdInfo->pw_dir);
printf("shell: \t\%s\n", pwdInfo->pw_shell);
}
int main(int argc, char* argv[])
{
printf("test getpwuid: \n");
uid_t uid = getuid();
printf("uid: %d\n", uid);
// test getpwuid
struct passwd* pwdInfo = getpwuid(uid);
if(!pwdInfo)
return 1;
PrintfPwd(pwdInfo);
// test getpwnam
printf("\n\ntest getpwnam: \n");
struct passwd* pwdInfo2 = getpwnam(pwdInfo->pw_name);
PrintfPwd(pwdInfo2);
return 0;
}
getpwuid_r用例:
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>
#include <errno.h>
static void PrintfPwd(const passwd* pwdInfo)
{
if(!pwdInfo)
return;
printf("name: \t%s\n", pwdInfo->pw_name);
printf("passwd: \t%s\n", pwdInfo->pw_passwd);
printf("uid: \t%d\n", pwdInfo->pw_uid);
printf("gid: \t%d\n", pwdInfo->pw_gid);
printf("gecos: \t%s\n", pwdInfo->pw_gecos);
printf("dir: \t%s\n", pwdInfo->pw_dir);
printf("shell: \t\%s\n", pwdInfo->pw_shell);
}
int main(int argc, char* argv[])
{
uid_t uid = getuid();
size_t len = sysconf(_SC_GETPW_R_SIZE_MAX);
if(len == -1)
len = 16384;
char* buffer = new char[len];
if(!buffer)
{
printf("buffer create failed. error[%d]\n", errno);
return 1;
}
struct passwd pwd;
struct passwd* result = NULL;
int ret = getpwuid_r(uid, &pwd, buffer, len, &result);
if(!result)
{
printf("getpwuid failed. ret[%d]\n", ret);
return 1;
}
printf("----------pwd---------- \n");
PrintfPwd(&pwd);
printf("\n\n----------result----------\n");
PrintfPwd(result);
printf("\n\n----------buffer----------\n");
printf("buffer: %s\n", buffer);
return 0;
}
以下三个函数与读取/etc/passwd相关:
#include <sys/types.h>
#include <pwd.h>
struct passwd* getpwent(void);
void setpwent(void);
void endpwent(void);
getpwent: 获取passwd文件中的一个口令,严格的说,是获取下一个口令
setpwent: 将获取口令重置到第一个
endpwent: 关闭由getpwent打开的文件
程序用例:
#include <stdio.h>
#include <pwd.h>
int main(int argc, char* argv[])
{
// 为了测试方便,最多只打印10个口令信息
struct passwd* pwd;
// 设置从头开始读取
setpwent();
int n = 0;
while((pwd = getpwent()) != NULL)
{
printf("name: %s \t uid: %d\n", pwd->pw_name, pwd->pw_uid);
if(++n >= 10)
break;
}
endpwent();
return 0;
}
2 shadow passwords
看着名字就知道它藏的好深。
有以下函数可以操作这个文件:
#include <shadow.h>
struct spwd* getspnam(const char* name);
struct spwd* getspent(void);
void setspent(void);
void endspent(void);
struct spwd*fgetspent(FILE* fp);
struct spwd*sgetspent(const char* s);
int putspent(struct spwd* p, FILE* fp);
int lckpwdf(void);
int ulckpwdf(void);
/* GNU extension */
#include <shadow.h>
int getspent_r(struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp);
int getspnam_r(const char* name, struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp);
int fgetspent_r(FILE* fp, struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp);
int sgetspent_r(const char* s, struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp);
其中的struct spwd定义如下:
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 expires
to warn user to change it */
long sp_inact; /* # of days after password expires
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 */
};
getspnam程序用例:
#include <stdio.h>
#include <shadow.h>
#include <errno.h>
#include <string.h>
int main(int argc, char* argv[])
{
struct spwd* pwd = getspnam("alex_my");
if(!pwd)
{
printf("getspnam failed, error: [%d] [%s]\n", errno, strerror(errno));
return 1;
}
printf("name: %s\t password: %s\n", pwd->sp_namp, pwd->sp_pwdp);
return 0;
}
如果在普通账号下运行,就会发生错误,因为读取文件的权限不够。
3 group file
位于/etc/group
有以下函数可以操作:
#include <sys/types.h>
#include <grp.h>
struct group *getgrnam(const char *name);
struct group *getgrgid(gid_t gid);
int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
int getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
用法可以参考passwd file
用户在登陆的时候,就会获取到group ID,属于某一个group,可以通过命令来改变所属的组。但总体来说不方便。
于是,出现了supplementary group IDs(附加组ID)。
4 获取本地主机名
#include <unistd.h>
int gethostname(char* name, size_t namelen);
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
char name[256] = { 0 };
gethostname(name, sizeof(name));
printf("name: %s\n", name);
return 0;
}