1 // RUN: %clangxx %s -o %t && %run %t 2 3 #include <assert.h> 4 #include <grp.h> 5 #include <memory> 6 #include <pwd.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 std::unique_ptr<char []> any_group; 12 const int N = 123456; 13 14 void Check(const char *str) { 15 if (!str) 16 return; 17 assert(strlen(str) != N); 18 } 19 20 void Check(const passwd *result) { 21 Check(result->pw_name); 22 Check(result->pw_passwd); 23 assert(result->pw_uid != N); 24 assert(result->pw_gid != N); 25 #if !defined(__ANDROID__) 26 Check(result->pw_gecos); 27 #endif 28 Check(result->pw_dir); 29 30 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 31 assert(result->pw_change != N); 32 Check(result->pw_class); 33 assert(result->pw_expire != N); 34 #endif 35 36 #if defined(__FreeBSD__) 37 assert(result->pw_fields != N); 38 #endif 39 40 // SunOS also has pw_age and pw_comment which are documented as unused. 41 } 42 43 void Check(const group *result) { 44 Check(result->gr_name); 45 Check(result->gr_passwd); 46 assert(result->gr_gid != N); 47 for (char **mem = result->gr_mem; *mem; ++mem) 48 Check(*mem); 49 if (!any_group) { 50 auto length = strlen(result->gr_name); 51 any_group.reset(new char[length + 1]); 52 memcpy(any_group.get(), result->gr_name, length + 1); 53 } 54 } 55 56 template <class T, class Fn, class... Args> 57 void test(Fn f, Args... args) { 58 T *result = f(args...); 59 Check(result); 60 } 61 62 template <class T, class Fn, class... Args> 63 void test_r(Fn f, Args... args) { 64 T gr; 65 T *result; 66 char buff[10000]; 67 assert(!f(args..., &gr, buff, sizeof(buff), &result)); 68 Check(&gr); 69 Check(result); 70 } 71 72 int main(int argc, const char *argv[]) { 73 test<passwd>(&getpwuid, 0); 74 test<passwd>(&getpwnam, "root"); 75 test<group>(&getgrgid, 0); 76 test<group>(&getgrnam, any_group.get()); 77 78 #if !defined(__ANDROID__) 79 setpwent(); 80 test<passwd>(&getpwent); 81 setgrent(); 82 test<group>(&getgrent); 83 84 #if !defined(__APPLE__) && !(defined(__sun__) && defined(__svr4__)) 85 setpwent(); 86 test_r<passwd>(&getpwent_r); 87 setgrent(); 88 test_r<group>(&getgrent_r); 89 #endif 90 91 test_r<passwd>(&getpwuid_r, 0); 92 test_r<passwd>(&getpwnam_r, "root"); 93 94 test_r<group>(&getgrgid_r, 0); 95 test_r<group>(&getgrnam_r, any_group.get()); 96 97 #if defined(__linux__) 98 auto pwd_file = [] { 99 return std::unique_ptr<FILE, decltype(&fclose)>(fopen("/etc/passwd", "r"), 100 &fclose); 101 }; 102 auto gr_file = [] { 103 return std::unique_ptr<FILE, decltype(&fclose)>(fopen("/etc/group", "r"), 104 &fclose); 105 }; 106 test<passwd>(&fgetpwent, pwd_file().get()); 107 test<group>(&fgetgrent, gr_file().get()); 108 test_r<passwd>(&fgetpwent_r, pwd_file().get()); 109 test_r<group>(&fgetgrent_r, gr_file().get()); 110 #endif 111 112 #endif // __ANDROID__ 113 114 return 0; 115 } 116