/** * Parse notify command. * */ static void set_notify_ns(zone_type* zone, const char* cmd) { const char* str = NULL; const char* str2 = NULL; char* token = NULL; ods_log_assert(cmd); ods_log_assert(zone); ods_log_assert(zone->name); ods_log_assert(zone->adoutbound); if (zone->adoutbound->type == ADAPTER_FILE) { str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr); if (!str) { ods_log_error("[%s] unable to set notify ns: replace zonefile failed", engine_str); } str2 = ods_replace(str, "%zone", zone->name); free((void*)str); } else { str2 = ods_replace(cmd, "%zone", zone->name); } if (str2) { ods_str_trim((char*) str2); str = str2; if (*str) { token = NULL; while ((token = strtok((char*) str, " "))) { if (*token) { ods_str_list_add(&zone->notify_args, token); } str = NULL; } } zone->notify_command = (char*) str2; zone->notify_ns = zone->notify_args[0]; ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns); } else { ods_log_error("[%s] unable to set notify ns: replace zone failed", engine_str); } return; }
/** * Interface. * */ static int interface_run(FILE* fp, int sockfd, char* cmd) { int maxfdp1 = 0; int stdineof = 0; int i = 0; int n = 0; int ret = 0; int cmd_written = 0; int cmd_response = 0; fd_set rset; char buf[ODS_SE_MAXLINE]; int written; stdineof = 0; FD_ZERO(&rset); for(;;) { /* prepare */ if (stdineof == 0) { FD_SET(fileno(fp), &rset); } FD_SET(sockfd, &rset); maxfdp1 = max(fileno(fp), sockfd) + 1; if (!cmd || cmd_written) { /* interactive mode */ ret = select(maxfdp1, &rset, NULL, NULL, NULL); if (ret < 0) { if (errno != EINTR && errno != EWOULDBLOCK) { ods_log_warning("[%s] interface select error: %s", cli_str, strerror(errno)); } continue; } } else if (cmd) { /* passive mode */ ods_writen(sockfd, cmd, strlen(cmd)); cmd_written = 1; stdineof = 1; /* Clear the interactive mode / stdin fd from the set */ FD_CLR(fileno(fp), &rset); continue; } if (cmd && cmd_written && cmd_response) { /* normal termination */ return 0; } if (FD_ISSET(sockfd, &rset)) { /* clear buffer */ for (i=0; i < ODS_SE_MAXLINE; i++) { buf[i] = 0; } buf[ODS_SE_MAXLINE-1] = '\0'; /* socket is readable */ if ((n = read(sockfd, buf, ODS_SE_MAXLINE)) <= 0) { if (n < 0) { /* error occurred */ fprintf(stderr, "error: %s\n", strerror(errno)); return 1; } else { /* n==0 */ if (stdineof == 1) { /* normal termination */ return 0; } else { /* weird termination */ fprintf(stderr, "enforcer engine terminated " "prematurely\n"); return 1; } } } if (cmd) { if (n < SE_CLI_CMDLEN) { /* not enough data received */ fprintf(stderr, "not enough response data received " "from daemon.\n"); return 1; } /* n >= SE_CLI_CMDLEN : and so it is safe to do buffer manipulations below. */ if (strncmp(buf+n-SE_CLI_CMDLEN,"\ncmd> ",SE_CLI_CMDLEN) == 0) { /* we have the full response */ n -= SE_CLI_CMDLEN; buf[n] = '\0'; cmd_response = 1; } } /* n > 0 : when we get to this line... */ for (written=0; written < n; written += ret) { /* write what we got to stdout */ ret = (int) write(fileno(stdout), &buf[written], n-written); /* error and shutdown handling */ if (ret == 0) { fprintf(stderr, "no write\n"); break; } if (ret < 0) { if (errno == EINTR || errno == EWOULDBLOCK) { ret = 0; continue; /* try again... */ } fprintf(stderr, "\n\nwrite error: %s\n", strerror(errno)); break; } /* ret > 0 : when we get here... */ if (written+ret > n) { fprintf(stderr, "\n\nwrite error: more bytes (%d) written than required (%d)\n", written+ret, n); break; } /* written+ret < n : means partial write, requires us to loop... */ } if (ods_strcmp(buf, ODS_SE_STOP_RESPONSE) == 0 ) { /* we do no further reading, flush */ write(fileno(stdout), "\n", 1); return 0; } else if (cmd_response) return 0; } if (FD_ISSET(fileno(fp), &rset)) { /* input is readable */ if (cmd && cmd_written) { /* passive mode */ stdineof = 1; ret = shutdown(sockfd, SHUT_WR); if (ret != 0) { fprintf(stderr, "shutdown failed: %s\n", strerror(errno)); return 1; } FD_CLR(fileno(fp), &rset); continue; } /* clear buffer */ for (i=0; i< ODS_SE_MAXLINE; i++) { buf[i] = 0; } /* interactive mode */ if ((n = read(fileno(fp), buf, ODS_SE_MAXLINE)) == 0) { stdineof = 1; ret = shutdown(sockfd, SHUT_WR); if (ret != 0) { fprintf(stderr, "shutdown failed: %s\n", strerror(errno)); return 1; } FD_CLR(fileno(fp), &rset); continue; } if (strncmp(buf, "exit", 4) == 0 || strncmp(buf, "quit", 4) == 0) { return 0; } ods_str_trim(buf); n = strlen(buf); ods_writen(sockfd, buf, n); } } }