pwd_grp.c 28 KB

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