user.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. *
  4. * Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Marcus Crestani
  5. */
  6. /*
  7. * Users and groups
  8. *
  9. * This provides Scheme access to the following: getgrgid(), getgrnam(),
  10. * getpwuid(), and getpwnam().
  11. *
  12. * The only externally visible bindings are s48_posix_init_user() and
  13. * s48_{enter|extract}_{u|g}id
  14. */
  15. #include <stdio.h>
  16. #include "scheme48.h"
  17. #include <sys/types.h>
  18. #include <stdio.h>
  19. #include <errno.h>
  20. #include <pwd.h>
  21. #include <grp.h>
  22. #include "posix.h"
  23. #include "unix.h"
  24. extern void s48_posix_init_user(void);
  25. static s48_ref_t posix_getpwuid(s48_call_t call, s48_ref_t uid),
  26. posix_getpwnam(s48_call_t call, s48_ref_t user_name),
  27. posix_getgrgid(s48_call_t call, s48_ref_t gid),
  28. posix_getgrnam(s48_call_t call, s48_ref_t group_name);
  29. /*
  30. * Record types imported from Scheme.
  31. */
  32. static s48_ref_t posix_user_id_type_binding,
  33. posix_group_id_type_binding;
  34. /*
  35. * Install all exported functions in Scheme48 and import and protect the
  36. * required record types.
  37. */
  38. void
  39. s48_init_posix_user(void)
  40. {
  41. S48_EXPORT_FUNCTION(posix_getpwuid);
  42. S48_EXPORT_FUNCTION(posix_getpwnam);
  43. S48_EXPORT_FUNCTION(posix_getgrgid);
  44. S48_EXPORT_FUNCTION(posix_getgrnam);
  45. posix_user_id_type_binding = s48_get_imported_binding_2("posix-user-id-type");
  46. posix_group_id_type_binding = s48_get_imported_binding_2("posix-group-id-type");
  47. }
  48. /* ****************************************************************
  49. * Converting uids and gids back and forth between C and Scheme.
  50. */
  51. /*
  52. * Convert a uid into a Scheme uid record.
  53. */
  54. s48_ref_t
  55. s48_enter_uid(s48_call_t call, uid_t uid)
  56. {
  57. s48_ref_t sch_uid;
  58. sch_uid = s48_make_record_2(call, posix_user_id_type_binding);
  59. s48_unsafe_record_set_2(call, sch_uid, 0, s48_enter_long_2(call, uid));
  60. return sch_uid;
  61. }
  62. /*
  63. * Convert a Scheme uid record into a uid_t.
  64. */
  65. uid_t
  66. s48_extract_uid(s48_call_t call, s48_ref_t uid)
  67. {
  68. s48_check_record_type_2(call, uid, posix_user_id_type_binding);
  69. return s48_extract_long_2(call, s48_unsafe_record_ref_2(call, uid, 0));
  70. }
  71. /*
  72. * Convert a gid into a Scheme gid record.
  73. */
  74. s48_ref_t
  75. s48_enter_gid(s48_call_t call, gid_t gid)
  76. {
  77. s48_ref_t sch_gid;
  78. sch_gid = s48_make_record_2(call, posix_group_id_type_binding);
  79. s48_unsafe_record_set_2(call, sch_gid, 0, s48_enter_long_2(call, gid));
  80. return sch_gid;
  81. }
  82. /*
  83. * Convert a Scheme gid record into a gid_t.
  84. */
  85. gid_t
  86. s48_extract_gid(s48_call_t call, s48_ref_t gid)
  87. {
  88. s48_check_record_type_2(call, gid, posix_group_id_type_binding);
  89. return s48_extract_long_2(call, s48_unsafe_record_ref_2(call, gid, 0));
  90. }
  91. /* ****************************************************************
  92. * Getting user and group information.
  93. */
  94. static s48_ref_t enter_user_data(s48_call_t call, struct passwd *data);
  95. static s48_ref_t
  96. posix_getpwuid(s48_call_t call, s48_ref_t uid)
  97. {
  98. struct passwd *data;
  99. RETRY_OR_RAISE_NULL(data, getpwuid(s48_extract_uid(call, uid)));
  100. return enter_user_data(call, data);
  101. }
  102. static s48_ref_t
  103. posix_getpwnam(s48_call_t call, s48_ref_t name)
  104. {
  105. struct passwd *data;
  106. RETRY_OR_RAISE_NULL(data, getpwnam(s48_extract_byte_vector_readonly_2(call, name)));
  107. return enter_user_data(call, data);
  108. }
  109. /*
  110. * returns a list of components
  111. */
  112. static s48_ref_t
  113. enter_user_data(s48_call_t call, struct passwd *data)
  114. {
  115. s48_ref_t sch_data, temp;
  116. sch_data = s48_null_2(call);
  117. temp = s48_enter_byte_string_2(call, data->pw_shell);
  118. sch_data = s48_cons_2(call, temp, sch_data);
  119. temp = s48_enter_byte_string_2(call, data->pw_dir);
  120. sch_data = s48_cons_2(call, temp, sch_data);
  121. temp = s48_enter_gid(call, data->pw_gid);
  122. sch_data = s48_cons_2(call, temp, sch_data);
  123. temp = s48_enter_uid(call, data->pw_uid);
  124. sch_data = s48_cons_2(call, temp, sch_data);
  125. temp = s48_enter_byte_string_2(call, data->pw_name);
  126. sch_data = s48_cons_2(call, temp, sch_data);
  127. return sch_data;
  128. }
  129. static s48_ref_t
  130. enter_group_data(s48_call_t call, struct group *data)
  131. {
  132. s48_ref_t sch_data, members, temp;
  133. int length;
  134. char **names;
  135. for(length = 0, names = data->gr_mem; *names != NULL; length++, names++);
  136. members = s48_make_vector_2(call, length, s48_false_2(call));
  137. for(length = 0, names = data->gr_mem; *names != NULL; length++, names++) {
  138. temp = s48_enter_byte_string_2(call, *names);
  139. s48_unsafe_vector_set_2(call, members, length, temp);
  140. }
  141. sch_data = s48_null_2(call);
  142. sch_data = s48_cons_2(call, members, sch_data);
  143. temp = s48_enter_gid(call, data->gr_gid);
  144. sch_data = s48_cons_2(call, temp, sch_data);
  145. temp = s48_enter_byte_string_2(call, data->gr_name);
  146. sch_data = s48_cons_2(call, temp, sch_data);
  147. return sch_data;
  148. }
  149. static s48_ref_t
  150. posix_getgrgid(s48_call_t call, s48_ref_t gid)
  151. {
  152. struct group *data;
  153. RETRY_OR_RAISE_NULL(data, getgrgid(s48_extract_gid(call, gid)));
  154. return enter_group_data(call, data);
  155. }
  156. static s48_ref_t
  157. posix_getgrnam(s48_call_t call, s48_ref_t name)
  158. {
  159. struct group *data;
  160. RETRY_OR_RAISE_NULL(data, getgrnam(s48_extract_byte_vector_readonly_2(call, name)));
  161. return enter_group_data(call, data);
  162. }