pwd_grp.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178
  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. __STDIO_AUTO_THREADLOCK_VAR;
  639. if (!p || !f) { /* Sigh... glibc checks. */
  640. __set_errno(EINVAL);
  641. } else {
  642. __STDIO_AUTO_THREADLOCK(f);
  643. if (fprintf(f, "%s:%s:%lu:",
  644. p->gr_name, p->gr_passwd,
  645. (unsigned long)(p->gr_gid)) >= 0
  646. ) {
  647. fmt = format + 1;
  648. assert(p->gr_mem);
  649. m = p->gr_mem;
  650. do {
  651. if (!*m) {
  652. if (fputc_unlocked('\n', f) >= 0) {
  653. rv = 0;
  654. }
  655. break;
  656. }
  657. if (fprintf(f, fmt, *m) < 0) {
  658. break;
  659. }
  660. ++m;
  661. fmt = format;
  662. } while (1);
  663. }
  664. __STDIO_AUTO_THREADUNLOCK(f);
  665. }
  666. return rv;
  667. }
  668. #endif
  669. /**********************************************************************/
  670. #ifdef L_putspent
  671. static const unsigned char sp_off[] = {
  672. offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */
  673. offsetof(struct spwd, sp_min), /* 3 - not a char ptr */
  674. offsetof(struct spwd, sp_max), /* 4 - not a char ptr */
  675. offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */
  676. offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */
  677. offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */
  678. };
  679. int putspent(const struct spwd *p, FILE *stream)
  680. {
  681. static const char ld_format[] = "%ld:";
  682. const char *f;
  683. long int x;
  684. int i;
  685. int rv = -1;
  686. __STDIO_AUTO_THREADLOCK_VAR;
  687. /* Unlike putpwent and putgrent, glibc does not check the args. */
  688. __STDIO_AUTO_THREADLOCK(stream);
  689. if (fprintf(stream, "%s:%s:", p->sp_namp,
  690. (p->sp_pwdp ? p->sp_pwdp : "")) < 0
  691. ) {
  692. goto DO_UNLOCK;
  693. }
  694. for (i=0 ; i < sizeof(sp_off) ; i++) {
  695. f = ld_format;
  696. if ((x = *(const long int *)(((const char *) p) + sp_off[i])) == -1) {
  697. f += 3;
  698. }
  699. if (fprintf(stream, f, x) < 0) {
  700. goto DO_UNLOCK;
  701. }
  702. }
  703. if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) {
  704. goto DO_UNLOCK;
  705. }
  706. if (fputc_unlocked('\n', stream) > 0) {
  707. rv = 0;
  708. }
  709. DO_UNLOCK:
  710. __STDIO_AUTO_THREADUNLOCK(stream);
  711. return rv;
  712. }
  713. #endif
  714. /**********************************************************************/
  715. /* Internal uClibc functions. */
  716. /**********************************************************************/
  717. #ifdef L___parsepwent
  718. static const unsigned char pw_off[] = {
  719. offsetof(struct passwd, pw_name), /* 0 */
  720. offsetof(struct passwd, pw_passwd), /* 1 */
  721. offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */
  722. offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */
  723. offsetof(struct passwd, pw_gecos), /* 4 */
  724. offsetof(struct passwd, pw_dir), /* 5 */
  725. offsetof(struct passwd, pw_shell) /* 6 */
  726. };
  727. int __parsepwent(void *data, char *line)
  728. {
  729. char *endptr;
  730. char *p;
  731. int i;
  732. i = 0;
  733. do {
  734. p = ((char *) ((struct passwd *) data)) + pw_off[i];
  735. if ((i & 6) ^ 2) { /* i!=2 and i!=3 */
  736. *((char **) p) = line;
  737. if (i==6) {
  738. return 0;
  739. }
  740. /* NOTE: glibc difference - glibc allows omission of
  741. * ':' seperators after the gid field if all remaining
  742. * entries are empty. We require all separators. */
  743. if (!(line = strchr(line, ':'))) {
  744. break;
  745. }
  746. } else {
  747. unsigned long t = strtoul(line, &endptr, 10);
  748. /* Make sure we had at least one digit, and that the
  749. * failing char is the next field seperator ':'. See
  750. * glibc difference note above. */
  751. /* TODO: Also check for leading whitespace? */
  752. if ((endptr == line) || (*endptr != ':')) {
  753. break;
  754. }
  755. line = endptr;
  756. if (i & 1) { /* i == 3 -- gid */
  757. *((gid_t *) p) = t;
  758. } else { /* i == 2 -- uid */
  759. *((uid_t *) p) = t;
  760. }
  761. }
  762. *line++ = 0;
  763. ++i;
  764. } while (1);
  765. return -1;
  766. }
  767. #endif
  768. /**********************************************************************/
  769. #ifdef L___parsegrent
  770. static const unsigned char gr_off[] = {
  771. offsetof(struct group, gr_name), /* 0 */
  772. offsetof(struct group, gr_passwd), /* 1 */
  773. offsetof(struct group, gr_gid) /* 2 - not a char ptr */
  774. };
  775. int __parsegrent(void *data, char *line)
  776. {
  777. char *endptr;
  778. char *p;
  779. int i;
  780. char **members;
  781. char *end_of_buf;
  782. end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */
  783. i = 0;
  784. do {
  785. p = ((char *) ((struct group *) data)) + gr_off[i];
  786. if (i < 2) {
  787. *((char **) p) = line;
  788. if (!(line = strchr(line, ':'))) {
  789. break;
  790. }
  791. *line++ = 0;
  792. ++i;
  793. } else {
  794. *((gid_t *) p) = strtoul(line, &endptr, 10);
  795. /* NOTE: glibc difference - glibc allows omission of the
  796. * trailing colon when there is no member list. We treat
  797. * this as an error. */
  798. /* Make sure we had at least one digit, and that the
  799. * failing char is the next field seperator ':'. See
  800. * glibc difference note above. */
  801. if ((endptr == line) || (*endptr != ':')) {
  802. break;
  803. }
  804. i = 1; /* Count terminating NULL ptr. */
  805. p = endptr;
  806. if (p[1]) { /* We have a member list to process. */
  807. /* Overwrite the last ':' with a ',' before counting.
  808. * This allows us to test for initial ',' and adds
  809. * one ',' so that the ',' count equals the member
  810. * count. */
  811. *p = ',';
  812. do {
  813. /* NOTE: glibc difference - glibc allows and trims leading
  814. * (but not trailing) space. We treat this as an error. */
  815. /* NOTE: glibc difference - glibc allows consecutive and
  816. * trailing commas, and ignores "empty string" users. We
  817. * treat this as an error. */
  818. if (*p == ',') {
  819. ++i;
  820. *p = 0; /* nul-terminate each member string. */
  821. if (!*++p || (*p == ',') || isspace(*p)) {
  822. goto ERR;
  823. }
  824. }
  825. } while (*++p);
  826. }
  827. /* Now align (p+1), rounding up. */
  828. /* Assumes sizeof(char **) is a power of 2. */
  829. members = (char **)( (((intptr_t) p) + sizeof(char **))
  830. & ~((intptr_t)(sizeof(char **) - 1)) );
  831. if (((char *)(members + i)) > end_of_buf) { /* No space. */
  832. break;
  833. }
  834. ((struct group *) data)->gr_mem = members;
  835. if (--i) {
  836. p = endptr; /* Pointing to char prior to first member. */
  837. do {
  838. *members++ = ++p;
  839. if (!--i) break;
  840. while (*++p) {}
  841. } while (1);
  842. }
  843. *members = NULL;
  844. return 0;
  845. }
  846. } while (1);
  847. ERR:
  848. return -1;
  849. }
  850. #endif
  851. /**********************************************************************/
  852. #ifdef L___parsespent
  853. static const unsigned char sp_off[] = {
  854. offsetof(struct spwd, sp_namp), /* 0 */
  855. offsetof(struct spwd, sp_pwdp), /* 1 */
  856. offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */
  857. offsetof(struct spwd, sp_min), /* 3 - not a char ptr */
  858. offsetof(struct spwd, sp_max), /* 4 - not a char ptr */
  859. offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */
  860. offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */
  861. offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */
  862. offsetof(struct spwd, sp_flag) /* 8 - not a char ptr */
  863. };
  864. int __parsespent(void *data, char * line)
  865. {
  866. char *endptr;
  867. char *p;
  868. int i;
  869. i = 0;
  870. do {
  871. p = ((char *) ((struct spwd *) data)) + sp_off[i];
  872. if (i < 2) {
  873. *((char **) p) = line;
  874. if (!(line = strchr(line, ':'))) {
  875. break;
  876. }
  877. } else {
  878. #if 0
  879. if (i==5) { /* Support for old format. */
  880. while (isspace(*line)) ++line; /* glibc eats space here. */
  881. if (!*line) {
  882. ((struct spwd *) data)->sp_warn = -1;
  883. ((struct spwd *) data)->sp_inact = -1;
  884. ((struct spwd *) data)->sp_expire = -1;
  885. ((struct spwd *) data)->sp_flag = ~0UL;
  886. return 0;
  887. }
  888. }
  889. #endif
  890. *((long *) p) = (long) strtoul(line, &endptr, 10);
  891. if (endptr == line) {
  892. *((long *) p) = ((i != 8) ? -1L : ((long)(~0UL)));
  893. }
  894. line = endptr;
  895. if (i == 8) {
  896. if (!*endptr) {
  897. return 0;
  898. }
  899. break;
  900. }
  901. if (*endptr != ':') {
  902. break;
  903. }
  904. }
  905. *line++ = 0;
  906. ++i;
  907. } while (1);
  908. return EINVAL;
  909. }
  910. #endif
  911. /**********************************************************************/
  912. #ifdef L___pgsreader
  913. /* Reads until if EOF, or until if finds a line which fits in the buffer
  914. * and for which the parser function succeeds.
  915. *
  916. * Returns 0 on success and ENOENT for end-of-file (glibc concession).
  917. */
  918. int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
  919. char *__restrict line_buff, size_t buflen, FILE *f)
  920. {
  921. int line_len;
  922. int skip;
  923. int rv = ERANGE;
  924. __STDIO_AUTO_THREADLOCK_VAR;
  925. if (buflen < PWD_BUFFER_SIZE) {
  926. __set_errno(rv);
  927. } else {
  928. __STDIO_AUTO_THREADLOCK(f);
  929. skip = 0;
  930. do {
  931. if (!fgets_unlocked(line_buff, buflen, f)) {
  932. if (feof_unlocked(f)) {
  933. rv = ENOENT;
  934. }
  935. break;
  936. }
  937. line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */
  938. if (line_buff[line_len] == '\n') {
  939. line_buff[line_len] = 0;
  940. } else if (line_len + 2 == buflen) { /* line too long */
  941. ++skip;
  942. continue;
  943. }
  944. if (skip) {
  945. --skip;
  946. continue;
  947. }
  948. /* NOTE: glibc difference - glibc strips leading whitespace from
  949. * records. We do not allow leading whitespace. */
  950. /* Skip empty lines, comment lines, and lines with leading
  951. * whitespace. */
  952. if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) {
  953. if (__parserfunc == __parsegrent) { /* Do evil group hack. */
  954. /* The group entry parsing function needs to know where
  955. * the end of the buffer is so that it can construct the
  956. * group member ptr table. */
  957. ((struct group *) data)->gr_name = line_buff + buflen;
  958. }
  959. if (!__parserfunc(data, line_buff)) {
  960. rv = 0;
  961. break;
  962. }
  963. }
  964. } while (1);
  965. __STDIO_AUTO_THREADUNLOCK(f);
  966. }
  967. return rv;
  968. }
  969. #endif
  970. /**********************************************************************/