在比較新版本的 Library 當中,其實都已經逐漸不支援 cuserid 這個 function call 了。如果花點時間看一下 man page 的說明,可以發現當中有這麼一段,讓人相當 surprise 的文字:
The cuserid() function is made obsolete by getpwuid(3).
真是神奇的講法。既然人家預設不支援了,當然我們要想辦法求生存。
其實拆穿了 cuserid() 的真面目之後,可以發現,cuserid() 他作的事情不過就是這些:
首先調用 getlogin(),若 getlogin() 返回 NULL 指標,再調用 getpwuid(getuid())。
既然知道他的真面目是這樣,所以,對於程式當中用到 cuserid() 這個 function call 的地方,就可以用一連串的 system call 取代了。以下就是用來取代 cuserid() 的程式,喜歡的,可以直接拿去用。
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#define USERNAME_MAX_LENGTH (128)
char *cuserid(char *s)
{
static char *id = NULL;
static int allocid = 0;
struct passwd *pw;
if (id != NULL && allocid == 1)
{
free(id);
}
id = getlogin();
if (id == NULL)
{
if ((pw = getpwuid(getuid())) != NULL)
{
id = (char *) malloc(USERNAME_MAX_LENGTH);
allocid = 1;
strlcpy(id, pw->pw_name, USERNAME_MAX_LENGTH);
}
else
{
return NULL;
}
}
if (s != NULL)
{
strlcpy(s, id, strlen(id) + 1);
}
return id;
}
可能有人好奇會問,為啥不把抓到的 userid 保留下來,下次直接回傳就好了,不需要再跑一次複雜的 system call 流程?這個建議滿好的,但是如果,這之程式會變換身份的話,也就是在程式中有可能呼叫 seteuid() 等等的變身 system call 的話,身份其實是會變的。
比較標準的作法,其實應該 follow 真正的新式流程:
if ((pw = getpwuid(geteuid())) != NULL)
{
strlcpy(foo, pw->pw_name, sizeof(foo));
}
這個才是比較符合實際的新式呼叫方式。