compat-initgroups.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* Prototype for the setgrent functions we use here. */
  2. typedef enum nss_status (*set_function) (void);
  3. /* Prototype for the endgrent functions we use here. */
  4. typedef enum nss_status (*end_function) (void);
  5. /* Prototype for the setgrent functions we use here. */
  6. typedef enum nss_status (*get_function) (struct group *, char *,
  7. size_t, int *);
  8. static enum nss_status
  9. compat_call (service_user *nip, const char *user, gid_t group, long int *start,
  10. long int *size, gid_t **groupsp, long int limit, int *errnop)
  11. {
  12. struct group grpbuf;
  13. enum nss_status status;
  14. set_function setgrent_fct;
  15. get_function getgrent_fct;
  16. end_function endgrent_fct;
  17. gid_t *groups = *groupsp;
  18. getgrent_fct = __nss_lookup_function (nip, "getgrent_r");
  19. if (getgrent_fct == NULL)
  20. return NSS_STATUS_UNAVAIL;
  21. setgrent_fct = __nss_lookup_function (nip, "setgrent");
  22. if (setgrent_fct)
  23. {
  24. status = DL_CALL_FCT (setgrent_fct, ());
  25. if (status != NSS_STATUS_SUCCESS)
  26. return status;
  27. }
  28. endgrent_fct = __nss_lookup_function (nip, "endgrent");
  29. struct scratch_buffer tmpbuf;
  30. scratch_buffer_init (&tmpbuf);
  31. enum nss_status result = NSS_STATUS_SUCCESS;
  32. do
  33. {
  34. while ((status = DL_CALL_FCT (getgrent_fct,
  35. (&grpbuf, tmpbuf.data, tmpbuf.length,
  36. errnop)),
  37. status == NSS_STATUS_TRYAGAIN)
  38. && *errnop == ERANGE)
  39. {
  40. if (!scratch_buffer_grow (&tmpbuf))
  41. {
  42. result = NSS_STATUS_TRYAGAIN;
  43. goto done;
  44. }
  45. }
  46. if (status != NSS_STATUS_SUCCESS)
  47. goto done;
  48. if (grpbuf.gr_gid != group)
  49. {
  50. char **m;
  51. for (m = grpbuf.gr_mem; *m != NULL; ++m)
  52. if (strcmp (*m, user) == 0)
  53. {
  54. /* Check whether the group is already on the list. */
  55. long int cnt;
  56. for (cnt = 0; cnt < *start; ++cnt)
  57. if (groups[cnt] == grpbuf.gr_gid)
  58. break;
  59. if (cnt == *start)
  60. {
  61. /* Matches user and not yet on the list. Insert
  62. this group. */
  63. if (__glibc_unlikely (*start == *size))
  64. {
  65. /* Need a bigger buffer. */
  66. gid_t *newgroups;
  67. long int newsize;
  68. if (limit > 0 && *size == limit)
  69. /* We reached the maximum. */
  70. goto done;
  71. if (limit <= 0)
  72. newsize = 2 * *size;
  73. else
  74. newsize = MIN (limit, 2 * *size);
  75. newgroups = realloc (groups,
  76. newsize * sizeof (*groups));
  77. if (newgroups == NULL)
  78. goto done;
  79. *groupsp = groups = newgroups;
  80. *size = newsize;
  81. }
  82. groups[*start] = grpbuf.gr_gid;
  83. *start += 1;
  84. }
  85. break;
  86. }
  87. }
  88. }
  89. while (status == NSS_STATUS_SUCCESS);
  90. done:
  91. scratch_buffer_free (&tmpbuf);
  92. if (endgrent_fct)
  93. DL_CALL_FCT (endgrent_fct, ());
  94. return result;
  95. }