pwd_grp.c 26 KB

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