static void pcp_worker_will_go_down(int code, Datum arg) { if (processType != PT_PCP_WORKER) { /* should never happen */ ereport(WARNING, (errmsg("pcp_worker_will_go_down called from invalid process"))); return; } if(pcp_frontend) pcp_close(pcp_frontend); processState = EXITING; POOL_SETMASK(&UnBlockSig); }
static void proxy_list_rset() { struct proxy_list *p; while ((p=proxy_list) != NULL) { proxy_list=p->next; if (p->newevent) pcp_destroy_eventid(p->proxy, p->newevent); pcp_close(p->proxy); free(p->userid); if (p->old_event_id) free(p->old_event_id); proxy_list=p->next; free(p); } }
struct PCP *open_calendar(const char *p) { struct PCP *pcp; struct passwd *pw=getpwuid(getuid()); const char *cp; if (!pw) { perror("getpwuid"); exit(1); } userid=strdup(pw->pw_name); if (p && *p) { if (chdir(p)) { perror(p); exit(1); } } else if ((cp=getenv("PCPDIR")) != NULL && *cp) { if (chdir(cp)) { perror(cp); exit(1); } } pcp=pcp_open_dir(".", userid); if (pcp && pcp_cleanup(pcp)) { pcp_close(pcp); pcp=NULL; } if (!pcp) { perror("pcp_open_dir"); exit(1); } return (pcp); }
static struct proxy_list *proxy(const char *proxy_userid, char **errmsg) { struct proxy_list *p; if (errmsg) *errmsg=0; for (p=proxy_list; p; p=p->next) { if (addrcmp(proxy_userid, p->userid) == 0) return (p); } p=malloc(sizeof(struct proxy_list)); if (!p) return (NULL); memset(p, 0, sizeof(*p)); if ((p->userid=strdup(proxy_userid)) == NULL) { free(p); return (NULL); } if ((p->proxy=pcp_find_proxy(proxy_userid, NULL, errmsg)) == NULL || pcp_set_proxy(p->proxy, userid)) { if (p->proxy) pcp_close(p->proxy); free(p->userid); free(p); return (NULL); } p->next=proxy_list; proxy_list=p; return (p); }
/* -------------------------------- * pcp_disconnect - close connection to pgpool * -------------------------------- */ void pcp_disconnect(void) { int wsize; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); return; } pcp_write(pc, "X", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { /* backend had closed connection already */ } if (debug) fprintf(stderr, "DEBUG: send: tos=\"X\", len=%d\n", (int) sizeof(int)); pcp_close(pc); pc = NULL; }
/* -------------------------------- * pcp_disconnect - close connection to pgpool * -------------------------------- */ void pcp_disconnect(PCPConnInfo* pcpConn) { int wsize; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn,"invalid PCP connection"); return; } pcp_write(pcpConn->pcpConn, "X", 1); wsize = htonl(sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); if (PCPFlush(pcpConn) < 0) return; if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug, "DEBUG: send: tos=\"X\", len=%d\n", (int) sizeof(int)); pcp_close(pcpConn->pcpConn); pcpConn->connState = PCP_CONNECTION_NOT_CONNECTED; pcpConn->pcpConn = NULL; }
/* -------------------------------- * pcp_connect - open connection to pgpool using given arguments * * return 0 on success, -1 otherwise * -------------------------------- */ int pcp_connect(char *hostname, int port, char *username, char *password) { struct sockaddr_in addr; struct sockaddr_un unix_addr; struct hostent *hp; int fd; int on = 1; int len; if (pc != NULL) { if (debug) fprintf(stderr, "DEBUG: connection to backend \"%s\" already exists\n", hostname); return 0; } if (hostname == NULL || *hostname == '\0' || *hostname == '/') { char *path; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { if (debug) fprintf(stderr, "DEBUG: could not create socket\n"); errorcode = SOCKERR; return -1; } memset(&unix_addr, 0, sizeof(unix_addr)); unix_addr.sun_family = AF_UNIX; if (hostname == NULL || *hostname == '\0') { path = UNIX_DOMAIN_PATH; } else { path = hostname; } snprintf(unix_addr.sun_path, sizeof(unix_addr.sun_path), "%s/.s.PGSQL.%d", path, port); if (connect(fd, (struct sockaddr *) &unix_addr, sizeof(unix_addr)) < 0) { if (debug) fprintf(stderr, "DEBUG: could not connect to \"%s\"\n", unix_addr.sun_path); close(fd); errorcode = CONNERR; return -1; } } else { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { if (debug) fprintf(stderr, "DEBUG: could not create socket\n"); errorcode = SOCKERR; return -1; } if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) { if (debug) fprintf(stderr, "DEBUG: could not set socket option\n"); close(fd); errorcode = SOCKERR; return -1; } memset((char *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; hp = gethostbyname(hostname); if ((hp == NULL) || (hp->h_addrtype != AF_INET)) { if (debug) fprintf(stderr, "DEBUG: could not retrieve hostname\n"); close(fd); errorcode = HOSTERR; return -1; } memmove((char *) &(addr.sin_addr), (char *) hp->h_addr, hp->h_length); addr.sin_port = htons(port); len = sizeof(struct sockaddr_in); if (connect(fd, (struct sockaddr *) &addr, len) < 0) { if (debug) fprintf(stderr, "DEBUG: could not connect to \"%s\"\n", hostname); close(fd); errorcode = CONNERR; return -1; } } pc = pcp_open(fd); if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: could not allocate buffer space\n"); close(fd); return -1; } if (pcp_authorize(username, password) < 0) { pcp_close(pc); pc = NULL; return -1; } return 0; }
/* pcp command processor */ static void pcp_process_command(char tos, char *buf, int buf_len) { if (tos == 'C' || tos == 'd' || tos == 'D' || tos == 'j' || tos == 'J' || tos == 'O' || tos == 'T') { if (Req_info->switching) { if(Req_info->request_queue_tail != Req_info->request_queue_head) { POOL_REQUEST_KIND reqkind; reqkind = Req_info->request[(Req_info->request_queue_head +1) % MAX_REQUEST_QUEUE_SIZE].kind; if (reqkind == NODE_UP_REQUEST) ereport(ERROR, (errmsg("failed to process PCP request at the moment"), errdetail("failback is in progress"))); else if (reqkind == NODE_DOWN_REQUEST) ereport(ERROR, (errmsg("failed to process PCP request at the moment"), errdetail("failover is in progress"))); else if (reqkind == PROMOTE_NODE_REQUEST) ereport(ERROR, (errmsg("failed to process PCP request at the moment"), errdetail("promote node operation is in progress"))); ereport(ERROR, (errmsg("failed to process PCP request at the moment"), errdetail("operation is in progress"))); } } } switch (tos) { case 'A': /* set configuration parameter */ set_ps_display("PCP: processing set configration parameter request", false); process_set_configration_parameter(pcp_frontend,buf,buf_len); break; case 'L': /* node count */ set_ps_display("PCP: processing node count request", false); inform_node_count(pcp_frontend); break; case 'I': /* node info */ set_ps_display("PCP: processing node info request", false); inform_node_info(pcp_frontend, buf); break; case 'N': /* process count */ set_ps_display("PCP: processing process count request", false); inform_process_count(pcp_frontend); break; case 'P': /* process info */ set_ps_display("PCP: processing process info request", false); inform_process_info(pcp_frontend, buf); break; case 'W': /* watchdog info */ set_ps_display("PCP: processing watchdog info request", false); inform_watchdog_info(pcp_frontend, buf); break; case 'D': /* detach node */ case 'd': /* detach node gracefully */ set_ps_display("PCP: processing detach node request", false); process_detach_node(pcp_frontend, buf, tos); break; case 'C': /* attach node */ set_ps_display("PCP: processing attach node request", false); process_attach_node(pcp_frontend, buf); break; case 'T': set_ps_display("PCP: processing shutdown request", false); process_shutown_request(pcp_frontend, buf[0]); break; case 'O': /* recovery request */ set_ps_display("PCP: processing recovery request", false); process_recovery_request(pcp_frontend, buf); break; case 'B': /* status request*/ set_ps_display("PCP: processing status request request", false); process_status_request(pcp_frontend); break; case 'J': /* promote node */ case 'j': /* promote node gracefully */ set_ps_display("PCP: processing promote node request", false); process_promote_node(pcp_frontend,buf,tos); break; case 'F': ereport(DEBUG1, (errmsg("PCP processing request, stop online recovery"))); break; case 'X': /* disconnect */ ereport(DEBUG1, (errmsg("PCP processing request, client disconnecting"), errdetail("closing PCP connection, and exiting child"))); pcp_close(pcp_frontend); pcp_frontend = NULL; /* This child has done its part. Rest in peace now */ exit(0); break; default: ereport(FATAL, (errmsg("PCP processing request"), errdetail("unknown PCP packet type \"%c\"",tos))); } }
PCPConnInfo* pcp_connect(char *hostname, int port, char *username, char *password, FILE *Pfdebug) { struct sockaddr_in addr; struct sockaddr_un unix_addr; struct hostent *hp; char *password_fron_file = NULL; char os_user[256]; PCPConnInfo* pcpConn = palloc0(sizeof(PCPConnInfo)); int fd; int on = 1; int len; pcpConn->connState = PCP_CONNECTION_NOT_CONNECTED; pcpConn->Pfdebug = Pfdebug; if (hostname == NULL || *hostname == '\0' || *hostname == '/') { char *path; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { pcp_internal_error(pcpConn, "ERROR: failed to create UNIX domain socket. socket error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } memset(&unix_addr, 0, sizeof(unix_addr)); unix_addr.sun_family = AF_UNIX; if (hostname == NULL || *hostname == '\0') { path = UNIX_DOMAIN_PATH; hostname = path; } else { path = hostname; } snprintf(unix_addr.sun_path, sizeof(unix_addr.sun_path), "%s/.s.PGSQL.%d", path, port); if (connect(fd, (struct sockaddr *) &unix_addr, sizeof(unix_addr)) < 0) { close(fd); pcp_internal_error(pcpConn, "ERROR: connection to socket \"%s\" failed with error \"%s\"",unix_addr.sun_path,strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } } else { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { pcp_internal_error(pcpConn, "ERROR: failed to create INET domain socket with error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) { close(fd); pcp_internal_error(pcpConn, "ERROR: set socket option failed with error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } memset((char *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; hp = gethostbyname(hostname); if ((hp == NULL) || (hp->h_addrtype != AF_INET)) { close(fd); pcp_internal_error(pcpConn, "ERROR: could not retrieve hostname. gethostbyname failed with error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } memmove((char *) &(addr.sin_addr), (char *) hp->h_addr, hp->h_length); addr.sin_port = htons(port); len = sizeof(struct sockaddr_in); if (connect(fd, (struct sockaddr *) &addr, len) < 0) { close(fd); pcp_internal_error(pcpConn, "ERROR: connection to host \"%s\" failed with error \"%s\"",hostname,strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } } pcpConn->pcpConn = pcp_open(fd); if (pcpConn->pcpConn == NULL) { close(fd); pcp_internal_error(pcpConn, "ERROR: failed to allocate memory"); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } pcpConn->connState = PCP_CONNECTION_CONNECTED; /* * If username is not provided. Use the os user name * and do not complain if it (getting os user name) gets failed */ if (username == NULL && get_os_username(os_user, sizeof(os_user))) username = os_user; /* * If password is not provided. lookup in pcppass file */ if (password == NULL || *password == '\0') { char port_str[100]; snprintf(port_str, sizeof(port_str), "%d",port); password_fron_file = PasswordFromFile(pcpConn, hostname, port_str, username); password = password_fron_file; } if (pcp_authorize(pcpConn,username, password) < 0) { pcp_close(pcpConn->pcpConn); pcpConn->pcpConn = NULL; pcpConn->connState = PCP_CONNECTION_AUTH_ERROR; } else pcpConn->connState = PCP_CONNECTION_OK; if(password_fron_file) pfree(password_fron_file); return pcpConn; }
int main(int argc, char **argv) { int argn=1; static const char * const authvars[]={NULL}; signal(SIGPIPE, SIG_IGN); umask(022); if (argn >= argc) { struct PCP *pcp; pcp=open_calendar(NULL); mainloop(pcp); exit(0); } maildir_cache_init(TIMEOUT * 2, CACHEDIR, LOCALCACHEOWNER, authvars); if (strcmp(argv[argn], "start") == 0) { struct group *gr; if (chdir(CALENDARDIR) < 0) { perror(CALENDARDIR); exit(1); } gr=getgrnam(MAILGROUP); if (!gr) { fprintf(stderr, "Unknown group: %s\n", MAILGROUP); exit(1); } authtoken_init(); libmail_changeuidgid(getuid(), gr->gr_gid); start(); } else if (strcmp(argv[argn], "login") == 0 || strcmp(argv[argn], "slogin") == 0) { struct PCP *pcp; int flag; struct group *gr; gr=getgrnam(MAILGROUP); if (!gr) { fprintf(stderr, "Unknown group: %s\n", MAILGROUP); exit(1); } libmail_changeuidgid(getuid(), gr->gr_gid); if (chdir(CALENDARDIR) < 0) { perror(CALENDARDIR); exit(1); } authtoken_init(); userid=login(strcmp(argv[argn], "login"), &flag); pcp=pcp_open_dir(".", userid); if (pcp && flag && pcp_cleanup(pcp)) { pcp_close(pcp); syslog(LOG_CRIT, "pcpd: pcp_cleanup failed"); pcp=NULL; } if (!pcp) { syslog(LOG_CRIT, "pcpd: pcp_open_dir failed"); perror("pcp_open_dir"); exit(1); } mainloop(pcp); exit(0); } else if (strcmp(argv[argn], "stop") == 0) { if (chdir(CALENDARDIR) < 0) { perror(CALENDARDIR); exit(1); } ll_daemon_stop(LOCKFILE, PIDFILE); exit(0); } else if (strcmp(argv[argn], "open") == 0) { ++argn; if (argn < argc) { struct PCP *pcp; pcp=open_calendar(argv[argn]); mainloop(pcp); exit(0); } } fprintf(stderr, "Usage: %s (start|stop|open [path])\n", argv[0]); exit(1); return (0); }
static void accept_pcpd(int sock, int pubsock, int privsock, int flag) { int fd; pid_t pid; struct PCP *pcp; if ((fd=accept_sock(sock)) < 0) return; if (fcntl(fd, F_SETFL, 0) < 0) { syslog(LOG_CRIT, "pcpd: fcntl() failed: %m"); close(fd); return; } maildir_cache_purge(); pid=fork(); if (pid < 0) { syslog(LOG_CRIT, "pcpd: fork() failed: %m"); close(fd); return; } if (pid) { close(fd); return; /* Parent resumes listening */ } /* child */ close(pubsock); close(privsock); close(0); if (dup(fd) != 0) exit(0); close(1); if (dup(fd) != 1) exit(0); close(fd); userid=login(flag, &flag); pcp=pcp_open_dir(".", userid); if (pcp && flag && pcp_cleanup(pcp)) { pcp_close(pcp); syslog(LOG_CRIT, "pcpd: pcp_cleanup failed"); pcp=NULL; } if (!pcp) { syslog(LOG_CRIT, "pcpd: pcp_open_dir failed"); perror("pcp_open_dir"); exit(1); } mainloop(pcp); exit(0); }