pamc_client.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (c) Andrew G. Morgan <morgan@ftp.kernel.org>
  5. *
  6. * pamc_start and pamc_end
  7. */
  8. #include "libpamc.h"
  9. /*
  10. * liberate path list
  11. */
  12. static void __pamc_delete_path_list(pamc_handle_t pch)
  13. {
  14. int i;
  15. for (i=0; pch->agent_paths[i]; ++i) {
  16. free(pch->agent_paths[i]);
  17. pch->agent_paths[i] = NULL;
  18. }
  19. free(pch->agent_paths);
  20. pch->agent_paths = NULL;
  21. }
  22. /*
  23. * open the pamc library
  24. */
  25. pamc_handle_t pamc_start(void)
  26. {
  27. int i, count, last, this;
  28. const char *default_path;
  29. pamc_handle_t pch;
  30. pch = calloc(1, sizeof(struct pamc_handle_s));
  31. if (pch == NULL) {
  32. D(("no memory for *pch"));
  33. return NULL;
  34. }
  35. pch->highest_fd_to_close = _PAMC_DEFAULT_TOP_FD;
  36. default_path = getenv("PAMC_AGENT_PATH");
  37. if (default_path == NULL) {
  38. default_path = PAMC_SYSTEM_AGENT_PATH;
  39. }
  40. /* number of individual paths */
  41. for (count=1, i=0; default_path[i]; ++i) {
  42. if (default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR) {
  43. ++count;
  44. }
  45. }
  46. pch->agent_paths = calloc(count+1, sizeof(char *));
  47. if (pch->agent_paths == NULL) {
  48. D(("no memory for path list"));
  49. goto drop_pch;
  50. }
  51. this = last = i = 0;
  52. while ( default_path[i] || (i != last) ) {
  53. if ( default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR
  54. || !default_path[i] ) {
  55. int length;
  56. pch->agent_paths[this] = malloc(length = 1+i-last);
  57. if (pch->agent_paths[this] == NULL) {
  58. D(("no memory for next path"));
  59. goto drop_list;
  60. }
  61. memcpy(pch->agent_paths[this], default_path + last, i-last);
  62. pch->agent_paths[this][i-last] = '\0';
  63. if (length > pch->max_path) {
  64. pch->max_path = length;
  65. }
  66. if (++this == count) {
  67. break;
  68. }
  69. last = ++i;
  70. } else {
  71. ++i;
  72. }
  73. }
  74. return pch;
  75. drop_list:
  76. __pamc_delete_path_list(pch);
  77. drop_pch:
  78. free(pch);
  79. return NULL;
  80. }
  81. /*
  82. * shutdown each of the loaded agents and
  83. */
  84. static int __pamc_shutdown_agents(pamc_handle_t pch)
  85. {
  86. int retval = PAM_BPC_TRUE;
  87. D(("called"));
  88. while (pch->chain) {
  89. pid_t pid;
  90. int status;
  91. pamc_agent_t *this;
  92. this = pch->chain;
  93. D(("cleaning up agent %p", this));
  94. pch->chain = pch->chain->next;
  95. this->next = NULL;
  96. D(("cleaning up agent: %s", this->id));
  97. /* close off contact with agent and wait for it to shutdown */
  98. close(this->writer);
  99. this->writer = -1;
  100. close(this->reader);
  101. this->reader = -1;
  102. pid = waitpid(this->pid, &status, 0);
  103. if (pid == this->pid) {
  104. D(("is exit:%d, exit val:%d",
  105. WIFEXITED(status), WEXITSTATUS(status)));
  106. if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
  107. retval = PAM_BPC_FALSE;
  108. }
  109. } else {
  110. D(("problem shutting down agent (%s): pid(%d) != waitpid(%d)!?",
  111. this->id, this->pid, pid));
  112. retval = PAM_BPC_FALSE;
  113. }
  114. pid = this->pid = 0;
  115. memset(this->id, 0, this->id_length);
  116. free(this->id);
  117. this->id = NULL;
  118. this->id_length = 0;
  119. free(this);
  120. this = NULL;
  121. }
  122. return retval;
  123. }
  124. /*
  125. * close the pamc library
  126. */
  127. int pamc_end(pamc_handle_t *pch_p)
  128. {
  129. int retval;
  130. if (pch_p == NULL) {
  131. D(("called with no pch_p"));
  132. return PAM_BPC_FALSE;
  133. }
  134. if (*pch_p == NULL) {
  135. D(("called with no *pch_p"));
  136. return PAM_BPC_FALSE;
  137. }
  138. D(("removing path_list"));
  139. __pamc_delete_path_list(*pch_p);
  140. D(("shutting down agents"));
  141. retval = __pamc_shutdown_agents(*pch_p);
  142. D(("freeing *pch_p"));
  143. free(*pch_p);
  144. *pch_p = NULL;
  145. return retval;
  146. }