pwd_grp.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. /*
  2. * Copyright (C) 2003 Manuel Novoa III
  3. *
  4. * Licensed under LGPL v2.1, see the file COPYING.LIB in this tarball for details.
  5. */
  6. /* Nov 6, 2003 Initial version.
  7. *
  8. * NOTE: This implementation is quite strict about requiring all
  9. * field seperators. It also does not allow leading whitespace
  10. * except when processing the numeric fields. glibc is more
  11. * lenient. See the various glibc difference comments below.
  12. *
  13. * TODO:
  14. * Move to dynamic allocation of (currently staticly allocated)
  15. * buffers; especially for the group-related functions since
  16. * large group member lists will cause error returns.
  17. *
  18. */
  19. #define setgroups __setgroups
  20. #define strtoul __strtoul
  21. #define rewind __rewind
  22. #define _GNU_SOURCE
  23. #include <features.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <stdint.h>
  27. #include <string.h>
  28. #include <stddef.h>
  29. #include <errno.h>
  30. #include <assert.h>
  31. #include <ctype.h>
  32. #include <pwd.h>
  33. #include <grp.h>
  34. #include <paths.h>
  35. #ifdef __HAS_SHADOW__
  36. #include <shadow.h>
  37. #endif
  38. #ifdef __UCLIBC_HAS_THREADS__
  39. #include <pthread.h>
  40. #endif
  41. extern int __getspnam_r (__const char *__name, struct spwd *__result_buf,
  42. char *__buffer, size_t __buflen,
  43. struct spwd **__result) attribute_hidden;
  44. extern int __getpwuid_r (__uid_t __uid,
  45. struct passwd *__restrict __resultbuf,
  46. char *__restrict __buffer, size_t __buflen,
  47. struct passwd **__restrict __result) attribute_hidden;
  48. /**********************************************************************/
  49. /* Sizes for staticly allocated buffers. */
  50. /* If you change these values, also change _SC_GETPW_R_SIZE_MAX and
  51. * _SC_GETGR_R_SIZE_MAX in libc/unistd/sysconf.c to match */
  52. #define PWD_BUFFER_SIZE 256
  53. #define GRP_BUFFER_SIZE 256
  54. /**********************************************************************/
  55. /* Prototypes for internal functions. */
  56. extern int __parsepwent(void *pw, char *line) attribute_hidden;
  57. extern int __parsegrent(void *gr, char *line) attribute_hidden;
  58. extern int __parsespent(void *sp, char *line) attribute_hidden;
  59. extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
  60. char *__restrict line_buff, size_t buflen, FILE *f) attribute_hidden;
  61. /**********************************************************************/
  62. /* For the various fget??ent_r funcs, return
  63. *
  64. * 0: success
  65. * ENOENT: end-of-file encountered
  66. * ERANGE: buflen too small
  67. * other error values possible. See __pgsreader.
  68. *
  69. * Also, *result == resultbuf on success and NULL on failure.
  70. *
  71. * NOTE: glibc difference - For the ENOENT case, glibc also sets errno.
  72. * We do not, as it really isn't an error if we reach the end-of-file.
  73. * Doing so is analogous to having fgetc() set errno on EOF.
  74. */
  75. /**********************************************************************/
  76. #ifdef L_fgetpwent_r
  77. int attribute_hidden __fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf,
  78. char *__restrict buffer, size_t buflen,
  79. struct passwd **__restrict result)
  80. {
  81. int rv;
  82. *result = NULL;
  83. if (!(rv = __pgsreader(__parsepwent, resultbuf, buffer, buflen, stream))) {
  84. *result = resultbuf;
  85. }
  86. return rv;
  87. }
  88. strong_alias(__fgetpwent_r,fgetpwent_r)
  89. #endif
  90. /**********************************************************************/
  91. #ifdef L_fgetgrent_r
  92. int attribute_hidden __fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf,
  93. char *__restrict buffer, size_t buflen,
  94. struct group **__restrict result)
  95. {
  96. int rv;
  97. *result = NULL;
  98. if (!(rv = __pgsreader(__parsegrent, resultbuf, buffer, buflen, stream))) {
  99. *result = resultbuf;
  100. }
  101. return rv;
  102. }
  103. strong_alias(__fgetgrent_r,fgetgrent_r)
  104. #endif
  105. /**********************************************************************/
  106. #ifdef L_fgetspent_r
  107. int attribute_hidden __fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf,
  108. char *__restrict buffer, size_t buflen,
  109. struct spwd **__restrict result)
  110. {
  111. int rv;
  112. *result = NULL;
  113. if (!(rv = __pgsreader(__parsespent, resultbuf, buffer, buflen, stream))) {
  114. *result = resultbuf;
  115. }
  116. return rv;
  117. }
  118. strong_alias(__fgetspent_r,fgetspent_r)
  119. #endif
  120. /**********************************************************************/
  121. /* For the various fget??ent funcs, return NULL on failure and a
  122. * pointer to the appropriate struct (staticly allocated) on success.
  123. */
  124. /**********************************************************************/
  125. #ifdef L_fgetpwent
  126. extern int __fgetpwent_r (FILE *__restrict __stream,
  127. struct passwd *__restrict __resultbuf,
  128. char *__restrict __buffer, size_t __buflen,
  129. struct passwd **__restrict __result) attribute_hidden;
  130. struct passwd *fgetpwent(FILE *stream)
  131. {
  132. static char buffer[PWD_BUFFER_SIZE];
  133. static struct passwd resultbuf;
  134. struct passwd *result;
  135. __fgetpwent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
  136. return result;
  137. }
  138. #endif
  139. /**********************************************************************/
  140. #ifdef L_fgetgrent
  141. extern int __fgetgrent_r (FILE *__restrict __stream,
  142. struct group *__restrict __resultbuf,
  143. char *__restrict __buffer, size_t __buflen,
  144. struct group **__restrict __result) attribute_hidden;
  145. struct group *fgetgrent(FILE *stream)
  146. {
  147. static char buffer[GRP_BUFFER_SIZE];
  148. static struct group resultbuf;
  149. struct group *result;
  150. __fgetgrent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
  151. return result;
  152. }
  153. #endif
  154. /**********************************************************************/
  155. #ifdef L_fgetspent
  156. extern int __fgetspent_r (FILE *__stream, struct spwd *__result_buf,
  157. char *__buffer, size_t __buflen,
  158. struct spwd **__result) attribute_hidden;
  159. struct spwd *fgetspent(FILE *stream)
  160. {
  161. static char buffer[PWD_BUFFER_SIZE];
  162. static struct spwd resultbuf;
  163. struct spwd *result;
  164. __fgetspent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
  165. return result;
  166. }
  167. #endif
  168. /**********************************************************************/
  169. #ifdef L_sgetspent_r
  170. int attribute_hidden __sgetspent_r(const char *string, struct spwd *result_buf,
  171. char *buffer, size_t buflen, struct spwd **result)
  172. {
  173. int rv = ERANGE;
  174. *result = NULL;
  175. if (buflen < PWD_BUFFER_SIZE) {
  176. DO_ERANGE:
  177. __set_errno(rv);
  178. goto DONE;
  179. }
  180. if (string != buffer) {
  181. if (__strlen(string) >= buflen) {
  182. goto DO_ERANGE;
  183. }
  184. __strcpy(buffer, string);
  185. }
  186. if (!(rv = __parsespent(result_buf, buffer))) {
  187. *result = result_buf;
  188. }
  189. DONE:
  190. return rv;
  191. }
  192. strong_alias(__sgetspent_r,sgetspent_r)
  193. #endif
  194. /**********************************************************************/
  195. #ifdef GETXXKEY_R_FUNC
  196. #error GETXXKEY_R_FUNC is already defined!
  197. #endif
  198. #ifdef L_getpwnam_r
  199. #define GETXXKEY_R_FUNC_HIDDEN __getpwnam_r
  200. #define GETXXKEY_R_FUNC getpwnam_r
  201. #define GETXXKEY_R_PARSER __parsepwent
  202. #define GETXXKEY_R_ENTTYPE struct passwd
  203. #define GETXXKEY_R_TEST(ENT) (!__strcmp((ENT)->pw_name, key))
  204. #define DO_GETXXKEY_R_KEYTYPE const char *__restrict
  205. #define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD
  206. #include "pwd_grp_internal.c"
  207. #endif
  208. #ifdef L_getgrnam_r
  209. #define GETXXKEY_R_FUNC_HIDDEN __getgrnam_r
  210. #define GETXXKEY_R_FUNC getgrnam_r
  211. #define GETXXKEY_R_PARSER __parsegrent
  212. #define GETXXKEY_R_ENTTYPE struct group
  213. #define GETXXKEY_R_TEST(ENT) (!__strcmp((ENT)->gr_name, key))
  214. #define DO_GETXXKEY_R_KEYTYPE const char *__restrict
  215. #define DO_GETXXKEY_R_PATHNAME _PATH_GROUP
  216. #include "pwd_grp_internal.c"
  217. #endif
  218. #ifdef L_getspnam_r
  219. #define GETXXKEY_R_FUNC_HIDDEN __getspnam_r
  220. #define GETXXKEY_R_FUNC getspnam_r
  221. #define GETXXKEY_R_PARSER __parsespent
  222. #define GETXXKEY_R_ENTTYPE struct spwd
  223. #define GETXXKEY_R_TEST(ENT) (!__strcmp((ENT)->sp_namp, key))
  224. #define DO_GETXXKEY_R_KEYTYPE const char *__restrict
  225. #define DO_GETXXKEY_R_PATHNAME _PATH_SHADOW
  226. #include "pwd_grp_internal.c"
  227. #endif
  228. #ifdef L_getpwuid_r
  229. #define GETXXKEY_R_FUNC_HIDDEN __getpwuid_r
  230. #define GETXXKEY_R_FUNC getpwuid_r
  231. #define GETXXKEY_R_PARSER __parsepwent
  232. #define GETXXKEY_R_ENTTYPE struct passwd
  233. #define GETXXKEY_R_TEST(ENT) ((ENT)->pw_uid == key)
  234. #define DO_GETXXKEY_R_KEYTYPE uid_t
  235. #define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD
  236. #include "pwd_grp_internal.c"
  237. #endif
  238. #ifdef L_getgrgid_r
  239. #define GETXXKEY_R_FUNC_HIDDEN __getgrgid_r
  240. #define GETXXKEY_R_FUNC getgrgid_r
  241. #define GETXXKEY_R_PARSER __parsegrent
  242. #define GETXXKEY_R_ENTTYPE struct group
  243. #define GETXXKEY_R_TEST(ENT) ((ENT)->gr_gid == key)
  244. #define DO_GETXXKEY_R_KEYTYPE gid_t
  245. #define DO_GETXXKEY_R_PATHNAME _PATH_GROUP
  246. #include "pwd_grp_internal.c"
  247. #endif
  248. /**********************************************************************/
  249. #ifdef L_getpwuid
  250. struct passwd *getpwuid(uid_t uid)
  251. {
  252. static char buffer[PWD_BUFFER_SIZE];
  253. static struct passwd resultbuf;
  254. struct passwd *result;
  255. __getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
  256. return result;
  257. }
  258. #endif
  259. /**********************************************************************/
  260. #ifdef L_getgrgid
  261. extern int __getgrgid_r (__gid_t __gid, struct group *__restrict __resultbuf,
  262. char *__restrict __buffer, size_t __buflen,
  263. struct group **__restrict __result) attribute_hidden;
  264. struct group *getgrgid(gid_t gid)
  265. {
  266. static char buffer[GRP_BUFFER_SIZE];
  267. static struct group resultbuf;
  268. struct group *result;
  269. __getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result);
  270. return result;
  271. }
  272. #endif
  273. /**********************************************************************/
  274. #ifdef L_getspuid_r
  275. /* This function is non-standard and is currently not built. It seems
  276. * to have been created as a reentrant version of the non-standard
  277. * functions getspuid. Why getspuid was added, I do not know. */
  278. int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf,
  279. char *__restrict buffer, size_t buflen,
  280. struct spwd **__restrict result)
  281. {
  282. int rv;
  283. struct passwd *pp;
  284. struct passwd password;
  285. char pwd_buff[PWD_BUFFER_SIZE];
  286. *result = NULL;
  287. if (!(rv = __getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp))) {
  288. rv = __getspnam_r(password.pw_name, resultbuf, buffer, buflen, result);
  289. }
  290. return rv;
  291. }
  292. #endif
  293. /**********************************************************************/
  294. #ifdef L_getspuid
  295. /* This function is non-standard and is currently not built.
  296. * Why it was added, I do not know. */
  297. struct spwd *getspuid(uid_t uid)
  298. {
  299. static char buffer[PWD_BUFFER_SIZE];
  300. static struct spwd resultbuf;
  301. struct spwd *result;
  302. getspuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
  303. return result;
  304. }
  305. #endif
  306. /**********************************************************************/
  307. #ifdef L_getpwnam
  308. extern int __getpwnam_r (__const char *__restrict __name,
  309. struct passwd *__restrict __resultbuf,
  310. char *__restrict __buffer, size_t __buflen,
  311. struct passwd **__restrict __result) attribute_hidden;
  312. struct passwd *getpwnam(const char *name)
  313. {
  314. static char buffer[PWD_BUFFER_SIZE];
  315. static struct passwd resultbuf;
  316. struct passwd *result;
  317. __getpwnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
  318. return result;
  319. }
  320. #endif
  321. /**********************************************************************/
  322. #ifdef L_getgrnam
  323. extern int __getgrnam_r (__const char *__restrict __name,
  324. struct group *__restrict __resultbuf,
  325. char *__restrict __buffer, size_t __buflen,
  326. struct group **__restrict __result) attribute_hidden;
  327. struct group *getgrnam(const char *name)
  328. {
  329. static char buffer[GRP_BUFFER_SIZE];
  330. static struct group resultbuf;
  331. struct group *result;
  332. __getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
  333. return result;
  334. }
  335. #endif
  336. /**********************************************************************/
  337. #ifdef L_getspnam
  338. struct spwd *getspnam(const char *name)
  339. {
  340. static char buffer[PWD_BUFFER_SIZE];
  341. static struct spwd resultbuf;
  342. struct spwd *result;
  343. __getspnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
  344. return result;
  345. }
  346. #endif
  347. /**********************************************************************/
  348. #ifdef L_getpw
  349. int getpw(uid_t uid, char *buf)
  350. {
  351. struct passwd resultbuf;
  352. struct passwd *result;
  353. char buffer[PWD_BUFFER_SIZE];
  354. if (!buf) {
  355. __set_errno(EINVAL);
  356. } else if (!__getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) {
  357. if (__sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n",
  358. resultbuf.pw_name, resultbuf.pw_passwd,
  359. (unsigned long)(resultbuf.pw_uid),
  360. (unsigned long)(resultbuf.pw_gid),
  361. resultbuf.pw_gecos, resultbuf.pw_dir,
  362. resultbuf.pw_shell) >= 0
  363. ) {
  364. return 0;
  365. }
  366. }
  367. return -1;
  368. }
  369. #endif
  370. /**********************************************************************/
  371. #if defined(L_getpwent_r) || defined(L_getgrent_r) || defined(L_getspent_r)
  372. #ifdef __UCLIBC_HAS_THREADS__
  373. # include <pthread.h>
  374. static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
  375. #endif
  376. #define LOCK __pthread_mutex_lock(&mylock)
  377. #define UNLOCK __pthread_mutex_unlock(&mylock)
  378. #endif
  379. #ifdef L_getpwent_r
  380. static FILE *pwf /*= NULL*/;
  381. void setpwent(void)
  382. {
  383. LOCK;
  384. if (pwf) {
  385. rewind(pwf);
  386. }
  387. UNLOCK;
  388. }
  389. void endpwent(void)
  390. {
  391. LOCK;
  392. if (pwf) {
  393. fclose(pwf);
  394. pwf = NULL;
  395. }
  396. UNLOCK;
  397. }
  398. int attribute_hidden __getpwent_r(struct passwd *__restrict resultbuf,
  399. char *__restrict buffer, size_t buflen,
  400. struct passwd **__restrict result)
  401. {
  402. int rv;
  403. LOCK;
  404. *result = NULL; /* In case of error... */
  405. if (!pwf) {
  406. if (!(pwf = fopen(_PATH_PASSWD, "r"))) {
  407. rv = errno;
  408. goto ERR;
  409. }
  410. __STDIO_SET_USER_LOCKING(pwf);
  411. }
  412. if (!(rv = __pgsreader(__parsepwent, resultbuf,
  413. buffer, buflen, pwf))) {
  414. *result = resultbuf;
  415. }
  416. ERR:
  417. UNLOCK;
  418. return rv;
  419. }
  420. strong_alias(__getpwent_r,getpwent_r)
  421. #endif
  422. /**********************************************************************/
  423. #ifdef L_getgrent_r
  424. static FILE *grf /*= NULL*/;
  425. void setgrent(void)
  426. {
  427. LOCK;
  428. if (grf) {
  429. rewind(grf);
  430. }
  431. UNLOCK;
  432. }
  433. void endgrent(void)
  434. {
  435. LOCK;
  436. if (grf) {
  437. fclose(grf);
  438. grf = NULL;
  439. }
  440. UNLOCK;
  441. }
  442. int attribute_hidden __getgrent_r(struct group *__restrict resultbuf,
  443. char *__restrict buffer, size_t buflen,
  444. struct group **__restrict result)
  445. {
  446. int rv;
  447. LOCK;
  448. *result = NULL; /* In case of error... */
  449. if (!grf) {
  450. if (!(grf = fopen(_PATH_GROUP, "r"))) {
  451. rv = errno;
  452. goto ERR;
  453. }
  454. __STDIO_SET_USER_LOCKING(grf);
  455. }
  456. if (!(rv = __pgsreader(__parsegrent, resultbuf,
  457. buffer, buflen, grf))) {
  458. *result = resultbuf;
  459. }
  460. ERR:
  461. UNLOCK;
  462. return rv;
  463. }
  464. strong_alias(__getgrent_r,getgrent_r)
  465. #endif
  466. /**********************************************************************/
  467. #ifdef L_getspent_r
  468. static FILE *spf /*= NULL*/;
  469. void setspent(void)
  470. {
  471. LOCK;
  472. if (spf) {
  473. rewind(spf);
  474. }
  475. UNLOCK;
  476. }
  477. void endspent(void)
  478. {
  479. LOCK;
  480. if (spf) {
  481. fclose(spf);
  482. spf = NULL;
  483. }
  484. UNLOCK;
  485. }
  486. int attribute_hidden __getspent_r(struct spwd *resultbuf, char *buffer,
  487. size_t buflen, struct spwd **result)
  488. {
  489. int rv;
  490. LOCK;
  491. *result = NULL; /* In case of error... */
  492. if (!spf) {
  493. if (!(spf = fopen(_PATH_SHADOW, "r"))) {
  494. rv = errno;
  495. goto ERR;
  496. }
  497. __STDIO_SET_USER_LOCKING(spf);
  498. }
  499. if (!(rv = __pgsreader(__parsespent, resultbuf,
  500. buffer, buflen, spf))) {
  501. *result = resultbuf;
  502. }
  503. ERR:
  504. UNLOCK;
  505. return rv;
  506. }
  507. strong_alias(__getspent_r,getspent_r)
  508. #endif
  509. /**********************************************************************/
  510. #ifdef L_getpwent
  511. extern int __getpwent_r (struct passwd *__restrict __resultbuf,
  512. char *__restrict __buffer, size_t __buflen,
  513. struct passwd **__restrict __result) attribute_hidden;
  514. struct passwd *getpwent(void)
  515. {
  516. static char line_buff[PWD_BUFFER_SIZE];
  517. static struct passwd pwd;
  518. struct passwd *result;
  519. __getpwent_r(&pwd, line_buff, sizeof(line_buff), &result);
  520. return result;
  521. }
  522. #endif
  523. /**********************************************************************/
  524. #ifdef L_getgrent
  525. extern int __getgrent_r (struct group *__restrict __resultbuf,
  526. char *__restrict __buffer, size_t __buflen,
  527. struct group **__restrict __result) attribute_hidden;
  528. struct group *getgrent(void)
  529. {
  530. static char line_buff[GRP_BUFFER_SIZE];
  531. static struct group gr;
  532. struct group *result;
  533. __getgrent_r(&gr, line_buff, sizeof(line_buff), &result);
  534. return result;
  535. }
  536. #endif
  537. /**********************************************************************/
  538. #ifdef L_getspent
  539. extern int __getspent_r (struct spwd *__result_buf, char *__buffer,
  540. size_t __buflen, struct spwd **__result) attribute_hidden;
  541. struct spwd *getspent(void)
  542. {
  543. static char line_buff[PWD_BUFFER_SIZE];
  544. static struct spwd spwd;
  545. struct spwd *result;
  546. __getspent_r(&spwd, line_buff, sizeof(line_buff), &result);
  547. return result;
  548. }
  549. #endif
  550. /**********************************************************************/
  551. #ifdef L_sgetspent
  552. extern int __sgetspent_r (__const char *__string, struct spwd *__result_buf,
  553. char *__buffer, size_t __buflen,
  554. struct spwd **__result) attribute_hidden;
  555. struct spwd *sgetspent(const char *string)
  556. {
  557. static char line_buff[PWD_BUFFER_SIZE];
  558. static struct spwd spwd;
  559. struct spwd *result;
  560. __sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result);
  561. return result;
  562. }
  563. #endif
  564. /**********************************************************************/
  565. #ifdef L_initgroups
  566. int initgroups(const char *user, gid_t gid)
  567. {
  568. FILE *grfile;
  569. gid_t *group_list;
  570. int num_groups, rv;
  571. char **m;
  572. struct group group;
  573. char buff[PWD_BUFFER_SIZE];
  574. rv = -1;
  575. /* We alloc space for 8 gids at a time. */
  576. if (((group_list = (gid_t *) malloc(8*sizeof(gid_t *))) != NULL)
  577. && ((grfile = fopen(_PATH_GROUP, "r")) != NULL)
  578. ) {
  579. __STDIO_SET_USER_LOCKING(grfile);
  580. *group_list = gid;
  581. num_groups = 1;
  582. while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) {
  583. assert(group.gr_mem); /* Must have at least a NULL terminator. */
  584. if (group.gr_gid != gid) {
  585. for (m=group.gr_mem ; *m ; m++) {
  586. if (!__strcmp(*m, user)) {
  587. if (!(num_groups & 7)) {
  588. gid_t *tmp = (gid_t *)
  589. realloc(group_list,
  590. (num_groups+8) * sizeof(gid_t *));
  591. if (!tmp) {
  592. rv = -1;
  593. goto DO_CLOSE;
  594. }
  595. group_list = tmp;
  596. }
  597. group_list[num_groups++] = group.gr_gid;
  598. break;
  599. }
  600. }
  601. }
  602. }
  603. rv = setgroups(num_groups, group_list);
  604. DO_CLOSE:
  605. fclose(grfile);
  606. }
  607. /* group_list will be NULL if initial malloc failed, which may trigger
  608. * warnings from various malloc debuggers. */
  609. free(group_list);
  610. return rv;
  611. }
  612. #endif
  613. /**********************************************************************/
  614. #ifdef L_putpwent
  615. int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
  616. {
  617. int rv = -1;
  618. if (!p || !f) {
  619. __set_errno(EINVAL);
  620. } else {
  621. /* No extra thread locking is needed above what fprintf does. */
  622. if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",
  623. p->pw_name, p->pw_passwd,
  624. (unsigned long)(p->pw_uid),
  625. (unsigned long)(p->pw_gid),
  626. p->pw_gecos, p->pw_dir, p->pw_shell) >= 0
  627. ) {
  628. rv = 0;
  629. }
  630. }
  631. return rv;
  632. }
  633. #endif
  634. /**********************************************************************/
  635. #ifdef L_putgrent
  636. int putgrent(const struct group *__restrict p, FILE *__restrict f)
  637. {
  638. static const char format[] = ",%s";
  639. char **m;
  640. const char *fmt;
  641. int rv = -1;
  642. __STDIO_AUTO_THREADLOCK_VAR;
  643. if (!p || !f) { /* Sigh... glibc checks. */
  644. __set_errno(EINVAL);
  645. } else {
  646. __STDIO_AUTO_THREADLOCK(f);
  647. if (fprintf(f, "%s:%s:%lu:",
  648. p->gr_name, p->gr_passwd,
  649. (unsigned long)(p->gr_gid)) >= 0
  650. ) {
  651. fmt = format + 1;
  652. assert(p->gr_mem);
  653. m = p->gr_mem;
  654. do {
  655. if (!*m) {
  656. if (fputc_unlocked('\n', f) >= 0) {
  657. rv = 0;
  658. }
  659. break;
  660. }
  661. if (fprintf(f, fmt, *m) < 0) {
  662. break;
  663. }
  664. ++m;
  665. fmt = format;
  666. } while (1);
  667. }
  668. __STDIO_AUTO_THREADUNLOCK(f);
  669. }
  670. return rv;
  671. }
  672. #endif
  673. /**********************************************************************/
  674. #ifdef L_putspent
  675. static const unsigned char _sp_off[] = {
  676. offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */
  677. offsetof(struct spwd, sp_min), /* 3 - not a char ptr */
  678. offsetof(struct spwd, sp_max), /* 4 - not a char ptr */
  679. offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */
  680. offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */
  681. offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */
  682. };
  683. int putspent(const struct spwd *p, FILE *stream)
  684. {
  685. static const char ld_format[] = "%ld:";
  686. const char *f;
  687. long int x;
  688. int i;
  689. int rv = -1;
  690. __STDIO_AUTO_THREADLOCK_VAR;
  691. /* Unlike putpwent and putgrent, glibc does not check the args. */
  692. __STDIO_AUTO_THREADLOCK(stream);
  693. if (fprintf(stream, "%s:%s:", p->sp_namp,
  694. (p->sp_pwdp ? p->sp_pwdp : "")) < 0
  695. ) {
  696. goto DO_UNLOCK;
  697. }
  698. for (i=0 ; i < sizeof(_sp_off) ; i++) {
  699. f = ld_format;
  700. if ((x = *(const long int *)(((const char *) p) + _sp_off[i])) == -1) {
  701. f += 3;
  702. }
  703. if (fprintf(stream, f, x) < 0) {
  704. goto DO_UNLOCK;
  705. }
  706. }
  707. if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) {
  708. goto DO_UNLOCK;
  709. }
  710. if (fputc_unlocked('\n', stream) > 0) {
  711. rv = 0;
  712. }
  713. DO_UNLOCK:
  714. __STDIO_AUTO_THREADUNLOCK(stream);
  715. return rv;
  716. }
  717. #endif
  718. /**********************************************************************/
  719. /* Internal uClibc functions. */
  720. /**********************************************************************/
  721. #ifdef L___parsepwent
  722. static const unsigned char pw_off[] = {
  723. offsetof(struct passwd, pw_name), /* 0 */
  724. offsetof(struct passwd, pw_passwd), /* 1 */
  725. offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */
  726. offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */
  727. offsetof(struct passwd, pw_gecos), /* 4 */
  728. offsetof(struct passwd, pw_dir), /* 5 */
  729. offsetof(struct passwd, pw_shell) /* 6 */
  730. };
  731. int attribute_hidden __parsepwent(void *data, char *line)
  732. {
  733. char *endptr;
  734. char *p;
  735. int i;
  736. i = 0;
  737. do {
  738. p = ((char *) ((struct passwd *) data)) + pw_off[i];
  739. if ((i & 6) ^ 2) { /* i!=2 and i!=3 */
  740. *((char **) p) = line;
  741. if (i==6) {
  742. return 0;
  743. }
  744. /* NOTE: glibc difference - glibc allows omission of
  745. * ':' seperators after the gid field if all remaining
  746. * entries are empty. We require all separators. */
  747. if (!(line = __strchr(line, ':'))) {
  748. break;
  749. }
  750. } else {
  751. unsigned long t = strtoul(line, &endptr, 10);
  752. /* Make sure we had at least one digit, and that the
  753. * failing char is the next field seperator ':'. See
  754. * glibc difference note above. */
  755. /* TODO: Also check for leading whitespace? */
  756. if ((endptr == line) || (*endptr != ':')) {
  757. break;
  758. }
  759. line = endptr;
  760. if (i & 1) { /* i == 3 -- gid */
  761. *((gid_t *) p) = t;
  762. } else { /* i == 2 -- uid */
  763. *((uid_t *) p) = t;
  764. }
  765. }
  766. *line++ = 0;
  767. ++i;
  768. } while (1);
  769. return -1;
  770. }
  771. #endif
  772. /**********************************************************************/
  773. #ifdef L___parsegrent
  774. static const unsigned char gr_off[] = {
  775. offsetof(struct group, gr_name), /* 0 */
  776. offsetof(struct group, gr_passwd), /* 1 */
  777. offsetof(struct group, gr_gid) /* 2 - not a char ptr */
  778. };
  779. int attribute_hidden __parsegrent(void *data, char *line)
  780. {
  781. char *endptr;
  782. char *p;
  783. int i;
  784. char **members;
  785. char *end_of_buf;
  786. end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */
  787. i = 0;
  788. do {
  789. p = ((char *) ((struct group *) data)) + gr_off[i];
  790. if (i < 2) {
  791. *((char **) p) = line;
  792. if (!(line = __strchr(line, ':'))) {
  793. break;
  794. }
  795. *line++ = 0;
  796. ++i;
  797. } else {
  798. *((gid_t *) p) = strtoul(line, &endptr, 10);
  799. /* NOTE: glibc difference - glibc allows omission of the
  800. * trailing colon when there is no member list. We treat
  801. * this as an error. */
  802. /* Make sure we had at least one digit, and that the
  803. * failing char is the next field seperator ':'. See
  804. * glibc difference note above. */
  805. if ((endptr == line) || (*endptr != ':')) {
  806. break;
  807. }
  808. i = 1; /* Count terminating NULL ptr. */
  809. p = endptr;
  810. if (p[1]) { /* We have a member list to process. */
  811. /* Overwrite the last ':' with a ',' before counting.
  812. * This allows us to test for initial ',' and adds
  813. * one ',' so that the ',' count equals the member
  814. * count. */
  815. *p = ',';
  816. do {
  817. /* NOTE: glibc difference - glibc allows and trims leading
  818. * (but not trailing) space. We treat this as an error. */
  819. /* NOTE: glibc difference - glibc allows consecutive and
  820. * trailing commas, and ignores "empty string" users. We
  821. * treat this as an error. */
  822. if (*p == ',') {
  823. ++i;
  824. *p = 0; /* nul-terminate each member string. */
  825. if (!*++p || (*p == ',') || isspace(*p)) {
  826. goto ERR;
  827. }
  828. }
  829. } while (*++p);
  830. }
  831. /* Now align (p+1), rounding up. */
  832. /* Assumes sizeof(char **) is a power of 2. */
  833. members = (char **)( (((intptr_t) p) + sizeof(char **))
  834. & ~((intptr_t)(sizeof(char **) - 1)) );
  835. if (((char *)(members + i)) > end_of_buf) { /* No space. */
  836. break;
  837. }
  838. ((struct group *) data)->gr_mem = members;
  839. if (--i) {
  840. p = endptr; /* Pointing to char prior to first member. */
  841. do {
  842. *members++ = ++p;
  843. if (!--i) break;
  844. while (*++p) {}
  845. } while (1);
  846. }
  847. *members = NULL;
  848. return 0;
  849. }
  850. } while (1);
  851. ERR:
  852. return -1;
  853. }
  854. #endif
  855. /**********************************************************************/
  856. #ifdef L___parsespent
  857. static const unsigned char sp_off[] = {
  858. offsetof(struct spwd, sp_namp), /* 0 */
  859. offsetof(struct spwd, sp_pwdp), /* 1 */
  860. offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */
  861. offsetof(struct spwd, sp_min), /* 3 - not a char ptr */
  862. offsetof(struct spwd, sp_max), /* 4 - not a char ptr */
  863. offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */
  864. offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */
  865. offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */
  866. offsetof(struct spwd, sp_flag) /* 8 - not a char ptr */
  867. };
  868. int attribute_hidden __parsespent(void *data, char * line)
  869. {
  870. char *endptr;
  871. char *p;
  872. int i;
  873. i = 0;
  874. do {
  875. p = ((char *) ((struct spwd *) data)) + sp_off[i];
  876. if (i < 2) {
  877. *((char **) p) = line;
  878. if (!(line = __strchr(line, ':'))) {
  879. break;
  880. }
  881. } else {
  882. #if 0
  883. if (i==5) { /* Support for old format. */
  884. while (isspace(*line)) ++line; /* glibc eats space here. */
  885. if (!*line) {
  886. ((struct spwd *) data)->sp_warn = -1;
  887. ((struct spwd *) data)->sp_inact = -1;
  888. ((struct spwd *) data)->sp_expire = -1;
  889. ((struct spwd *) data)->sp_flag = ~0UL;
  890. return 0;
  891. }
  892. }
  893. #endif
  894. *((long *) p) = (long) strtoul(line, &endptr, 10);
  895. if (endptr == line) {
  896. *((long *) p) = ((i != 8) ? -1L : ((long)(~0UL)));
  897. }
  898. line = endptr;
  899. if (i == 8) {
  900. if (!*endptr) {
  901. return 0;
  902. }
  903. break;
  904. }
  905. if (*endptr != ':') {
  906. break;
  907. }
  908. }
  909. *line++ = 0;
  910. ++i;
  911. } while (1);
  912. return EINVAL;
  913. }
  914. #endif
  915. /**********************************************************************/
  916. #ifdef L___pgsreader
  917. /* Reads until if EOF, or until if finds a line which fits in the buffer
  918. * and for which the parser function succeeds.
  919. *
  920. * Returns 0 on success and ENOENT for end-of-file (glibc concession).
  921. */
  922. int attribute_hidden __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
  923. char *__restrict line_buff, size_t buflen, FILE *f)
  924. {
  925. int line_len;
  926. int skip;
  927. int rv = ERANGE;
  928. __STDIO_AUTO_THREADLOCK_VAR;
  929. if (buflen < PWD_BUFFER_SIZE) {
  930. __set_errno(rv);
  931. } else {
  932. __STDIO_AUTO_THREADLOCK(f);
  933. skip = 0;
  934. do {
  935. if (!fgets_unlocked(line_buff, buflen, f)) {
  936. if (feof_unlocked(f)) {
  937. rv = ENOENT;
  938. }
  939. break;
  940. }
  941. line_len = __strlen(line_buff) - 1; /* strlen() must be > 0. */
  942. if (line_buff[line_len] == '\n') {
  943. line_buff[line_len] = 0;
  944. } else if (line_len + 2 == buflen) { /* line too long */
  945. ++skip;
  946. continue;
  947. }
  948. if (skip) {
  949. --skip;
  950. continue;
  951. }
  952. /* NOTE: glibc difference - glibc strips leading whitespace from
  953. * records. We do not allow leading whitespace. */
  954. /* Skip empty lines, comment lines, and lines with leading
  955. * whitespace. */
  956. if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) {
  957. if (__parserfunc == __parsegrent) { /* Do evil group hack. */
  958. /* The group entry parsing function needs to know where
  959. * the end of the buffer is so that it can construct the
  960. * group member ptr table. */
  961. ((struct group *) data)->gr_name = line_buff + buflen;
  962. }
  963. if (!__parserfunc(data, line_buff)) {
  964. rv = 0;
  965. break;
  966. }
  967. }
  968. } while (1);
  969. __STDIO_AUTO_THREADUNLOCK(f);
  970. }
  971. return rv;
  972. }
  973. #endif
  974. /**********************************************************************/