int rend_private_init(char *user) { mStatus status; mDNSBool result; status = mDNS_Init(&mDNSStorage, &PlatformStorage, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize, mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); if (status != mStatus_NoError) { DPRINTF(E_FATAL,L_REND,"mDNS Error %d\n",status); return(-1); } if(os_drop_privs(user)) return -1; signal(SIGINT, HandleSigInt); // SIGINT is what you get for a Ctrl-C signal(SIGQUIT, HandleSigQuit); // SIGQUIT is what you get for a Ctrl-\ (indeed) signal(SIGHUP, SIG_IGN); // SIGHUP might happen from a request to reload the daap server while (!gStopNow) { int nfds = 1; fd_set readfds; struct timeval timeout; int result; // 1. Set up the fd_set as usual here. // This example client has no file descriptors of its own, // but a real application would call FD_SET to add them to the set here FD_ZERO(&readfds); FD_SET(rend_pipe_to[RD_SIDE],&readfds); // 2. Set up the timeout. // This example client has no other work it needs to be doing, // so we set an effectively infinite timeout timeout.tv_sec = 0x3FFFFFFF; timeout.tv_usec = 0; // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &timeout); // 4. Call select as normal DPRINTF(E_SPAM,L_REND,"select(%d, %d.%06d)\n", nfds, timeout.tv_sec, timeout.tv_usec); result = select(nfds, &readfds, NULL, NULL, &timeout); if (result < 0) { if (errno != EINTR) gStopNow = mDNStrue; DPRINTF(E_WARN,L_REND,"select() returned %d errno %d\n", result, errno); } else { // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work mDNSPosixProcessFDSet(&mDNSStorage, &readfds); // 6. This example client has no other work it needs to be doing, // but a real client would do its work here // ... (do work) ... if(FD_ISSET(rend_pipe_to[RD_SIDE],&readfds)) { rend_callback(); } } } DPRINTF(E_DBG,L_REND,"Exiting\n"); DeregisterOurServices(); mDNS_Close(&mDNSStorage); if (status == mStatus_NoError) { result = 0; } else { result = 2; } DPRINTF(E_DBG,L_REND, "Finished with status %ld, result %d\n", status, result); exit(result); }
int main(int argc, char **argv) { mStatus status; int result; // Parse our command line arguments. This won't come back if there's an error. ParseArguments(argc, argv); // If we're told to run as a daemon, then do that straight away. // Note that we don't treat the inability to create our PID // file as an error. Also note that we assign getpid to a long // because printf has no format specified for pid_t. if (gDaemon) { if (gMDNSPlatformPosixVerboseLevel > 0) { fprintf(stderr, "%s: Starting in daemon mode\n", gProgramName); } daemon(0,0); { FILE *fp; int junk; fp = fopen(gPIDFile, "w"); if (fp != NULL) { fprintf(fp, "%ld\n", (long) getpid()); junk = fclose(fp); assert(junk == 0); } } } else { if (gMDNSPlatformPosixVerboseLevel > 0) { fprintf(stderr, "%s: Starting in foreground mode, PID %ld\n", gProgramName, (long) getpid()); } } status = mDNS_Init(&mDNSStorage, &PlatformStorage, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize, mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); if (status != mStatus_NoError) return(2); status = RegisterOurServices(); if (status != mStatus_NoError) return(2); signal(SIGHUP, HandleSigHup); // SIGHUP has to be sent by kill -HUP <pid> signal(SIGINT, HandleSigInt); // SIGINT is what you get for a Ctrl-C signal(SIGQUIT, HandleSigQuit); // SIGQUIT is what you get for a Ctrl-\ (indeed) signal(SIGUSR1, HandleSigUsr1); // SIGUSR1 has to be sent by kill -USR1 <pid> while (!gStopNow) { int nfds = 0; fd_set readfds; struct timeval timeout; int result; // 1. Set up the fd_set as usual here. // This example client has no file descriptors of its own, // but a real application would call FD_SET to add them to the set here FD_ZERO(&readfds); // 2. Set up the timeout. // This example client has no other work it needs to be doing, // so we set an effectively infinite timeout timeout.tv_sec = 0x3FFFFFFF; timeout.tv_usec = 0; // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &timeout); // 4. Call select as normal verbosedebugf("select(%d, %d.%06d)", nfds, timeout.tv_sec, timeout.tv_usec); result = select(nfds, &readfds, NULL, NULL, &timeout); if (result < 0) { verbosedebugf("select() returned %d errno %d", result, errno); if (errno != EINTR) gStopNow = mDNStrue; else { if (gReceivedSigUsr1) { gReceivedSigUsr1 = mDNSfalse; gMDNSPlatformPosixVerboseLevel += 1; if (gMDNSPlatformPosixVerboseLevel > 2) gMDNSPlatformPosixVerboseLevel = 0; if ( gMDNSPlatformPosixVerboseLevel > 0 ) fprintf(stderr, "\nVerbose level %d\n", gMDNSPlatformPosixVerboseLevel); } if (gReceivedSigHup) { if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "\nSIGHUP\n"); gReceivedSigHup = mDNSfalse; DeregisterOurServices(); status = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage); if (status != mStatus_NoError) break; status = RegisterOurServices(); if (status != mStatus_NoError) break; } } } else { // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work mDNSPosixProcessFDSet(&mDNSStorage, &readfds); // 6. This example client has no other work it needs to be doing, // but a real client would do its work here // ... (do work) ... } } debugf("Exiting"); DeregisterOurServices(); mDNS_Close(&mDNSStorage); if (status == mStatus_NoError) { result = 0; } else { result = 2; } if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) { fprintf(stderr, "%s: Finished with status %ld, result %d\n", gProgramName, status, result); } return result; }