pwd_grp.c 25 KB

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