pwd_grp.c 28 KB

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