/** * @retval 0 Success. * @retval LDM7_INVAL No multicast sender child process exists. */ static int terminateMcastSender(void) { int status; /* * Terminate the multicast sender process by sending a SIGTERM to the * process group. */ { struct sigaction oldSigact; struct sigaction newSigact; status = sigemptyset(&newSigact.sa_mask); CU_ASSERT_EQUAL_FATAL(status, 0); udebug("Setting SIGTERM action to ignore"); newSigact.sa_flags = 0; newSigact.sa_handler = SIG_IGN; status = sigaction(SIGTERM, &newSigact, &oldSigact); CU_ASSERT_EQUAL_FATAL(status, 0); udebug("Sending SIGTERM to process group"); status = kill(0, SIGTERM); CU_ASSERT_EQUAL_FATAL(status, 0); udebug("Restoring SIGTERM action"); status = sigaction(SIGTERM, &oldSigact, NULL); CU_ASSERT_EQUAL(status, 0); } /* Reap the terminated multicast sender. */ { udebug("Reaping multicast sender child process"); const pid_t wpid = wait(&status); if (wpid == (pid_t)-1) { CU_ASSERT_EQUAL(errno, ECHILD); status = LDM7_INVAL; } else { CU_ASSERT_TRUE_FATAL(wpid > 0); CU_ASSERT_TRUE(WIFEXITED(status)); CU_ASSERT_EQUAL(WEXITSTATUS(status), 0); status = mlsm_terminated(wpid); CU_ASSERT_EQUAL(status, 0); } } return status; }
void *decode_suomi(char *infilnam, long miss, int *iret) { int ier,cdfid; static int isinit=0; suomi_struct *head; if(isinit == 0) { isinit = -1; putenv("TZ=UTC0"); tzset(); } ier = nc_open(infilnam,0,&cdfid); if(ier != 0) { *iret = -1; uerror("Could not open %s\0",infilnam); return(NULL); } udebug("decode_suomi %s miss %ld ier %d cdfid %d\0",infilnam,miss,ier,cdfid); head = decode_ncsuomi(cdfid,miss,&ier); ier = nc_close(cdfid); *iret = 0; return(head); }
static int servlet_run( const int servSock) { /* NULL-s => not interested in receiver's address */ int sock = accept(servSock, NULL, NULL); int status; CU_ASSERT_NOT_EQUAL_FATAL(sock, -1); pthread_cleanup_push(closeSocket, &sock); Up7 up7; status = up7_init(&up7, sock); CU_ASSERT_EQUAL_FATAL(status, 0); pthread_cleanup_push(destroyUp7, &up7); // calls `up7_destroy()` status = up7_run(&up7); // might call `svc_destroy(up7->xprt)` CU_ASSERT_EQUAL(status, 0); pthread_cleanup_pop(1); // might call `svc_destroy(up7->xprt)` pthread_cleanup_pop(0); // `sock` already closed udebug("servlet_run(): Returning"); return 0; }
static pid_t run_child(int argc, char *argv[]) { pid_t pid; if(ulogIsDebug()) { char command[1024]; size_t left = sizeof(command) - 1; int ii; command[0] = 0; for (ii = 0; ii < argc; ++ii) { size_t nbytes; if (ii > 0) { (void)strncat(command, " ", left); left -= (1 <= left) ? 1 : left; } (void)strncat(command, argv[ii], left); nbytes = strlen(argv[ii]); left -= (nbytes <= left) ? nbytes : left; } udebug("exec'ing: \"%s\"", command); } pid = ldmfork(); if(pid == -1) { log_log(LOG_ERR); return pid; } if(pid == 0) { /* child */ const unsigned ulogOptions = ulog_get_options(); const char* ulogIdent = getulogident(); const unsigned ulogFacility = getulogfacility(); const char* ulogPath = getulogpath(); (void)signal(SIGCHLD, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); /* keep same descriptors as parent */ /* don't let child get real privilege */ endpriv(); (void) execvp(argv[0], &argv[0]); openulog(ulogIdent, ulogOptions, ulogFacility, ulogPath); serror("run_child: execvp: %s", argv[0]); _exit(127); } /* else, parent */ return pid; }
static void hndlr_noop(int sig) { #ifndef NDEBUG switch(sig) { case SIGALRM : udebug("SIGALRM") ; return ; case SIGCONT : udebug("SIGCONT") ; return; } udebug("hndlr_noop: unhandled signal: %d", sig) ; #endif /* nothing to do, just wake up */ return; }
static void funcCancelled( void* const arg) { const char* funcName = (const char*)arg; udebug("funcCancelled(): %s() thread cancelled", funcName); }
static void termSigHandler( const int sig) { udebug("Caught signal %d", sig); setDoneCondition(); }
int *is_alive_6_svc( unsigned *id, struct svc_req *rqstp) { static int alive; SVCXPRT * const xprt = rqstp->rq_xprt; int error = 0; alive = cps_contains((pid_t) *id); if (ulogIsDebug()) { udebug("LDM %u is %s", *id, alive ? "alive" : "dead"); } if (!svc_sendreply(xprt, (xdrproc_t) xdr_bool, (caddr_t) &alive)) { svcerr_systemerr(xprt); error = 1; } if (!svc_freeargs(xprt, xdr_u_int, (caddr_t)id)) { uerror("Couldn't free arguments"); error = 1; } svc_destroy(xprt); exit(error); /*NOTREACHED*/ return NULL ; }
static void signal_handler( int sig) { switch (sig) { case SIGHUP: udebug("SIGHUP"); return; case SIGINT: udebug("SIGINT"); return; case SIGTERM: udebug("SIGTERM"); return; default: udebug("Signal %d", sig); return; } }
static void shmfifo_print (const struct shmhandle* const shm) { struct shmprefix *p; uerror ("My Shared Memory information:\n"); if (shm == NULL) { uerror ("Handle is NULL!\n"); return; } if (shm->mem == NULL) { uerror ("isn't attached to shared mem\n"); return; } p = (struct shmprefix *) shm->mem; uerror ("Segment id: %d\nMem: %p\nRead pos: %d\nWrite pos: %d\n", shm->sid, shm->mem, p->read, p->write); if (p->read == p->write) uerror ("No blocks in shared memory\n"); else { void *ptr = (char *) shm->mem + p->read; int count = 0; while (ptr != (char *) shm->mem + p->write) { struct shmbh *h = (struct shmbh *) ptr; count++; udebug ("block: %d ", count); udebug ("size: %d ", h->sz); /* printf("data: \"%s\" ",(char*)ptr + sizeof(struct shmbh)); */ /* printf("\n"); */ /*(char*)ptr += h->sz + sizeof(struct shmbh); */ ptr = (char *) ptr + h->sz + sizeof (struct shmbh); } /* printf("---\n"); */ } }
static void unlockMutex(void) { udebug("Unlocking mutex"); int status = pthread_mutex_unlock(&mutex); if (status) { LOG_ERRNUM0(status, "Couldn't unlock mutex"); abortProcess(); } }
/** * Sets a data-structure so that it references the shared-memory FIFO * associated with a (partial) key. * * @retval 0 Success. The data-structure is initialized and references the * shared-memory FIFO. * @retval -1 \e shm is \c NULL. An error message is logged. * @retval -2 \e nkey is \c -1. * @retval -3 The shared-memory FIFO doesn't exist. * @retval -4 The shared-memory FIFO couldn't be accessed. An error message * is logged. */ int shmfifo_shm_from_key( struct shmhandle* const shm, /**< Pointer to the data-structure to * be set. */ const int nkey) /**< The (partial) key associated with * the shared-memory FIFO. */ { int status; if (shm == NULL) { uerror ("shm_from_key(): shm is NULL"); status = -1; } else if (-1 == nkey) { status = -2; } else { key_t key = (key_t)(DVBS_ID + nkey); int semid = semget(key, SI_SEM_COUNT, 0660); if (-1 == semid) { status = -3; } else { int sid = shmget(key, 0, 0); if (-1 == sid) { status = -3; } else { shm->semid = semid; shm->sid = sid; if (shmfifo_attach(shm) == -1) { status = -4; } else { struct shmprefix* p = (struct shmprefix*)(shm->mem); shm->privsz = p->privsz; shm->sz = p->sz; udebug ("look sizes %d %d\n", shm->privsz, shm->sz); status = 0; /* success */ } /* got shared-memory FIFO */ } /* got shared-memory ID */ } /* got semaphore */ } /* valid "shm" and "nkey" */ return status; }
/* get_cpio_addr - Routine to get cpio address */ int get_cpio_addr(char *addr){ int i_row; for(i_row=0; i_row < NUM_CPIO_ENTRIES ; i_row++){ if(!strcmp(cpio_tbl[i_row].mcast_addr,addr)){ break; } } if(i_row >= NUM_CPIO_ENTRIES){ i_row = -1; uerror("\n Fail to find match for cpio addr=%s\n",addr); } udebug("returning i_row = %d",i_row); return (i_row); }
static pid_t run_child(int argc, char *argv[]) { pid_t pid; if(ulogIsDebug()) { char command[1024]; char *cp = command; int ii = 0; command[0] = 0; while (ii < argc) { strcpy(cp, argv[ii]); cp += strlen(argv[ii]); if(++ii == argc) break; *cp++ = ' '; *cp = 0; } udebug("exec'ing: \"%s\"", command); } pid = ldmfork(); if(pid == -1) { log_log(LOG_ERR); return pid; } if(pid == 0) { /* child */ (void)signal(SIGCHLD, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); /* keep same descriptors as parent */ /* don't let child get real privilege */ endpriv(); (void) execvp(argv[0], &argv[0]); serror("run_child: execvp: %s", argv[0]); _exit(127); } /* else, parent */ return pid; }
/* * Logs shared-memory usage statistics at level DEBUG. * * Precondition: * The FIFO is locked by this process. An error-message is logged if it * isn't. * Arguments: * shm Pointer to the shared-memory FIFO data-structure. */ static void shmfifo_printmemstatus( const struct shmhandle* const shm) { if (ulogIsDebug()) { struct shmprefix* p = (struct shmprefix*)shm->mem; (void)checkLocked(shm); udebug ("<%d> c: %d sz: %d, r: %d, w: %d, used: %d, free: %d, maxblock: %d", getpid (), p->counter, shm->sz, p->read, p->write, shmfifo_ll_memused (shm), shmfifo_ll_memfree (shm), shmfifo_ll_memfree (shm) - sizeof (struct shmbh)); } }
/* * Send a data-product to an LDM using the LDM-6 HEREIS message. * * Arguments: * proxy Pointer to the LDM proxy data-structure. * product Pointer to the data-product to be sent. * Return: * 0 Success. * LP_TIMEDOUT RPC timeout. "log_start()" called. * LP_RPC_ERROR RPC error. "log_start()" called. * LP_LDM_ERROR LDM error. "log_start()" called. */ static LdmProxyStatus my_hereis_6( LdmProxy* const proxy, product* const product) { LdmProxyStatus status = 0; /* success */ udebug("Sending file via HEREIS_6"); if (NULL == hereis_6(product, proxy->clnt)) { status = getStatus(proxy, "HEREIS_6", &product->info); } return status; }
static void setDoneCondition(void) { lockMutex(); done = 1; udebug("Signaling condition variable"); int status = pthread_cond_broadcast(&cond); if (status) { LOG_ERRNUM0(status, "Couldn't signal condition variable"); abortProcess(); } unlockMutex(); }
/** * Called by `pthread_create()`. The thread is cancelled by * `sender_terminate()`. * * @param[in] arg Pointer to sender. * @retval &0 Success. Input end of sender's termination pipe(2) is closed. */ static void* sender_run( void* const arg) { Sender* const sender = (Sender*)arg; static int status; pthread_cleanup_push(freeLogging, NULL); const int servSock = sender->sock; struct pollfd fds; fds.fd = servSock; fds.events = POLLIN; for (;;) { status = poll(&fds, 1, -1); // `-1` => indefinite timeout int cancelState; (void)pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState); if (0 > status) break; if (fds.revents & POLLHUP) { status = 0; break; } if (fds.revents & POLLIN) { status = servlet_run(servSock); if (status) { LOG_ADD0("servlet_run() failure"); break; } } (void)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelState); } // `poll()` loop /* Because the current thread is ending: */ (status && !done) ? log_log(LOG_ERR) : log_clear(); // don't care about errors if termination requested pthread_cleanup_pop(1); // calls `log_free()` udebug("sender_run(): Returning &%d", status); return &status; }
static void waitForDoneCondition(void) { lockMutex(); while (!done) { udebug("Waiting on condition variable"); int status = pthread_cond_wait(&cond, &mutex); if (status) { LOG_ERRNUM0(status, "Couldn't wait on condition variable"); abortProcess(); } } unlockMutex(); }
/* * Sends a data-product to an LDM using the LDM-6 COMINGSOON and BLOCKDATA * messages. * * Arguments: * proxy Pointer to the LDM proxy data-structure. * product Pointer to the data-product to be sent. * Return: * 0 Success. * LP_UNWANTED Data-product was unwanted. * LP_TIMEDOUT The RPC call timed-out. "log_start()" called. * LP_RPC_ERROR RPC error. "log_start()" called. * LP_LDM_ERROR LDM error. "log_start()" called. */ static LdmProxyStatus my_csbd_6( LdmProxy* const proxy, product* const product) { LdmProxyStatus status = 0; /* success */ CLIENT* const clnt = proxy->clnt; prod_info* const info = &product->info; const unsigned size = info->sz; comingsoon_reply_t* reply; comingsoon_args soonArg; udebug("Sending file via COMINGSOON_6/BLKDATA_6"); soonArg.infop = info; soonArg.pktsz = size; reply = comingsoon_6(&soonArg, clnt); if (NULL == reply) { status = getStatus(proxy, "COMINGSOON_6", &product->info); } else { if (DONT_SEND == *reply) { status = LP_UNWANTED; } else if (0 != *reply) { LOG_START1("Unexpected reply from LDM: %s", s_ldm_errt(*reply)); status = LP_LDM_ERROR; } else { datapkt packet; packet.signaturep = (signaturet*)&info->signature; packet.pktnum = 0; packet.data.dbuf_len = size; packet.data.dbuf_val = product->data; if (NULL == blkdata_6(&packet, clnt)) status = getStatus(proxy, "BLKDATA_6", &product->info); } } return status; }
int peek_ahead(xbuf *buf) { int i, j, k, ic[4], isstart=1; static int IC[4]={SOH, CR, CR, NL}; static int TC[4]={CR, CR, NL, ETX}; static int UH[4]={NL, SOH, CR, CR}; /* * If there are at least 4 more characters in the buffer, and * they are not the start sequence for the next product, then * we may still be in the previous product. If there are fewer * than 4 characters in the buffer, assume we did find the end. */ for(i=0;i<4;i++) { ic[i] = nextc(buf); j = i; if(ic[i] == EOB) { isstart = 1; break; } if((ic[i] != TC[i])&&(ic[i] != IC[i])&&(ic[i] != UH[i])) isstart = 0; } for(i=j;i>=0;i--) { if(ic[i] != EOB) { k = unnextc(buf,ic[i]); if(k != ic[i]) uerror("Error in peek_ahead unnext: %d %d\0",ic[i],k); } if(isstart == 0) udebug("Peek_ahead check %d %d\0",i,ic[i]); } if(isstart) return(1); else return(0); }
static int doOne(const prod_info *infop, const void *datap) { struct product prod; int status = ENOERR; if(ulogIsDebug()) udebug("%s", s_prod_info(NULL, 0, infop, 1)); prod.info = *infop; prod.data = (void *)datap; /* cast away const */ nsplit++; /* ?? Do it here on only on success ?? */ status = pq_insertNoSig(opq, &prod); if(status == ENOERR) { return status; /* Normal return */ } /* else */ if(status == PQUEUE_DUP) { ndups++; if(ulogIsVerbose()) uinfo("Product already in queue: %s", s_prod_info(NULL, 0, &prod.info, ulogIsDebug())); return status; } /* else, error */ uerror("pq_insert: %s\n", strerror(status)); return status; }
int main( int ac, char* av[]) { const char* pqfname = getQueuePath(); int status; int doSomething = 1; in_addr_t ldmIpAddr = (in_addr_t) htonl(INADDR_ANY ); unsigned ldmPort = LDM_PORT; ensureDumpable(); /* * deal with the command line, set options */ { extern int optind; extern int opterr; extern char *optarg; int ch; int logmask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_NOTICE); opterr = 1; while ((ch = getopt(ac, av, "I:vxl:nq:o:P:M:m:t:")) != EOF) { switch (ch) { case 'I': { in_addr_t ipAddr = inet_addr(optarg); if ((in_addr_t) -1 == ipAddr) { (void) fprintf(stderr, "Interface specification \"%s\" " "isn't an IP address\n", optarg); exit(1); } ldmIpAddr = ipAddr; break; } case 'v': logmask |= LOG_MASK(LOG_INFO); break; case 'x': logmask |= LOG_MASK(LOG_DEBUG); break; case 'l': logfname = optarg; break; case 'q': pqfname = optarg; setQueuePath(optarg); break; case 'o': toffset = atoi(optarg); if (toffset == 0 && *optarg != '0') { (void) fprintf(stderr, "%s: invalid offset %s\n", av[0], optarg); usage(av[0]); } break; case 'P': { unsigned port; int nbytes; if (sscanf(optarg, "%5u %n", &port, &nbytes) != 1 || 0 != optarg[nbytes] || port > 0xffff) { (void)fprintf(stderr, "%s: invalid port number: %s\n", av[0], optarg); usage(av[0]); } ldmPort = port; break; } case 'M': { int max = atoi(optarg); if (max < 0) { (void) fprintf(stderr, "%s: invalid maximum number of clients %s\n", av[0], optarg); usage(av[0]); } maxClients = max; break; } case 'm': max_latency = atoi(optarg); if (max_latency <= 0) { (void) fprintf(stderr, "%s: invalid max_latency %s\n", av[0], optarg); usage(av[0]); } break; case 'n': doSomething = 0; break; case 't': rpctimeo = (unsigned) atoi(optarg); if (rpctimeo == 0 || rpctimeo > 32767) { (void) fprintf(stderr, "%s: invalid timeout %s", av[0], optarg); usage(av[0]); } break; case '?': usage(av[0]); break; } /* "switch" statement */ } /* argument loop */ if (ac - optind == 1) setLdmdConfigPath(av[optind]); (void) setulogmask(logmask); if (toffset != TOFFSET_NONE && toffset > max_latency) { (void) fprintf(stderr, "%s: invalid toffset (%d) > max_latency (%d)\n", av[0], toffset, max_latency); usage(av[0]); } } /* command-line argument decoding */ if (logfname != NULL && *logfname == '-') { /* * Logging to standard error stream. Assume interactive. * * Make this process a process group leader so that all child processes * (e.g., upstream LDM, downstream LDM, pqact(1)s) will be signaled by * `cleanup()`. */ (void)setpgid(0, 0); // can't fail } #ifndef DONTFORK else { /* * Logging to system logging daemon or file. Make this process a daemon. */ pid_t pid; pid = ldmfork(); if (pid == -1) { log_add("Couldn't fork LDM daemon"); log_log(LOG_ERR); exit(2); } if (pid > 0) { /* parent */ (void) printf("%ld\n", (long) pid); exit(0); } /* detach the child from parents process group ?? */ (void) setsid(); // also makes this process a process group leader } #endif /* * Initialize logger. * (Close fd 2 to remap stderr to the logfile, when * appropriate. I know, this is anal.) */ if (logfname == NULL ) (void) fclose(stderr); else if (!(logfname[0] == '-' && logfname[1] == 0)) (void) close(2); (void) openulog(ubasename(av[0]), (LOG_CONS | LOG_PID), LOG_LDM, logfname); unotice("Starting Up (version: %s; built: %s %s)", PACKAGE_VERSION, __DATE__, __TIME__); /* * register exit handler */ if (atexit(cleanup) != 0) { serror("atexit"); unotice("Exiting"); exit(1); } /* * set up signal handlers */ set_sigactions(); /* * Close the standard input and standard output streams because they won't * be used (more anality :-) */ (void) fclose(stdout); (void) fclose(stdin); /* * Vet the configuration file. */ udebug("main(): Vetting configuration-file"); if (read_conf(getLdmdConfigPath(), 0, ldmIpAddr, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } if (doSomething) { int sock = -1; if (lcf_isServerNeeded()) { /* * Create a service portal. This should be done before anything is * created because this is the function that relinquishes superuser * privileges. */ udebug("main(): Creating service portal"); if (create_ldm_tcp_svc(&sock, ldmIpAddr, ldmPort) != ENOERR) { /* error reports are emitted from create_ldm_tcp_svc() */ exit(1); } udebug("tcp sock: %d", sock); } /* * Verify that the product-queue can be open for writing. */ udebug("main(): Opening product-queue"); if ((status = pq_open(pqfname, PQ_DEFAULT, &pq))) { if (PQ_CORRUPT == status) { uerror("The product-queue \"%s\" is inconsistent", pqfname); } else { uerror("pq_open failed: %s: %s", pqfname, strerror(status)); } exit(1); } (void) pq_close(pq); pq = NULL; /* * Create the sharable database of upstream LDM metadata. */ udebug("main(): Creating shared upstream LDM database"); if ((status = uldb_delete(NULL))) { if (ULDB_EXIST == status) { log_clear(); } else { LOG_ADD0( "Couldn't delete existing shared upstream LDM database"); log_log(LOG_ERR); exit(1); } } if (uldb_create(NULL, maxClients * 1024)) { LOG_ADD0("Couldn't create shared upstream LDM database"); log_log(LOG_ERR); exit(1); } /* * Initialize the multicast sender map. */ #if WANT_MULTICAST if (msm_init()) { LOG_ADD0("Couldn't initialize multicast LDM sender map"); log_log(LOG_ERR); exit(1); } #endif /* * Re-read (and execute) the configuration file (downstream LDM-s are * started). */ lcf_free(); // Start with a clean slate to prevent duplicates udebug("main(): Reading configuration-file"); if (read_conf(getLdmdConfigPath(), 1, ldmIpAddr, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } if (lcf_isServerNeeded()) { /* * Serve */ udebug("main(): Serving socket"); sock_svc(sock); } else { /* * Wait until all child processes have terminated. */ while (reap(-1, 0) > 0) /* empty */; } } // configuration-file will be executed return (0); }
/* * Create a TCP socket, bind it to a port, call 'listen' (we are a * server), and inform the portmap (rpcbind) service. Does _not_ create * an RPC SVCXPRT or do the xprt_register() or svc_fds() stuff. * * Arguments: * sockp Pointer to socket (file) descriptor. Set on and only on * success. * localIpAddr The IP address, in network byte order, of the * local interface to use. May be htonl(INADDR_ANY). * localPort The number of the local port on which the LDM server * should listen. * Returns: * 0 Success. * EACCES The process doesn't have appropriate privileges. * EADDRINUSE The local address is already in use. * EADDRNOTAVAIL The specified address is not available from the local * machine. * EAFNOSUPPORT The system doesn't support IP. * EMFILE No more file descriptors are available for this process. * ENFILE No more file descriptors are available for the system. * ENOBUFS Insufficient resources were available in the system. * ENOMEM Insufficient memory was available. * ENOSR There were insufficient STREAMS resources available. * EOPNOTSUPP The socket protocol does not support listen(). * EPROTONOSUPPORT The system doesn't support TCP. */ static int create_ldm_tcp_svc( int* sockp, in_addr_t localIpAddr, unsigned localPort) { int error = 0; /* success */ int sock; /* * Get a TCP socket. */ udebug("create_ldm_tcp_svc(): Getting TCP socket"); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { error = errno; serror("Couldn't get socket for server"); } else { unsigned short port = (unsigned short) localPort; struct sockaddr_in addr; socklen_t len = sizeof(addr); /* * Eliminate problem with EADDRINUSE for reserved socket. * We get this if an upstream data source hasn't tried to * write on the other end and we are in FIN_WAIT_2 */ udebug("create_ldm_tcp_svc(): Eliminating EADDRINUSE problem."); { int on = 1; (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); } (void) memset(&addr, 0, len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = localIpAddr; addr.sin_port = (short) htons((short) port); /* * If privilege available, set it so we can bind to the port for LDM * services. Also needed for the pmap_set() call. */ udebug("create_ldm_tcp_svc(): Getting root privs"); rootpriv(); udebug("create_ldm_tcp_svc(): Binding socket"); if (bind(sock, (struct sockaddr *) &addr, len) < 0) { error = errno; serror("Couldn't obtain local address %s:%u for server", inet_ntoa(addr.sin_addr), (unsigned) port); if (error == EACCES) { error = 0; addr.sin_port = 0; /* let system assign port */ if (bind(sock, (struct sockaddr *) &addr, len) < 0) { error = errno; serror("Couldn't obtain local address %s:* for server", inet_ntoa(addr.sin_addr)); } } /* requested port is reserved */ } /* couldn't bind to requested port */ if (!error) { /* * Get the local address associated with the bound socket. */ udebug("create_ldm_tcp_svc(): Calling getsockname()"); if (getsockname(sock, (struct sockaddr *) &addr, &len) < 0) { error = errno; serror("Couldn't get local address of server's socket"); } else { port = (short) ntohs((short) addr.sin_port); unotice("Using local address %s:%u", inet_ntoa(addr.sin_addr), (unsigned) port); udebug("create_ldm_tcp_svc(): Calling listen()"); if (listen(sock, 32) != 0) { error = errno; serror("Couldn't listen() on server's socket"); } else { /* * Register with the portmapper if it's running. The * check to see if it's running is made because on a * FreeBSD 4.7-STABLE system, a pmap_set() call takes * one minute even if the portmapper isn't running. */ udebug("create_ldm_tcp_svc(): Checking portmapper"); if (local_portmapper_running()) { udebug("create_ldm_tcp_svc(): Registering"); if (pmap_set(LDMPROG, 6, IPPROTO_TCP, port) == 0) { uwarn("Can't register TCP service %lu on " "port %u", LDMPROG, (unsigned) port); uwarn("Downstream LDMs won't be able to " "connect via the RPC portmapper daemon " "(rpcbind(8), portmap(8), etc.)"); } else { portIsMapped = 1; (void) pmap_set(LDMPROG, 5, IPPROTO_TCP, port); } } /* a local portmapper is running */ /* * Done with the need for privilege. */ udebug("create_ldm_tcp_svc(): Releasing root privs"); unpriv(); *sockp = sock; } /* listen() success */ } /* getsockname() success */ } /* "sock" is bound to local address */ if (error) (void) close(sock); } /* "sock" is open */ return error; }
hiya_reply_t* hiya_6_svc( prod_class_t *offered, struct svc_req *rqstp) { const char* const pqfname = getQueuePath(); static hiya_reply_t reply; SVCXPRT * const xprt = rqstp->rq_xprt; struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt); const char *upName = hostbyaddr(upAddr); int error; int isPrimary; unsigned int maxHereis; static prod_class_t *accept; /* * Open the product-queue for writing. It will be closed by cleanup() * during process termination. */ if (pq) { (void) pq_close(pq); pq = NULL; } error = pq_open(pqfname, PQ_DEFAULT, &pq); if (error) { err_log_and_free(ERR_NEW2(error, NULL, "Couldn't open product-queue \"%s\" for writing: %s", pqfname, PQ_CORRUPT == error ? "The product-queue is inconsistent" : strerror(error)), ERR_FAILURE); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } /* else */ error = down6_init(upName, upAddr, pqfname, pq); if (error) { uerror("Couldn't initialize downstream LDM"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { uinfo("Downstream LDM initialized"); } /* * The previous "accept" is freed here -- rather than freeing the * soon-to-be-allocated "accept" at the end of its block -- because it can * be used in the reply. */ if (accept) { free_prod_class(accept); /* NULL safe */ accept = NULL; } error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered, &accept, &isPrimary); maxHereis = isPrimary ? UINT_MAX : 0; if (error) { serror("Couldn't validate HIYA"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { if (ulogIsDebug()) udebug("intersection: %s", s_prod_class(NULL, 0, accept)); if (accept->psa.psa_len == 0) { uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT " "entries", upName, s_prod_class(NULL, 0, offered)); svcerr_weakauth(xprt); svc_destroy(xprt); exit(0); } else { error = down6_set_prod_class(accept); if (error) { if (DOWN6_SYSTEM_ERROR == error) { serror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } else { uerror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } svcerr_systemerr(xprt); svc_destroy(xprt); exit(EXIT_FAILURE); } /* else */ if (clss_eq(offered, accept)) { unotice("hiya6: %s", s_prod_class(NULL, 0, offered)); reply.code = OK; reply.hiya_reply_t_u.max_hereis = maxHereis; } else { if (ulogIsVerbose()) { char off[512]; char acc[512]; (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class( acc, sizeof(acc), accept); uinfo("hiya6: RECLASS: %s -> %s", off, acc); } reply.code = RECLASS; reply.hiya_reply_t_u.feedPar.prod_class = accept; reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis; } } /* product-intersection != empty set */ } /* successful acl_check_hiya() */ return &reply; }
int main( int ac, char* av[]) { const char* pqfname = getQueuePath(); int sock = -1; int status; int doSomething = 1; in_addr_t locIpAddr = (in_addr_t) htonl(INADDR_ANY ); unsigned ldmPort = LDM_PORT; ensureDumpable(); /* * deal with the command line, set options */ { extern int optind; extern int opterr; extern char *optarg; int ch; int logmask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_NOTICE); opterr = 1; while ((ch = getopt(ac, av, "I:vxl:nq:o:P:M:m:t:")) != EOF) { switch (ch) { case 'I': { in_addr_t ipAddr = inet_addr(optarg); if ((in_addr_t) -1 == ipAddr) { (void) fprintf(stderr, "Interface specification \"%s\" " "isn't an IP address\n", optarg); exit(1); } locIpAddr = ipAddr; break; } case 'v': logmask |= LOG_MASK(LOG_INFO); break; case 'x': logmask |= LOG_MASK(LOG_DEBUG); break; case 'l': logfname = optarg; break; case 'q': pqfname = optarg; setQueuePath(optarg); break; case 'o': toffset = atoi(optarg); if (toffset == 0 && *optarg != '0') { (void) fprintf(stderr, "%s: invalid offset %s\n", av[0], optarg); usage(av[0]); } break; case 'P': { char* suffix = ""; long port; errno = 0; port = strtol(optarg, &suffix, 0); if (0 != errno || 0 != *suffix || 0 >= port || 0xffff < port) { (void) fprintf(stderr, "%s: invalid port %s\n", av[0], optarg); usage(av[0]); } ldmPort = (unsigned) port; break; } case 'M': { int max = atoi(optarg); if (max < 0) { (void) fprintf(stderr, "%s: invalid maximum number of clients %s\n", av[0], optarg); usage(av[0]); } maxClients = max; break; } case 'm': max_latency = atoi(optarg); if (max_latency <= 0) { (void) fprintf(stderr, "%s: invalid max_latency %s\n", av[0], optarg); usage(av[0]); } break; case 'n': doSomething = 0; break; case 't': rpctimeo = (unsigned) atoi(optarg); if (rpctimeo == 0 || rpctimeo > 32767) { (void) fprintf(stderr, "%s: invalid timeout %s", av[0], optarg); usage(av[0]); } break; case '?': usage(av[0]); break; } /* "switch" statement */ } /* argument loop */ if (ac - optind == 1) setLdmdConfigPath(av[optind]); (void) setulogmask(logmask); if (toffset != TOFFSET_NONE && toffset > max_latency) { (void) fprintf(stderr, "%s: invalid toffset (%d) > max_latency (%d)\n", av[0], toffset, max_latency); usage(av[0]); } } /* command-line argument decoding */ #ifndef DONTFORK /* * daemon behavior * * Background the process unless we are logging to stderr, in which * case we assume interactive. */ if (logfname == NULL || *logfname != '-') { /* detach */ pid_t pid; pid = ldmfork(); if (pid == -1) { log_add("Couldn't fork LDM daemon"); log_log(LOG_ERR); exit(2); } if (pid > 0) { /* parent */ (void) printf("%ld\n", (long) pid); exit(0); } /* detach the child from parents process group ?? */ (void) setsid(); } #endif /* * Initialize logger. * (Close fd 2 to remap stderr to the logfile, when * appropriate. I know, this is anal.) */ if (logfname == NULL ) (void) fclose(stderr); else if (!(logfname[0] == '-' && logfname[1] == 0)) (void) close(2); (void) openulog(ubasename(av[0]), (LOG_CONS | LOG_PID), LOG_LDM, logfname); unotice("Starting Up (version: %s; built: %s %s)", PACKAGE_VERSION, __DATE__, __TIME__); /* * register exit handler */ if (atexit(cleanup) != 0) { serror("atexit"); unotice("Exiting"); exit(1); } /* * set up signal handlers */ set_sigactions(); /* * Close the standard input and standard output streams because they won't * be used (more anality :-) */ (void) fclose(stdout); (void) fclose(stdin); if (!doSomething) { /* * Vet the configuration file. */ udebug("main(): Vetting configuration-file"); if (read_conf(getLdmdConfigPath(), doSomething, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } } else { /* * Create a service portal. This should be done before anything is * created because this is the function that relinquishes superuser * privileges. */ udebug("main(): Creating service portal"); if (create_ldm_tcp_svc(&sock, locIpAddr, ldmPort) != ENOERR) { /* error reports are emitted from create_ldm_tcp_svc() */ exit(1); } udebug("tcp sock: %d", sock); /* * Verify that the product-queue can be open for writing. */ udebug("main(): Opening product-queue"); if (status = pq_open(pqfname, PQ_DEFAULT, &pq)) { if (PQ_CORRUPT == status) { uerror("The product-queue \"%s\" is inconsistent", pqfname); } else { uerror("pq_open failed: %s: %s", pqfname, strerror(status)); } exit(1); } (void) pq_close(pq); pq = NULL; /* * Create the sharable database of upstream LDM metadata. */ udebug("main(): Creating shared upstream LDM database"); if (status = uldb_delete(NULL)) { if (ULDB_EXIST == status) { log_clear(); } else { LOG_ADD0( "Couldn't delete existing shared upstream LDM database"); log_log(LOG_ERR); exit(1); } } if (uldb_create(NULL, maxClients * 1024)) { LOG_ADD0("Couldn't create shared upstream LDM database"); log_log(LOG_ERR); exit(1); } /* * Read the configuration file (downstream LDM-s are started). */ udebug("main(): Reading configuration-file"); if (read_conf(getLdmdConfigPath(), doSomething, ldmPort) != 0) { log_log(LOG_ERR); exit(1); } /* * Serve */ udebug("main(): Serving socket"); sock_svc(sock); } /* "doSomething" is true */ return (0); }
sta_struct *decode_fsl2(int cdfid, long miss, int *iret) { int ndims,nvars,natts,nunlim; int tmpint[20]; int ier,i,j,unlimsiz; int wmoStaNum_id,wmoStaNum,staName_id; char staName[20]; int staLat_id,staLon_id,staElev_id,timeObs_id,levels_id; int uwnd_id,vwnd_id,wwnd_id,uv_qual_id,w_qual_id,levelMode_id; int sigma_uv_id,sigma_w_id; int sfc_sped_id,sfc_drct_id,sfc_pres_id,sfc_temp_id,sfc_relh_id,sfc_rain_id; float staLat,staLon,staElev,level; float uwnd,vwnd,wwnd,sigma_uv,sigma_w; int uv_qual,w_qual,levelMode; float sfc_sped,sfc_drct,sfc_pres,sfc_temp,sfc_relh,sfc_rain; double timeObs; nc_type xtype; int nvdims,nvatts,time_interval; size_t dimsiz,var_i[5],vc[5],namelen; float ufill,vfill,wfill; float pfill,tfill,dfill,sfill,rfill,rrfill; float fmiss,e; time_t obs_time; char timestr[80],*atttext; int year,month,day,hour,minute; struct tm *gmt_time=NULL,new_time; sta_struct *stadat,*head=NULL; prof_data *plev,*plast; udebug("decoding fsl2\0"); fmiss = (float)miss; ier = nc_inq(cdfid,&ndims,&nvars,&natts,&nunlim); ier = nc_inq_atttype(cdfid,NC_GLOBAL,"avgTimePeriod",&xtype); if(xtype == NC_CHAR) { ier = nc_inq_attlen(cdfid,NC_GLOBAL,"avgTimePeriod",&namelen); udebug("AvgTimPeriod name len is %d",namelen); atttext = (char *)malloc(namelen + 1); ier = nc_get_att_text(cdfid,NC_GLOBAL,"avgTimePeriod",atttext); sscanf(atttext,"%d",tmpint); udebug("AvgTimPeriod type is NC_CHAR %s VAL %d",atttext,tmpint[0]); free(atttext); } else { ier = nc_get_att_int(cdfid,NC_GLOBAL,"avgTimePeriod",tmpint); } udebug("AvgTimPeriod is %d\0",tmpint[0]); time_interval = tmpint[0]; ier = 0; ier += nc_inq_varid(cdfid,"wmoStaNum",&wmoStaNum_id); ier += nc_inq_varid(cdfid,"staName",&staName_id); ier += nc_inq_varid(cdfid,"staLat",&staLat_id); ier += nc_inq_varid(cdfid,"staLon",&staLon_id); ier += nc_inq_varid(cdfid,"staElev",&staElev_id); ier += nc_inq_varid(cdfid,"timeObs",&timeObs_id); ier += nc_inq_varid(cdfid,"levels",&levels_id); ier += nc_inq_varid(cdfid,"uComponent",&uwnd_id); ier += nc_inq_varid(cdfid,"vComponent",&vwnd_id); ier += nc_inq_varid(cdfid,"wComponent",&wwnd_id); ier += nc_get_att_float(cdfid,uwnd_id,"_FillValue",&ufill); ier += nc_get_att_float(cdfid,vwnd_id,"_FillValue",&vfill); ier += nc_get_att_float(cdfid,wwnd_id,"_FillValue",&wfill); ier += nc_inq_varid(cdfid,"uvQualityCode",&uv_qual_id); ier += nc_inq_varid(cdfid,"wQualityCode",&w_qual_id); ier += nc_inq_varid(cdfid,"windSpeedStdDev",&sigma_uv_id); ier += nc_inq_varid(cdfid,"wStdDev",&sigma_w_id); ier += nc_inq_varid(cdfid,"levelMode",&levelMode_id); ier += nc_inq_varid(cdfid,"windSpeedSfc",&sfc_sped_id); ier += nc_inq_varid(cdfid,"windDirSfc",&sfc_drct_id); ier += nc_inq_varid(cdfid,"pressure",&sfc_pres_id); ier += nc_inq_varid(cdfid,"temperature",&sfc_temp_id); ier += nc_inq_varid(cdfid,"relHumidity",&sfc_relh_id); ier += nc_inq_varid(cdfid,"rainRate",&sfc_rain_id); ier += nc_get_att_float(cdfid,sfc_sped_id,"_FillValue",&sfill); ier += nc_get_att_float(cdfid,sfc_drct_id,"_FillValue",&dfill); ier += nc_get_att_float(cdfid,sfc_pres_id,"_FillValue",&pfill); ier += nc_get_att_float(cdfid,sfc_temp_id,"_FillValue",&tfill); ier += nc_get_att_float(cdfid,sfc_relh_id,"_FillValue",&rfill); ier += nc_get_att_float(cdfid,sfc_rain_id,"_FillValue",&rrfill); if(ier != 0) { uerror("could not get station information\0"); *iret = -1; return(NULL); } ier = nc_inq_vardimid(cdfid,staName_id,tmpint); ier += nc_inq_dimlen(cdfid,tmpint[1],&namelen); tmpint[0] = 0;tmpint[1] = 0; ier += nc_inq_var(cdfid,wmoStaNum_id,NULL, &xtype, &nvdims, tmpint, &nvatts); ier += nc_inq_dimlen(cdfid,tmpint[0],&dimsiz); if(ier == 0) unlimsiz = dimsiz; for(i=0;i<unlimsiz;i++) { var_i[0] = i; var_i[1] = 0; vc[0] = 1; vc[1] = namelen-1; memset(staName,'\0',20); ier = nc_get_vara_text(cdfid,staName_id,var_i,vc,staName); ier = nc_get_var1_int(cdfid,wmoStaNum_id,var_i,&wmoStaNum); ier = nc_get_var1_float(cdfid,staLat_id,var_i,&staLat); ier = nc_get_var1_float(cdfid,staLon_id,var_i,&staLon); ier = nc_get_var1_float(cdfid,staElev_id,var_i,&staElev); ier = nc_get_var1_float(cdfid,sfc_sped_id,var_i,&sfc_sped); ier = nc_get_var1_float(cdfid,sfc_drct_id,var_i,&sfc_drct); ier = nc_get_var1_float(cdfid,sfc_pres_id,var_i,&sfc_pres); ier = nc_get_var1_float(cdfid,sfc_temp_id,var_i,&sfc_temp); ier = nc_get_var1_float(cdfid,sfc_relh_id,var_i,&sfc_relh); ier = nc_get_var1_float(cdfid,sfc_rain_id,var_i,&sfc_rain); ier = nc_get_var1_double(cdfid,timeObs_id,var_i,&timeObs); obs_time = (time_t) timeObs; gmt_time = gmtime(&obs_time); new_time = *gmt_time; timestr[0] = '\0'; strftime(timestr,80,"%Y %m %d %H %M",&new_time); sscanf(timestr,"%d %d %d %d %d",&year,&month,&day,&hour,&minute); udebug("Station %3d %8d %s = %6.2f %7.2f %5.0f %s\0",i,wmoStaNum, staName,staLat,staLon,staElev,timestr); stadat = (sta_struct *)malloc(sizeof(sta_struct)); if(stadat == NULL) { uerror("Could not allocate station data structure\0"); exit(-2); } stadat->wmoStaNum = wmoStaNum; stadat->staName = (char *)malloc(strlen(staName)+1); strcpy(stadat->staName,staName); stadat->staLat = staLat; stadat->staLon = staLon; stadat->staElev = staElev; stadat->timeObs = timeObs; stadat->year = year; stadat->month = month; stadat->day = day; stadat->hour = hour; stadat->minute = minute; stadat->time_interval = time_interval; stadat->pdata = NULL; stadat->rdata = NULL; stadat->sfc_pres = fmiss; stadat->sfc_temp = fmiss; stadat->sfc_sped = fmiss; stadat->sfc_drct = fmiss; stadat->sfc_relh = fmiss; stadat->sfc_rain_rate = fmiss; stadat->sfc_rain_amt = fmiss; stadat->sfc_dwpc = fmiss; if(sfc_pres != pfill) stadat->sfc_pres = sfc_pres; if(sfc_temp != tfill) stadat->sfc_temp = sfc_temp - 273.15; if(sfc_sped != sfill) stadat->sfc_sped = sfc_sped; if(sfc_drct != dfill) stadat->sfc_drct = sfc_drct; if(sfc_relh != rfill) stadat->sfc_relh = sfc_relh; if(sfc_rain != rrfill) stadat->sfc_rain_rate = sfc_rain; if((stadat->sfc_temp != fmiss)&&(stadat->sfc_relh != fmiss)) { VAPOR_PRES(stadat->sfc_temp+273.15,&e); e = e * (stadat->sfc_relh / 100.); t_from_e(e,&stadat->sfc_dwpc); stadat->sfc_dwpc = stadat->sfc_dwpc - 273.15; } ier = nc_inq_var(cdfid,levels_id,NULL, &xtype, &nvdims, tmpint, &nvatts); if(ier == 0) { ier = nc_inq_dimlen(cdfid,tmpint[0],&dimsiz); stadat->numlevs = dimsiz; plast = stadat->pdata; for(j=0;j<stadat->numlevs;j++) { var_i[0] = j; ier = nc_get_var1_float(cdfid,levels_id,var_i,&level); ier = nc_get_var1_int(cdfid,levelMode_id,var_i,&levelMode); var_i[0] = i; var_i[1] = j; ier = nc_get_var1_float(cdfid,uwnd_id,var_i,&uwnd); ier = nc_get_var1_float(cdfid,vwnd_id,var_i,&vwnd); ier = nc_get_var1_float(cdfid,wwnd_id,var_i,&wwnd); ier = nc_get_var1_int(cdfid,uv_qual_id,var_i,&uv_qual); ier = nc_get_var1_int(cdfid,w_qual_id,var_i,&w_qual); ier = nc_get_var1_float(cdfid,sigma_uv_id,var_i,&sigma_uv); ier = nc_get_var1_float(cdfid,sigma_w_id,var_i,&sigma_w); plev = (prof_data *)malloc(sizeof(prof_data)); if(plev != NULL) { plev->level = level; if(uwnd == ufill) uwnd = fmiss; if(vwnd == vfill) vwnd = fmiss; if(wwnd == wfill) wwnd = fmiss; if(uv_qual != 0) { uwnd = fmiss; vwnd = fmiss; } if(w_qual != 0) wwnd = fmiss; if((uwnd == fmiss)||(vwnd == fmiss)) sigma_uv = fmiss; if(wwnd == fmiss) sigma_w = fmiss; plev->u = uwnd; plev->v = vwnd; plev->w = wwnd; plev->sigma_uv = sigma_uv; plev->sigma_w = sigma_w; plev->levmode = levelMode; plev->nextlev = NULL; if(plast == NULL) stadat->pdata = plev; else plast->nextlev = plev; plast = plev; } } } else stadat->numlevs = 0; stadat->next = head; head = stadat; } return(head); }
/** * @retval LDM7_INVAL No multicast sender child process exists. */ static int sender_terminate(void) { int retval = 0; int status; #if CANCEL_SENDER udebug("Canceling sender thread"); status = pthread_cancel(sender.thread); if (status) { LOG_ERRNUM0(status, "Couldn't cancel sender thread"); retval = status; } #else udebug("Writing to termination pipe"); status = write(sender.fds[1], &status, sizeof(int)); if (status == -1) { LOG_SERROR0("Couldn't write to termination pipe"); retval = status; } #endif void* statusPtr; udebug("Joining sender thread"); status = pthread_join(sender.thread, &statusPtr); if (status) { LOG_ERRNUM0(status, "Couldn't join sender thread"); retval = status; } if (statusPtr != PTHREAD_CANCELED) { status = *(int*)statusPtr; if (status) { LOG_START1("Sender task exit-status was %d", status); retval = status; } } (void)close(sender.sock); udebug("Terminating multicast sender"); status = terminateMcastSender(); if (status) { LOG_ADD0("Couldn't terminate multicast sender process"); retval = status; } udebug("Clearing multicast LDM sender manager"); status = mlsm_clear(); if (status) { LOG_ADD0("mlsm_clear() failure"); retval = status; } status = pq_close(pq); if (status) { LOG_ADD0("pq_close() failure"); retval = status; } status = deleteProductQueue(UP7_PQ_PATHNAME); if (status) { LOG_ADD0("deleteProductQueue() failure"); retval = status; } return retval; }
int main(int ac, char *av[]) { const char* pqfname = getQueuePath(); const char *opqfname = getSurfQueuePath(); const char *progname = ubasename(av[0]); char *logfname; prod_class_t clss; prod_spec spec; int status = 0; unsigned interval = DEFAULT_INTERVAL; int logoptions = (LOG_CONS|LOG_PID); double age = DEFAULT_AGE; /* these are containers for the pqact args */ char *argv[16]; int argc = 0; int toffset = TOFFSET_NONE; logfname = ""; if(set_timestamp(&clss.from) != ENOERR) /* corrected by toffset below */ { int errnum = errno; fprintf(stderr, "Couldn't set timestamp: %s", strerror(errnum)); exit(1); } clss.to = TS_ENDT; clss.psa.psa_len = 1; clss.psa.psa_val = &spec; spec.feedtype = DEFAULT_FEEDTYPE; spec.pattern = DEFAULT_PATTERN; memset(argv, 0, sizeof(argv)); argv[0] = "pqact"; argc++; { extern int optind; extern int opterr; extern char *optarg; int ch; int logmask = (LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_NOTICE)); int fterr; const char *conffilename = getPqsurfConfigPath(); const char *datadir = getPqsurfDataDirPath(); usePil = 1; opterr = 1; while ((ch = getopt(ac, av, "vxl:d:f:p:q:Q:o:i:a:t:")) != EOF) switch (ch) { case 'v': argv[argc++] = "-v"; logmask |= LOG_MASK(LOG_INFO); break; case 'x': argv[argc++] = "-x"; logmask |= LOG_MASK(LOG_DEBUG); break; case 'l': argv[argc++] = "-l"; argv[argc++] = optarg; logfname = optarg; break; case 'd': datadir = optarg; break; case 'f': fterr = strfeedtypet(optarg, &spec.feedtype); if(fterr != FEEDTYPE_OK) { fprintf(stderr, "%s: %s: \"%s\"\n", av[0], strfeederr(fterr), optarg); usage(progname); } argv[argc++] = "-f"; argv[argc++] = optarg; break; case 'p': spec.pattern = optarg; /* compiled below */ break; case 'q': pqfname = optarg; break; case 'Q': opqfname = optarg; break; case 'o': toffset = atoi(optarg); if(toffset == 0 && *optarg != '0') { fprintf(stderr, "%s: invalid offset %s\n", av[0], optarg); usage(av[0]); } argv[argc++] = "-o"; argv[argc++] = optarg; break; case 'i': interval = atoi(optarg); if(interval == 0 && *optarg != '0') { fprintf(stderr, "%s: invalid interval \"%s\"\n", av[0], optarg); usage(av[0]); } /* N.B. -i just used for input queue. */ break; case 'a': age = atof(optarg); if(age < 0.) { (void) fprintf(stderr, "age (%s) must be non negative\n", optarg); usage(av[0]); } break; case 't': /* pipe_timeo */ argv[argc++] = "-t"; argv[argc++] = optarg; break; case '?': usage(progname); break; } (void) setulogmask(logmask); if (re_isPathological(spec.pattern)) { fprintf(stderr, "Adjusting pathological regular-expression: " "\"%s\"\n", spec.pattern); re_vetSpec(spec.pattern); } status = regcomp(&spec.rgx, spec.pattern, REG_EXTENDED|REG_NOSUB); if(status != 0) { fprintf(stderr, "Bad regular expression \"%s\"\n", spec.pattern); usage(av[0]); } if(ac - optind == 1) conffilename = av[optind]; argv[argc++] = "-d"; argv[argc++] = (char*)datadir; argv[argc++] = "-q"; argv[argc++] = (char*)opqfname; argv[argc++] = (char*)conffilename; age *= 3600.; } if(toffset != TOFFSET_NONE) { clss.from.tv_sec -= toffset; } else { clss.from.tv_sec -= (age - interval); } /* * Set up error logging. * N.B. log ident is the remote */ (void) openulog(progname, logoptions, LOG_LDM, logfname); unotice("Starting Up (%d)", getpgrp()); /* * register exit handler */ if(atexit(cleanup) != 0) { serror("atexit"); exit(1); } /* * set up signal handlers */ set_sigactions(); /* * Open the output product queue */ status = pq_open(opqfname, PQ_DEFAULT, &opq); if(status) { if (PQ_CORRUPT == status) { uerror("The output product-queue \"%s\" is inconsistent\n", opqfname); } else { uerror("pq_open failed: %s: %s\n", opqfname, strerror(status)); } exit(1); } act_pid = run_child(argc, argv); if(act_pid == (pid_t)-1) exit(1); /* * Open the input product queue */ status = pq_open(pqfname, PQ_READONLY, &pq); if(status) { if (PQ_CORRUPT == status) { uerror("The product-queue \"%s\" is inconsistent\n", pqfname); } else { uerror("pq_open failed: %s: %s\n", pqfname, strerror(status)); } exit(1); } if(toffset == TOFFSET_NONE) { /* Jump to the end of the queue */ timestampt sav; sav = clss.from; clss.from = TS_ZERO; (void) pq_last(pq, &clss, NULL); clss.from = sav; } else { pq_cset(pq, &clss.from); } if(ulogIsVerbose()) { char buf[1984]; uinfo("%s", s_prod_class(buf, sizeof(buf), &clss)); } while(exitIfDone(0)) { if(stats_req) { dump_stats(); stats_req = 0; } status = pq_sequence(pq, TV_GT, &clss, split_prod, NULL); switch(status) { case 0: /* no error */ continue; /* N.B., other cases sleep */ case PQUEUE_END: udebug("surf: End of Queue"); break; case EAGAIN: case EACCES: udebug("Hit a lock"); break; default: uerror("pq_sequence failed: %s (errno = %d)", strerror(status), status); exit(1); break; } if(interval == 0) { break; } (void) expire(opq, interval, age); pq_suspend(interval); (void) reap_act(WNOHANG); } /* * TODO: how can we determine that pqact has finished * the work in opq? */ sleep(5); exit(0); }
/** * Might call `svc_destroy(up7->xprt)`. * * @param[in] up7 Upstream LDM-7. * @retval 0 Success. */ static int up7_run( Up7* const up7) { const int sock = up7->xprt->xp_sock; int status; struct pollfd fds; fds.fd = sock; fds.events = POLLRDNORM; pthread_cleanup_push(funcCancelled, "up7_run"); int initCancelState; (void)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &initCancelState); for (;;) { udebug("up7_run(): Calling poll()"); status = poll(&fds, 1, -1); // `-1` => indefinite timeout int cancelState; // (void)pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState); if (0 > status) { svc_destroy(up7->xprt); break; } if ((fds.revents & POLLERR) || (fds.revents & POLLNVAL)) { status = EIO; break; } if (fds.revents & POLLHUP) { status = 0; break; } if (fds.revents & POLLRDNORM) { udebug("up7_run(): Calling svc_getreqsock()"); svc_getreqsock(sock); // calls `ldmprog_7()` } if (!FD_ISSET(sock, &svc_fdset)) { /* * The connection to the receiver was closed by the RPC layer => * `svc_destroy(up7->xprt)` was called. */ up7->xprt = NULL; // so others don't try to destroy it status = 0; break; } (void)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelState); } /* * In order to play nice with the caller, the cancelability state is * reverted to its value on entry. */ (void)pthread_setcancelstate(initCancelState, &initCancelState); pthread_cleanup_pop(0); udebug("up7_run(): Returning %d", status); return status; }