/* file: daemon.c G. Moody 24 February 2012 Last revised: 15 May 2017 main() and other functions for the PhysioBank Simple Query Server daemon */ #include "pbsqs.h" #include #include #include #include #include #include #include #include #define SERV_TCP_PORT 9967 #define SERV_HOST_ADDR "127.0.0.1" /* localhost */ void newline() { fprintf(ofile, "\n"); } int reload = 1; void reload_handler(int dummy) { reload = 1; } static void fatal(const char *message) { syslog(LOG_ERR, "pbsqs: %s: %s", message, strerror(errno)); exit(1); } main(int argc, char **argv) { int sockfd, newsockfd, clilen, childpid; struct sockaddr_in cli_addr, serv_addr; int matches, qc = 0, status = 1; /* Drop into the background, close stdio, detach from terminal. */ daemon(0, 0); /* Open a TCP socket */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) fatal("can't open stream socket"); clilen = sizeof(cli_addr); /* Bind our local address so that the client can send to us */ bzero((char *)&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(SERV_TCP_PORT); if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) fatal("can't bind local address"); ofile = efile = fdopen(sockfd, "w+"); signal(SIGHUP, &reload_handler); signal(SIGCHLD, SIG_IGN); if (listen(sockfd, 5) < 0) fatal("can't listen on local port"); while (1) { static char *p, *r, qbuf[64]; Query q; if (reload) { cleanup(); (void)geturl(PBI_URL, &indeximg); /* (re)read the index */ (void)parsepbi(); /* ... and parse it */ reload = 0; } /* wait for a connection from a client process */ newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); if (newsockfd < 0) fatal("accept error"); if ((childpid = fork()) < 0) fatal("fork error"); else if (childpid == 0) { /* child process */ close(sockfd); signal(SIGCHLD, SIG_DFL); /* Set up for stream I/O via the socket. */ ofile = efile = fdopen(newsockfd, "w+"); ifile = fdopen(dup(newsockfd), "r+"); fprintf(ofile, "pbs>\n"); fflush(ofile); p = r = fgets(qbuf, sizeof(qbuf), ifile); while (r && r < p + sizeof(qbuf) && *r != '\r' && *r != '\n') r++; if (r && *r) *r = '\0'; q = parsequery(p); matches = -1; verbose = 1; switch (q.type) { case qt_count: showlist = 0; matches = search(q); qc++; break; case qt_list: showlist = 1; matches = search(q); qc++; break; case qt_long: showlist = 2; matches = search(q); qc++; break; case qt_help: help(q); break; case qt_exit: case qt_null: default: break; } if (matches >= 0 && showlist == 0) fprintf(ofile, "%d match%s for query: %s %s %s\n", matches, (matches == 1 ? "" : "es"), q.iname, rn[q.comp].name, q.sval); fprintf(ofile, "pbs>\n"); fflush(ofile); close(newsockfd); exit(0); } close(newsockfd); /* parent process */ } /* We should never get here! Child processes take one trip through the code and exit, and the parent process loops indefinitely. */ cleanup(); exit(0); }