void SetDaemonState(void) { int oldpid; #ifdef XFS_INETD if (runFromInetd) { int inetdListener; /* fd's 0, 1, & 2 are the initial listen socket provided by inetd, * so dup it and then clear them so stdin/out/err aren't in use. */ inetdListener = dup(0); if (inetdListener == -1) { FatalError("failed to dup inetd socket: %s\n", strerror(errno)); } DetachStdio(); /* Setup & pass the inetd socket back through the connection setup * code the same way as a cloned listening port */ OldListenCount = 1; OldListen = _FontTransGetInetdListenInfo (inetdListener); if (OldListen == NULL) { FatalError("failed to initialize OldListen to inetd socket: %s\n", strerror(errno)); } ListenPort = OldListen[0].portnum; NoticeF("accepting listener from inetd on fd %d, port %d\n", inetdListener, ListenPort); return; } #endif /* XFS_INETD */ if (becomeDaemon) { BecomeDaemon(); if ((oldpid = StorePid ())) { if (oldpid == -1) ErrorF ("error opening process-id file %s\n", pidFile); else ErrorF ("process-id file %s indicates another xfs is " "running (pid %d); exiting\n", pidFile, oldpid); exit(1); } } }
int CloneMyself(void) { int child; char old_listen_arg[256]; char *arg_ptr = old_listen_arg; int i, j; int lastfdesc; char portnum[20]; assert(!drone_server); /* a drone shouldn't hit this */ if (!CloneSelf) return -1; #ifdef __UNIXOS2__ NoticeF("cloning of font server not supported under OS/2!\n"); return(-1); #endif old_listen_arg[0] = '\0'; lastfdesc = sysconf(_SC_OPEN_MAX) - 1; if ( (lastfdesc < 0) || (lastfdesc > MAXSOCKS)) { lastfdesc = MAXSOCKS; } NoticeF("attempting clone...\n"); chdir("/"); child = fork(); if (child == -1) { /* failed to fork */ ErrorF("clone failed to fork()\n"); return -1; } /* * Note: they still share the same process group, and killing the parent * will take out all the kids as well. this is considered a feature (at * least until i'm convinced otherwise) */ if (child == 0) { StopListening(); NoticeF("clone: child becoming drone\n"); drone_server = TRUE; return 1; } else { /* parent */ NoticeF("clone: parent revitalizing as %s\n", progname); CloseErrors(); /* XXX should we close stdio as well? */ for (i = 3; i < lastfdesc; i++) { for (j = 0; j < ListenTransCount; j++) if (ListenTransFds[j] == i) break; if (j >= ListenTransCount) (void) close(i); } for (i = 0; i < ListenTransCount; i++) { int trans_id, fd; char *port; if (!_FontTransGetReopenInfo (ListenTransConns[i], &trans_id, &fd, &port)) continue; sprintf (arg_ptr, "%d/%d/%s", trans_id, fd, port); arg_ptr += strlen (arg_ptr); free (port); if (i < ListenTransCount - 1) { strcat (arg_ptr, ","); arg_ptr++; } } sprintf (portnum, "%d", ListenPort); if (*old_listen_arg != '\0') execlp(progname, progname, "-ls", old_listen_arg, "-cf", configfilename, "-port", portnum, (void *)NULL); InitErrors(); /* reopen errors, since we don't want to lose * this */ Error("clone failed"); FatalError("failed to clone self\n"); } /* NOTREACHED */ return 0; }
Dispatch() { int nready, result; int *clientReady; ClientPtr client; int op; nextFreeClientID = MINCLIENT; nClients = 0; clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); if (!clientReady) return; while (1) { /* wait for something */ nready = WaitForSomething(clientReady); while (!dispatchException && (--nready >= 0)) { client = currentClient = clients[clientReady[nready]]; /* Client can be NULL if CloseDownClient() is called during this dispatchException loop. */ if (client == (ClientPtr)NULL) continue; isItTimeToYield = FALSE; while (!isItTimeToYield) { result = ReadRequest(client); if (result <= 0) { if (result < 0) CloseDownClient(client); break; } client->sequence++; if (result > (MAX_REQUEST_SIZE << 2)) result = FSBadLength; else { op = MAJOROP; if (op >= NUM_PROC_VECTORS) result = ProcBadRequest (client); else result = (*client->requestVector[op]) (client); } if (result != FSSuccess) { if (client->noClientException != FSSuccess) CloseDownClient(client); break; } } FlushAllOutput (); } /* reset if server is a drone and has run out of clients */ if (drone_server && nClients == 0) { dispatchException |= DE_RESET; } if (dispatchException) { /* re-read the config file */ if (dispatchException & DE_RECONFIG) { NoticeF("Re-reading config file\n"); if (ReadConfigFile(configfilename) != FSSuccess) ErrorF("couldn't parse config file\n"); SetConfigValues(); dispatchException &= ~DE_RECONFIG; } /* flush all the caches */ if (dispatchException & DE_FLUSH) { NoticeF("flushing all caches\n"); CacheReset(); dispatchException &= ~DE_FLUSH; } /* reset */ if (dispatchException & DE_RESET) { NoticeF("resetting\n"); break; } /* die *now* */ if (dispatchException & DE_TERMINATE) { NoticeF("terminating\n"); kill_all_clients(); exit(0); break; } } } kill_all_clients(); dispatchException = 0; }
/* * creates the sockets for listening to clients * * only called when server first started */ void CreateSockets(int old_listen_count, OldListenRec *old_listen) { int i; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); FD_ZERO(&WellKnownConnections); for (i = 0; i < MAXSOCKS; i++) ConnectionTranslation[i] = 0; #ifdef XNO_SYSCONF /* should only be on FreeBSD 1.x and NetBSD 0.x */ #undef _SC_OPEN_MAX #endif #ifdef _SC_OPEN_MAX lastfdesc = sysconf(_SC_OPEN_MAX) - 1; #else #if defined(hpux) || defined(__UNIXOS2__) lastfdesc = _NFILE - 1; #else lastfdesc = getdtablesize() - 1; #endif /* hpux */ #endif if (lastfdesc > MAXSOCKS) { lastfdesc = MAXSOCKS; } if (old_listen_count > 0) { /* * The font server cloned itself. Re-use previously opened * transports for listening. */ ListenTransConns = (XtransConnInfo *) malloc ( old_listen_count * sizeof (XtransConnInfo)); ListenTransFds = (int *) malloc (old_listen_count * sizeof (int)); ListenTransCount = 0; for (i = 0; i < old_listen_count; i++) { char portnum[10]; if (old_listen[i].portnum != ListenPort) continue; /* this should never happen */ else sprintf (portnum, "%d", old_listen[i].portnum); if ((ListenTransConns[ListenTransCount] = _FontTransReopenCOTSServer (old_listen[i].trans_id, old_listen[i].fd, portnum)) != NULL) { ListenTransFds[ListenTransCount] = old_listen[i].fd; FD_SET (old_listen[i].fd, &WellKnownConnections); NoticeF("reusing existing file descriptor %d\n", old_listen[i].fd); ListenTransCount++; } } } else { char port[20]; int partial; sprintf (port, "%d", ListenPort); if ((_FontTransMakeAllCOTSServerListeners (port, &partial, &ListenTransCount, &ListenTransConns) >= 0) && (ListenTransCount >= 1)) { ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); for (i = 0; i < ListenTransCount; i++) { int fd = _FontTransGetConnectionNumber (ListenTransConns[i]); ListenTransFds[i] = fd; FD_SET (fd, &WellKnownConnections); } } } if (! XFD_ANYSET(&WellKnownConnections)) FatalError("cannot establish any listening sockets\n"); /* set up all the signal handlers */ signal(SIGPIPE, SIG_IGN); signal(SIGHUP, AutoResetServer); signal(SIGINT, GiveUp); signal(SIGTERM, GiveUp); signal(SIGUSR1, ServerReconfig); signal(SIGUSR2, ServerCacheFlush); signal(SIGCHLD, CleanupChild); XFD_COPYSET (&WellKnownConnections, &AllSockets); }
/* * creates the sockets for listening to clients * * only called when server first started */ void CreateSockets(int old_listen_count, OldListenRec *old_listen) { int i; struct sigaction act; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); FD_ZERO(&WellKnownConnections); for (i = 0; i < MAXSOCKS; i++) ConnectionTranslation[i] = 0; lastfdesc = sysconf(_SC_OPEN_MAX) - 1; if ((lastfdesc < 0) || (lastfdesc > MAXSOCKS)) { lastfdesc = MAXSOCKS; } if (old_listen_count > 0) { /* * The font server cloned itself. Re-use previously opened * transports for listening. */ ListenTransConns = (XtransConnInfo *) malloc ( old_listen_count * sizeof (XtransConnInfo)); ListenTransFds = (int *) malloc (old_listen_count * sizeof (int)); ListenTransCount = 0; for (i = 0; i < old_listen_count; i++) { char portnum[10]; if (old_listen[i].portnum != ListenPort) continue; /* this should never happen */ else sprintf (portnum, "%d", old_listen[i].portnum); if ((ListenTransConns[ListenTransCount] = _FontTransReopenCOTSServer (old_listen[i].trans_id, old_listen[i].fd, portnum)) != NULL) { ListenTransFds[ListenTransCount] = old_listen[i].fd; FD_SET (old_listen[i].fd, &WellKnownConnections); NoticeF("reusing existing file descriptor %d\n", old_listen[i].fd); ListenTransCount++; } } } else { char port[20]; int partial; sprintf (port, "%d", ListenPort); if ((_FontTransMakeAllCOTSServerListeners (port, &partial, &ListenTransCount, &ListenTransConns) >= 0) && (ListenTransCount >= 1)) { ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); for (i = 0; i < ListenTransCount; i++) { int fd = _FontTransGetConnectionNumber (ListenTransConns[i]); ListenTransFds[i] = fd; FD_SET (fd, &WellKnownConnections); } } } if (! XFD_ANYSET(&WellKnownConnections)) FatalError("cannot establish any listening sockets\n"); /* set up all the signal handlers */ sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; #define HANDLE_SIGNAL(s, h) act.sa_handler = h; sigaction(s, &act, NULL) HANDLE_SIGNAL(SIGPIPE, SIG_IGN); HANDLE_SIGNAL(SIGHUP, AutoResetServer); HANDLE_SIGNAL(SIGINT, GiveUp); HANDLE_SIGNAL(SIGTERM, GiveUp); HANDLE_SIGNAL(SIGUSR1, ServerReconfig); HANDLE_SIGNAL(SIGUSR2, ServerCacheFlush); HANDLE_SIGNAL(SIGCHLD, CleanupChild); XFD_COPYSET (&WellKnownConnections, &AllSockets); }