pwd_grp.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  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 staticly 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 <string.h>
  25. #include <stddef.h>
  26. #include <errno.h>
  27. #include <assert.h>
  28. #include <ctype.h>
  29. #include <pwd.h>
  30. #include <grp.h>
  31. #include <paths.h>
  32. #ifdef __HAS_SHADOW__
  33. #include <shadow.h>
  34. #endif
  35. #ifdef __UCLIBC_HAS_THREADS__
  36. #include <pthread.h>
  37. #endif
  38. libc_hidden_proto(strchr)
  39. libc_hidden_proto(strcmp)
  40. libc_hidden_proto(strcpy)
  41. libc_hidden_proto(strlen)
  42. libc_hidden_proto(setgroups)
  43. libc_hidden_proto(strtoul)
  44. libc_hidden_proto(rewind)
  45. libc_hidden_proto(fgets_unlocked)
  46. libc_hidden_proto(__fputc_unlocked)
  47. libc_hidden_proto(sprintf)
  48. libc_hidden_proto(fopen)
  49. libc_hidden_proto(fclose)
  50. libc_hidden_proto(fprintf)
  51. #ifdef __UCLIBC_HAS_XLOCALE__
  52. libc_hidden_proto(__ctype_b_loc)
  53. #else
  54. libc_hidden_proto(__ctype_b)
  55. #endif
  56. /**********************************************************************/
  57. /* Sizes for staticly allocated buffers. */
  58. /* If you change these values, also change _SC_GETPW_R_SIZE_MAX and
  59. * _SC_GETGR_R_SIZE_MAX in libc/unistd/sysconf.c to match */
  60. #define PWD_BUFFER_SIZE 256
  61. #define GRP_BUFFER_SIZE 256
  62. /**********************************************************************/
  63. /* Prototypes for internal functions. */
  64. extern int __parsepwent(void *pw, char *line) attribute_hidden;
  65. extern int __parsegrent(void *gr, char *line) attribute_hidden;
  66. extern int __parsespent(void *sp, char *line) attribute_hidden;
  67. extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
  68. char *__restrict line_buff, size_t buflen, FILE *f) attribute_hidden;
  69. /**********************************************************************/
  70. /* For the various fget??ent_r funcs, return
  71. *
  72. * 0: success
  73. * ENOENT: end-of-file encountered
  74. * ERANGE: buflen too small
  75. * other error values possible. See __pgsreader.
  76. *
  77. * Also, *result == resultbuf on success and NULL on failure.
  78. *
  79. * NOTE: glibc difference - For the ENOENT case, glibc also sets errno.
  80. * We do not, as it really isn't an error if we reach the end-of-file.
  81. * Doing so is analogous to having fgetc() set errno on EOF.
  82. */
  83. /**********************************************************************/
  84. #ifdef L_fgetpwent_r
  85. libc_hidden_proto(fgetpwent_r)
  86. int fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf,
  87. char *__restrict buffer, size_t buflen,
  88. struct passwd **__restrict result)
  89. {
  90. int rv;
  91. *result = NULL;
  92. if (!(rv = __pgsreader(__parsepwent, resultbuf, buffer, buflen, stream))) {
  93. *result = resultbuf;
  94. }
  95. return rv;
  96. }
  97. libc_hidden_def(fgetpwent_r)
  98. #endif
  99. /**********************************************************************/
  100. #ifdef L_fgetgrent_r
  101. libc_hidden_proto(fgetgrent_r)
  102. int fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf,
  103. char *__restrict buffer, size_t buflen,
  104. struct group **__restrict result)
  105. {
  106. int rv;
  107. *result = NULL;
  108. if (!(rv = __pgsreader(__parsegrent, resultbuf, buffer, buflen, stream))) {
  109. *result = resultbuf;
  110. }
  111. return rv;
  112. }
  113. libc_hidden_def(fgetgrent_r)
  114. #endif
  115. /**********************************************************************/
  116. #ifdef L_fgetspent_r
  117. libc_hidden_proto(fgetspent_r)
  118. int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf,
  119. char *__restrict buffer, size_t buflen,
  120. struct spwd **__restrict result)
  121. {
  122. int rv;
  123. *result = NULL;
  124. if (!(rv = __pgsreader(__parsespent, resultbuf, buffer, buflen, stream))) {
  125. *result = resultbuf;
  126. }
  127. return rv;
  128. }
  129. libc_hidden_def(fgetspent_r)
  130. #endif
  131. /**********************************************************************/
  132. /* For the various fget??ent funcs, return NULL on failure and a
  133. * pointer to the appropriate struct (staticly allocated) on success.
  134. */
  135. /**********************************************************************/
  136. #ifdef L_fgetpwent
  137. libc_hidden_proto(fgetpwent_r)
  138. struct passwd *fgetpwent(FILE *stream)
  139. {
  140. static char buffer[PWD_BUFFER_SIZE];
  141. static struct passwd resultbuf;
  142. struct passwd *result;
  143. fgetpwent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
  144. return result;
  145. }
  146. #endif
  147. /**********************************************************************/
  148. #ifdef L_fgetgrent
  149. libc_hidden_proto(fgetgrent_r)
  150. struct group *fgetgrent(FILE *stream)
  151. {
  152. static char buffer[GRP_BUFFER_SIZE];
  153. static struct group resultbuf;
  154. struct group *result;
  155. fgetgrent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
  156. return result;
  157. }
  158. #endif
  159. /**********************************************************************/
  160. #ifdef L_fgetspent
  161. libc_hidden_proto(fgetspent_r)
  162. struct spwd *fgetspent(FILE *stream)
  163. {
  164. static char buffer[PWD_BUFFER_SIZE];
  165. static struct spwd resultbuf;
  166. struct spwd *result;
  167. fgetspent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
  168. return result;
  169. }
  170. #endif
  171. /**********************************************************************/
  172. #ifdef L_sgetspent_r
  173. libc_hidden_proto(sgetspent_r)
  174. int sgetspent_r(const char *string, struct spwd *result_buf,
  175. char *buffer, size_t buflen, struct spwd **result)
  176. {
  177. int rv = ERANGE;
  178. *result = NULL;
  179. if (buflen < PWD_BUFFER_SIZE) {
  180. DO_ERANGE:
  181. __set_errno(rv);
  182. goto DONE;
  183. }
  184. if (string != buffer) {
  185. if (strlen(string) >= buflen) {
  186. goto DO_ERANGE;
  187. }
  188. strcpy(buffer, string);
  189. }
  190. if (!(rv = __parsespent(result_buf, buffer))) {
  191. *result = result_buf;
  192. }
  193. DONE:
  194. return rv;
  195. }
  196. libc_hidden_def(sgetspent_r)
  197. #endif
  198. /**********************************************************************/
  199. #ifdef GETXXKEY_R_FUNC
  200. #error GETXXKEY_R_FUNC is already defined!
  201. #endif
  202. #ifdef L_getpwnam_r
  203. #define GETXXKEY_R_FUNC getpwnam_r
  204. #define GETXXKEY_R_PARSER __parsepwent
  205. #define GETXXKEY_R_ENTTYPE struct passwd
  206. #define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->pw_name, key))
  207. #define DO_GETXXKEY_R_KEYTYPE const char *__restrict
  208. #define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD
  209. #include "pwd_grp_internal.c"
  210. #endif
  211. #ifdef L_getgrnam_r
  212. #define GETXXKEY_R_FUNC getgrnam_r
  213. #define GETXXKEY_R_PARSER __parsegrent
  214. #define GETXXKEY_R_ENTTYPE struct group
  215. #define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->gr_name, key))
  216. #define DO_GETXXKEY_R_KEYTYPE const char *__restrict
  217. #define DO_GETXXKEY_R_PATHNAME _PATH_GROUP
  218. #include "pwd_grp_internal.c"
  219. #endif
  220. #ifdef L_getspnam_r
  221. #define GETXXKEY_R_FUNC getspnam_r
  222. #define GETXXKEY_R_PARSER __parsespent
  223. #define GETXXKEY_R_ENTTYPE struct spwd
  224. #define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->sp_namp, key))
  225. #define DO_GETXXKEY_R_KEYTYPE const char *__restrict
  226. #define DO_GETXXKEY_R_PATHNAME _PATH_SHADOW
  227. #include "pwd_grp_internal.c"
  228. #endif
  229. #ifdef L_getpwuid_r
  230. #define GETXXKEY_R_FUNC getpwuid_r
  231. #define GETXXKEY_R_PARSER __parsepwent
  232. #define GETXXKEY_R_ENTTYPE struct passwd
  233. #define GETXXKEY_R_TEST(ENT) ((ENT)->pw_uid == key)
  234. #define DO_GETXXKEY_R_KEYTYPE uid_t
  235. #define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD
  236. #include "pwd_grp_internal.c"
  237. #endif
  238. #ifdef L_getgrgid_r
  239. #define GETXXKEY_R_FUNC getgrgid_r
  240. #define GETXXKEY_R_PARSER __parsegrent
  241. #define GETXXKEY_R_ENTTYPE struct group
  242. #define GETXXKEY_R_TEST(ENT) ((ENT)->gr_gid == key)
  243. #define DO_GETXXKEY_R_KEYTYPE gid_t
  244. #define DO_GETXXKEY_R_PATHNAME _PATH_GROUP
  245. #include "pwd_grp_internal.c"
  246. #endif
  247. /**********************************************************************/
  248. #ifdef L_getpwuid
  249. libc_hidden_proto(getpwuid_r)
  250. struct passwd *getpwuid(uid_t uid)
  251. {
  252. static char buffer[PWD_BUFFER_SIZE];
  253. static struct passwd resultbuf;
  254. struct passwd *result;
  255. getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
  256. return result;
  257. }
  258. #endif
  259. /**********************************************************************/
  260. #ifdef L_getgrgid
  261. libc_hidden_proto(getgrgid_r)
  262. struct group *getgrgid(gid_t gid)
  263. {
  264. static char buffer[GRP_BUFFER_SIZE];
  265. static struct group resultbuf;
  266. struct group *result;
  267. getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result);
  268. return result;
  269. }
  270. #endif
  271. /**********************************************************************/
  272. #ifdef L_getspuid_r
  273. /* This function is non-standard and is currently not built. It seems
  274. * to have been created as a reentrant version of the non-standard
  275. * functions getspuid. Why getspuid was added, I do not know. */
  276. libc_hidden_proto(getpwuid_r)
  277. libc_hidden_proto(getspnam_r)
  278. int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf,
  279. char *__restrict buffer, size_t buflen,
  280. struct spwd **__restrict result)
  281. {
  282. int rv;
  283. struct passwd *pp;
  284. struct passwd password;
  285. char pwd_buff[PWD_BUFFER_SIZE];
  286. *result = NULL;
  287. if (!(rv = getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp))) {
  288. rv = getspnam_r(password.pw_name, resultbuf, buffer, buflen, result);
  289. }
  290. return rv;
  291. }
  292. #endif
  293. /**********************************************************************/
  294. #ifdef L_getspuid
  295. /* This function is non-standard and is currently not built.
  296. * Why it was added, I do not know. */
  297. libc_hidden_proto(getspuid_r)
  298. struct spwd *getspuid(uid_t uid)
  299. {
  300. static char buffer[PWD_BUFFER_SIZE];
  301. static struct spwd resultbuf;
  302. struct spwd *result;
  303. getspuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
  304. return result;
  305. }
  306. #endif
  307. /**********************************************************************/
  308. #ifdef L_getpwnam
  309. libc_hidden_proto(getpwnam_r)
  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. libc_hidden_proto(getgrnam_r)
  322. struct group *getgrnam(const char *name)
  323. {
  324. static char buffer[GRP_BUFFER_SIZE];
  325. static struct group resultbuf;
  326. struct group *result;
  327. getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
  328. return result;
  329. }
  330. #endif
  331. /**********************************************************************/
  332. #ifdef L_getspnam
  333. libc_hidden_proto(getspnam_r)
  334. struct spwd *getspnam(const char *name)
  335. {
  336. static char buffer[PWD_BUFFER_SIZE];
  337. static struct spwd resultbuf;
  338. struct spwd *result;
  339. getspnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
  340. return result;
  341. }
  342. #endif
  343. /**********************************************************************/
  344. #ifdef L_getpw
  345. libc_hidden_proto(getpwuid_r)
  346. int getpw(uid_t uid, char *buf)
  347. {
  348. struct passwd resultbuf;
  349. struct passwd *result;
  350. char buffer[PWD_BUFFER_SIZE];
  351. if (!buf) {
  352. __set_errno(EINVAL);
  353. } else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) {
  354. if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n",
  355. resultbuf.pw_name, resultbuf.pw_passwd,
  356. (unsigned long)(resultbuf.pw_uid),
  357. (unsigned long)(resultbuf.pw_gid),
  358. resultbuf.pw_gecos, resultbuf.pw_dir,
  359. resultbuf.pw_shell) >= 0
  360. ) {
  361. return 0;
  362. }
  363. }
  364. return -1;
  365. }
  366. #endif
  367. /**********************************************************************/
  368. #if defined(L_getpwent_r) || defined(L_getgrent_r) || defined(L_getspent_r)
  369. #ifdef __UCLIBC_HAS_THREADS__
  370. # include <pthread.h>
  371. static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
  372. #endif
  373. #define LOCK __pthread_mutex_lock(&mylock)
  374. #define UNLOCK __pthread_mutex_unlock(&mylock)
  375. #endif
  376. #ifdef L_getpwent_r
  377. static FILE *pwf /*= NULL*/;
  378. void setpwent(void)
  379. {
  380. LOCK;
  381. if (pwf) {
  382. rewind(pwf);
  383. }
  384. UNLOCK;
  385. }
  386. void endpwent(void)
  387. {
  388. LOCK;
  389. if (pwf) {
  390. fclose(pwf);
  391. pwf = NULL;
  392. }
  393. UNLOCK;
  394. }
  395. libc_hidden_proto(getpwent_r)
  396. int getpwent_r(struct passwd *__restrict resultbuf,
  397. char *__restrict buffer, size_t buflen,
  398. struct passwd **__restrict result)
  399. {
  400. int rv;
  401. LOCK;
  402. *result = NULL; /* In case of error... */
  403. if (!pwf) {
  404. if (!(pwf = fopen(_PATH_PASSWD, "r"))) {
  405. rv = errno;
  406. goto ERR;
  407. }
  408. __STDIO_SET_USER_LOCKING(pwf);
  409. }
  410. if (!(rv = __pgsreader(__parsepwent, resultbuf,
  411. buffer, buflen, pwf))) {
  412. *result = resultbuf;
  413. }
  414. ERR:
  415. UNLOCK;
  416. return rv;
  417. }
  418. libc_hidden_def(getpwent_r)
  419. #endif
  420. /**********************************************************************/
  421. #ifdef L_getgrent_r
  422. static FILE *grf /*= NULL*/;
  423. void setgrent(void)
  424. {
  425. LOCK;
  426. if (grf) {
  427. rewind(grf);
  428. }
  429. UNLOCK;
  430. }
  431. void endgrent(void)
  432. {
  433. LOCK;
  434. if (grf) {
  435. fclose(grf);
  436. grf = NULL;
  437. }
  438. UNLOCK;
  439. }
  440. libc_hidden_proto(getgrent_r)
  441. int getgrent_r(struct group *__restrict resultbuf,
  442. char *__restrict buffer, size_t buflen,
  443. struct group **__restrict result)
  444. {
  445. int rv;
  446. LOCK;
  447. *result = NULL; /* In case of error... */
  448. if (!grf) {
  449. if (!(grf = fopen(_PATH_GROUP, "r"))) {
  450. rv = errno;
  451. goto ERR;
  452. }
  453. __STDIO_SET_USER_LOCKING(grf);
  454. }
  455. if (!(rv = __pgsreader(__parsegrent, resultbuf,
  456. buffer, buflen, grf))) {
  457. *result = resultbuf;
  458. }
  459. ERR:
  460. UNLOCK;
  461. return rv;
  462. }
  463. libc_hidden_def(getgrent_r)
  464. #endif
  465. /**********************************************************************/
  466. #ifdef L_getspent_r
  467. static FILE *spf /*= NULL*/;
  468. void setspent(void)
  469. {
  470. LOCK;
  471. if (spf) {
  472. rewind(spf);
  473. }
  474. UNLOCK;
  475. }
  476. void endspent(void)
  477. {
  478. LOCK;
  479. if (spf) {
  480. fclose(spf);
  481. spf = NULL;
  482. }
  483. UNLOCK;
  484. }
  485. libc_hidden_proto(getspent_r)
  486. int getspent_r(struct spwd *resultbuf, char *buffer,
  487. size_t buflen, struct spwd **result)
  488. {
  489. int rv;
  490. LOCK;
  491. *result = NULL; /* In case of error... */
  492. if (!spf) {
  493. if (!(spf = fopen(_PATH_SHADOW, "r"))) {
  494. rv = errno;
  495. goto ERR;
  496. }
  497. __STDIO_SET_USER_LOCKING(spf);
  498. }
  499. if (!(rv = __pgsreader(__parsespent, resultbuf,
  500. buffer, buflen, spf))) {
  501. *result = resultbuf;
  502. }
  503. ERR:
  504. UNLOCK;
  505. return rv;
  506. }
  507. libc_hidden_def(getspent_r)
  508. #endif
  509. /**********************************************************************/
  510. #ifdef L_getpwent
  511. libc_hidden_proto(getpwent_r)
  512. struct passwd *getpwent(void)
  513. {
  514. static char line_buff[PWD_BUFFER_SIZE];
  515. static struct passwd pwd;
  516. struct passwd *result;
  517. getpwent_r(&pwd, line_buff, sizeof(line_buff), &result);
  518. return result;
  519. }
  520. #endif
  521. /**********************************************************************/
  522. #ifdef L_getgrent
  523. libc_hidden_proto(getgrent_r)
  524. struct group *getgrent(void)
  525. {
  526. static char line_buff[GRP_BUFFER_SIZE];
  527. static struct group gr;
  528. struct group *result;
  529. getgrent_r(&gr, line_buff, sizeof(line_buff), &result);
  530. return result;
  531. }
  532. #endif
  533. /**********************************************************************/
  534. #ifdef L_getspent
  535. libc_hidden_proto(getspent_r)
  536. struct spwd *getspent(void)
  537. {
  538. static char line_buff[PWD_BUFFER_SIZE];
  539. static struct spwd spwd;
  540. struct spwd *result;
  541. getspent_r(&spwd, line_buff, sizeof(line_buff), &result);
  542. return result;
  543. }
  544. #endif
  545. /**********************************************************************/
  546. #ifdef L_sgetspent
  547. libc_hidden_proto(sgetspent_r)
  548. struct spwd *sgetspent(const char *string)
  549. {
  550. static char line_buff[PWD_BUFFER_SIZE];
  551. static struct spwd spwd;
  552. struct spwd *result;
  553. sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result);
  554. return result;
  555. }
  556. #endif
  557. /**********************************************************************/
  558. #ifdef L_initgroups
  559. int initgroups(const char *user, gid_t gid)
  560. {
  561. FILE *grfile;
  562. gid_t *group_list;
  563. int num_groups, rv;
  564. char **m;
  565. struct group group;
  566. char buff[PWD_BUFFER_SIZE];
  567. rv = -1;
  568. /* We alloc space for 8 gids at a time. */
  569. if (((group_list = (gid_t *) malloc(8*sizeof(gid_t *))) != NULL)
  570. && ((grfile = fopen(_PATH_GROUP, "r")) != NULL)
  571. ) {
  572. __STDIO_SET_USER_LOCKING(grfile);
  573. *group_list = gid;
  574. num_groups = 1;
  575. while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) {
  576. assert(group.gr_mem); /* Must have at least a NULL terminator. */
  577. if (group.gr_gid != gid) {
  578. for (m=group.gr_mem ; *m ; m++) {
  579. if (!strcmp(*m, user)) {
  580. if (!(num_groups & 7)) {
  581. gid_t *tmp = (gid_t *)
  582. realloc(group_list,
  583. (num_groups+8) * sizeof(gid_t *));
  584. if (!tmp) {
  585. rv = -1;
  586. goto DO_CLOSE;
  587. }
  588. group_list = tmp;
  589. }
  590. group_list[num_groups++] = group.gr_gid;
  591. break;
  592. }
  593. }
  594. }
  595. }
  596. rv = setgroups(num_groups, group_list);
  597. DO_CLOSE:
  598. fclose(grfile);
  599. }
  600. /* group_list will be NULL if initial malloc failed, which may trigger
  601. * warnings from various malloc debuggers. */
  602. free(group_list);
  603. return rv;
  604. }
  605. #endif
  606. /**********************************************************************/
  607. #ifdef L_putpwent
  608. int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
  609. {
  610. int rv = -1;
  611. if (!p || !f) {
  612. __set_errno(EINVAL);
  613. } else {
  614. /* No extra thread locking is needed above what fprintf does. */
  615. if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",
  616. p->pw_name, p->pw_passwd,
  617. (unsigned long)(p->pw_uid),
  618. (unsigned long)(p->pw_gid),
  619. p->pw_gecos, p->pw_dir, p->pw_shell) >= 0
  620. ) {
  621. rv = 0;
  622. }
  623. }
  624. return rv;
  625. }
  626. #endif
  627. /**********************************************************************/
  628. #ifdef L_putgrent
  629. int putgrent(const struct group *__restrict p, FILE *__restrict f)
  630. {
  631. static const char format[] = ",%s";
  632. char **m;
  633. const char *fmt;
  634. int rv = -1;
  635. __STDIO_AUTO_THREADLOCK_VAR;
  636. if (!p || !f) { /* Sigh... glibc checks. */
  637. __set_errno(EINVAL);
  638. } else {
  639. __STDIO_AUTO_THREADLOCK(f);
  640. if (fprintf(f, "%s:%s:%lu:",
  641. p->gr_name, p->gr_passwd,
  642. (unsigned long)(p->gr_gid)) >= 0
  643. ) {
  644. fmt = format + 1;
  645. assert(p->gr_mem);
  646. m = p->gr_mem;
  647. do {
  648. if (!*m) {
  649. if (__fputc_unlocked('\n', f) >= 0) {
  650. rv = 0;
  651. }
  652. break;
  653. }
  654. if (fprintf(f, fmt, *m) < 0) {
  655. break;
  656. }
  657. ++m;
  658. fmt = format;
  659. } while (1);
  660. }
  661. __STDIO_AUTO_THREADUNLOCK(f);
  662. }
  663. return rv;
  664. }
  665. #endif
  666. /**********************************************************************/
  667. #ifdef L_putspent
  668. static const unsigned char _sp_off[] = {
  669. offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */
  670. offsetof(struct spwd, sp_min), /* 3 - not a char ptr */
  671. offsetof(struct spwd, sp_max), /* 4 - not a char ptr */
  672. offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */
  673. offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */
  674. offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */
  675. };
  676. int putspent(const struct spwd *p, FILE *stream)
  677. {
  678. static const char ld_format[] = "%ld:";
  679. const char *f;
  680. long int x;
  681. size_t i;
  682. int rv = -1;
  683. __STDIO_AUTO_THREADLOCK_VAR;
  684. /* Unlike putpwent and putgrent, glibc does not check the args. */
  685. __STDIO_AUTO_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_AUTO_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 attribute_hidden __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 attribute_hidden __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 attribute_hidden __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 attribute_hidden __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
  916. char *__restrict line_buff, size_t buflen, FILE *f)
  917. {
  918. size_t line_len;
  919. int skip;
  920. int rv = ERANGE;
  921. __STDIO_AUTO_THREADLOCK_VAR;
  922. if (buflen < PWD_BUFFER_SIZE) {
  923. __set_errno(rv);
  924. } else {
  925. __STDIO_AUTO_THREADLOCK(f);
  926. skip = 0;
  927. do {
  928. if (!fgets_unlocked(line_buff, buflen, f)) {
  929. if (feof_unlocked(f)) {
  930. rv = ENOENT;
  931. }
  932. break;
  933. }
  934. line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */
  935. if (line_buff[line_len] == '\n') {
  936. line_buff[line_len] = 0;
  937. } else if (line_len + 2 == buflen) { /* line too long */
  938. ++skip;
  939. continue;
  940. }
  941. if (skip) {
  942. --skip;
  943. continue;
  944. }
  945. /* NOTE: glibc difference - glibc strips leading whitespace from
  946. * records. We do not allow leading whitespace. */
  947. /* Skip empty lines, comment lines, and lines with leading
  948. * whitespace. */
  949. if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) {
  950. if (__parserfunc == __parsegrent) { /* Do evil group hack. */
  951. /* The group entry parsing function needs to know where
  952. * the end of the buffer is so that it can construct the
  953. * group member ptr table. */
  954. ((struct group *) data)->gr_name = line_buff + buflen;
  955. }
  956. if (!__parserfunc(data, line_buff)) {
  957. rv = 0;
  958. break;
  959. }
  960. }
  961. } while (1);
  962. __STDIO_AUTO_THREADUNLOCK(f);
  963. }
  964. return rv;
  965. }
  966. #endif
  967. /**********************************************************************/