mirror of
https://github.com/linux-pam/linux-pam.git
synced 2024-11-30 21:23:57 +08:00
190 lines
3.4 KiB
C
190 lines
3.4 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* Copyright (c) Andrew G. Morgan <morgan@ftp.kernel.org>
|
|
*
|
|
* pamc_start and pamc_end
|
|
*/
|
|
|
|
#include "libpamc.h"
|
|
|
|
/*
|
|
* liberate path list
|
|
*/
|
|
|
|
static void __pamc_delete_path_list(pamc_handle_t pch)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; pch->agent_paths[i]; ++i) {
|
|
free(pch->agent_paths[i]);
|
|
pch->agent_paths[i] = NULL;
|
|
}
|
|
|
|
free(pch->agent_paths);
|
|
pch->agent_paths = NULL;
|
|
}
|
|
|
|
/*
|
|
* open the pamc library
|
|
*/
|
|
|
|
pamc_handle_t pamc_start(void)
|
|
{
|
|
int i, count, last, this;
|
|
const char *default_path;
|
|
pamc_handle_t pch;
|
|
|
|
pch = calloc(1, sizeof(struct pamc_handle_s));
|
|
if (pch == NULL) {
|
|
D(("no memory for *pch"));
|
|
return NULL;
|
|
}
|
|
|
|
pch->highest_fd_to_close = _PAMC_DEFAULT_TOP_FD;
|
|
|
|
default_path = getenv("PAMC_AGENT_PATH");
|
|
if (default_path == NULL) {
|
|
default_path = PAMC_SYSTEM_AGENT_PATH;
|
|
}
|
|
|
|
/* number of individual paths */
|
|
for (count=1, i=0; default_path[i]; ++i) {
|
|
if (default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR) {
|
|
++count;
|
|
}
|
|
}
|
|
|
|
pch->agent_paths = calloc(count+1, sizeof(char *));
|
|
if (pch->agent_paths == NULL) {
|
|
D(("no memory for path list"));
|
|
goto drop_pch;
|
|
}
|
|
|
|
this = last = i = 0;
|
|
while ( default_path[i] || (i != last) ) {
|
|
if ( default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR
|
|
|| !default_path[i] ) {
|
|
int length;
|
|
|
|
pch->agent_paths[this] = malloc(length = 1+i-last);
|
|
|
|
if (pch->agent_paths[this] == NULL) {
|
|
D(("no memory for next path"));
|
|
goto drop_list;
|
|
}
|
|
|
|
memcpy(pch->agent_paths[this], default_path + last, i-last);
|
|
pch->agent_paths[this][i-last] = '\0';
|
|
if (length > pch->max_path) {
|
|
pch->max_path = length;
|
|
}
|
|
|
|
if (++this == count) {
|
|
break;
|
|
}
|
|
|
|
last = ++i;
|
|
} else {
|
|
++i;
|
|
}
|
|
}
|
|
|
|
return pch;
|
|
|
|
drop_list:
|
|
__pamc_delete_path_list(pch);
|
|
|
|
drop_pch:
|
|
free(pch);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* shutdown each of the loaded agents and
|
|
*/
|
|
|
|
static int __pamc_shutdown_agents(pamc_handle_t pch)
|
|
{
|
|
int retval = PAM_BPC_TRUE;
|
|
|
|
D(("called"));
|
|
|
|
while (pch->chain) {
|
|
pid_t pid;
|
|
int status;
|
|
pamc_agent_t *this;
|
|
|
|
this = pch->chain;
|
|
D(("cleaning up agent %p", this));
|
|
pch->chain = pch->chain->next;
|
|
this->next = NULL;
|
|
D(("cleaning up agent: %s", this->id));
|
|
|
|
/* close off contact with agent and wait for it to shutdown */
|
|
|
|
close(this->writer);
|
|
this->writer = -1;
|
|
close(this->reader);
|
|
this->reader = -1;
|
|
|
|
pid = waitpid(this->pid, &status, 0);
|
|
if (pid == this->pid) {
|
|
|
|
D(("is exit:%d, exit val:%d",
|
|
WIFEXITED(status), WEXITSTATUS(status)));
|
|
|
|
if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
|
|
retval = PAM_BPC_FALSE;
|
|
}
|
|
} else {
|
|
D(("problem shutting down agent (%s): pid(%d) != waitpid(%d)!?",
|
|
this->id, this->pid, pid));
|
|
retval = PAM_BPC_FALSE;
|
|
}
|
|
pid = this->pid = 0;
|
|
|
|
memset(this->id, 0, this->id_length);
|
|
free(this->id);
|
|
this->id = NULL;
|
|
this->id_length = 0;
|
|
|
|
free(this);
|
|
this = NULL;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* close the pamc library
|
|
*/
|
|
|
|
int pamc_end(pamc_handle_t *pch_p)
|
|
{
|
|
int retval;
|
|
|
|
if (pch_p == NULL) {
|
|
D(("called with no pch_p"));
|
|
return PAM_BPC_FALSE;
|
|
}
|
|
|
|
if (*pch_p == NULL) {
|
|
D(("called with no *pch_p"));
|
|
return PAM_BPC_FALSE;
|
|
}
|
|
|
|
D(("removing path_list"));
|
|
__pamc_delete_path_list(*pch_p);
|
|
|
|
D(("shutting down agents"));
|
|
retval = __pamc_shutdown_agents(*pch_p);
|
|
|
|
D(("freeing *pch_p"));
|
|
free(*pch_p);
|
|
*pch_p = NULL;
|
|
|
|
return retval;
|
|
}
|