if (as->ap0) {
if (memcmp(&nilap, &(as->ap0), sizeof(nilap)) != 0) {
auth_call(auth_session_t *as, char *path, ...){	char *line;	struct authdata *data;	struct authopts *opt;	pid_t pid;	int status;	int okay;	int pfd[2];	int argc;	char *argv[64];		/* 64 args should more than enough */#define	Nargc	(sizeof(argv)/sizeof(argv[0]))	va_start(as->ap0, path);	argc = 0;	if ((argv[argc] = _auth_next_arg(as)) != NULL)		++argc;	for (opt = as->optlist; opt != NULL; opt = opt->next) {		if (argc < Nargc - 2) {			argv[argc++] = "-v";			argv[argc++] = opt->opt;		} else {			syslog(LOG_ERR, "too many authentication options");			goto fail;		}	}	while (argc < Nargc - 1 && (argv[argc] = _auth_next_arg(as)))		++argc;	if (argc >= Nargc - 1 && _auth_next_arg(as)) {		if (as->ap0) {			va_end(as->ap0);			as->ap0 = NULL;		}		if (as->ap) {			va_end(as->ap);			as->ap = NULL;		}		syslog(LOG_ERR, "too many arguments");		goto fail;	}	argv[argc] = NULL;	if (secure_path(path) < 0) {		syslog(LOG_ERR, "%s: path not secure", path);		warnx("invalid script: %s", path);		goto fail;	}	if (socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd) < 0) {		syslog(LOG_ERR, "unable to create backchannel %m");		warnx("internal resource failure");		goto fail;	}	switch (pid = fork()) {	case -1:		close(pfd[0]);		close(pfd[1]);		syslog(LOG_ERR, "%s: %m", path);		warnx("internal resource failure");		goto fail;	case 0:#define	COMM_FD	3		close(pfd[0]);		if (pfd[1] != COMM_FD) {			if (dup2(pfd[1], COMM_FD) < 0)				err(1, "dup of backchannel");			close(pfd[1]);		}		for (status = getdtablesize() - 1; status > COMM_FD; status--)			close(status);		execve(path, argv, auth_environ);		syslog(LOG_ERR, "%s: %m", path);		err(1, "%s", path);	default:		close(pfd[1]);		while ((data = as->data) != NULL) {			as->data = data->next;			if (data->len > 0) {				write(pfd[0], data->ptr, data->len);				memset(data->ptr, 0, data->len);			}			free(data);		}		as->index = 0;		_auth_spool(as, pfd[0]);		close(pfd[0]);		if (waitpid(pid, &status, 0) < 0) {			syslog(LOG_ERR, "%s: waitpid: %m", path);			warnx("internal failure");			goto fail;		}		if (!WIFEXITED(status))			goto fail;	}	/*	 * Now scan the spooled data	 * It is easier to wait for all the data before starting	 * to scan it.	 */    	for (line = as->spool; line < as->spool + as->index;) {		if (!strncasecmp(line, BI_REJECT, sizeof(BI_REJECT)-1)) {			line += sizeof(BI_REJECT) - 1;			if (!*line || *line == ' ' || *line == '\t') {				while (*line == ' ' || *line == '\t')					++line;				if (!strcasecmp(line, "silent")) {					as->state = AUTH_SILENT;					break;				}				if (!strcasecmp(line, "challenge")) {					as->state  = AUTH_CHALLENGE;					break;				}				if (!strcasecmp(line, "expired")) {					as->state  = AUTH_EXPIRED;					break;				}				if (!strcasecmp(line, "pwexpired")) {					as->state  = AUTH_PWEXPIRED;					break;				}			}			break;		} else if (!strncasecmp(line, BI_AUTH, sizeof(BI_AUTH)-1)) {			line += sizeof(BI_AUTH) - 1;			if (!*line || *line == ' ' || *line == '\t') {				while (*line == ' ' || *line == '\t')					++line;				if (*line == '\0')					as->state |= AUTH_OKAY;				else if (!strcasecmp(line, "root"))					as->state |= AUTH_ROOTOKAY;				else if (!strcasecmp(line, "secure"))					as->state |= AUTH_SECURE;			}		} else if (!strncasecmp(line, BI_REMOVE, sizeof(BI_REMOVE)-1)) {			line += sizeof(BI_REMOVE) - 1;			while (*line == ' ' || *line == '\t')				++line;			if (*line)				_add_rmlist(as, line);		}		while (*line++)			;	}	if (WEXITSTATUS(status))		as->state &= ~AUTH_ALLOW;	okay = as->state & AUTH_ALLOW;	if (!okay)		auth_clrenv(as);	if (0) {fail:		auth_clrenv(as);		as->state = 0;		okay = -1;	}	while ((data = as->data) != NULL) {		as->data = data->next;		free(data);	}	if (as->ap0) {		va_end(as->ap0);		as->ap0 = NULL;	}	if (as->ap) {		va_end(as->ap);		as->ap = NULL;	}	return (okay);}