pwd_grp.c 25 KB

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