void cupsdStartServer(void) { /* * Start color management (as needed)... */ cupsdStartColor(); /* * Create the default security profile... */ DefaultProfile = cupsdCreateProfile(0, 1); /* * Startup all the networking stuff... */ cupsdStartListening(); cupsdStartBrowsing(); /* * Create a pipe for CGI processes... */ if (cupsdOpenPipe(CGIPipes)) cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdStartServer: Unable to create pipes for CGI status!"); else { CGIStatusBuffer = cupsdStatBufNew(CGIPipes[0], "[CGI]"); cupsdAddSelect(CGIPipes[0], (cupsd_selfunc_t)cupsdUpdateCGI, NULL, NULL); } /* * Mark that the server has started and printers and jobs may be changed... */ LastEvent = CUPSD_EVENT_PRINTER_CHANGED | CUPSD_EVENT_JOB_STATE_CHANGED | CUPSD_EVENT_SERVER_STARTED; started = 1; cupsdSetBusyState(); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ char *opt; /* Option character */ int close_all = 1, /* Close all file descriptors? */ disconnect = 1, /* Disconnect from controlling terminal? */ fg = 0, /* Run in foreground? */ run_as_child = 0, /* Running as child process? */ print_profile = 0; /* Print the sandbox profile to stdout? */ int fds; /* Number of ready descriptors */ cupsd_client_t *con; /* Current client */ cupsd_job_t *job; /* Current job */ cupsd_listener_t *lis; /* Current listener */ time_t current_time, /* Current time */ activity, /* Client activity timer */ senddoc_time, /* Send-Document time */ expire_time, /* Subscription expire time */ report_time, /* Malloc/client/job report time */ event_time; /* Last event notification time */ long timeout; /* Timeout for cupsdDoSelect() */ struct rlimit limit; /* Runtime limit */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ #ifdef __APPLE__ int use_sysman = 1; /* Use system management functions? */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ #if defined(HAVE_ONDEMAND) int service_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_ONDEMAND */ #ifdef HAVE_GETEUID /* * Check for setuid invocation, which we do not support! */ if (getuid() != geteuid()) { fputs("cupsd: Cannot run as a setuid program.\n", stderr); return (1); } #endif /* HAVE_GETEUID */ /* * Check for command-line arguments... */ fg = 0; #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { OnDemand = 1; fg = 1; close_all = 0; disconnect = 0; } #endif /* HAVE_LAUNCHD */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt != '\0'; opt ++) switch (*opt) { case 'C' : /* Run as child with config file */ run_as_child = 1; fg = 1; close_all = 0; case 'c' : /* Configuration file */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("cupsd: Expected config filename " "after \"-c\" option.")); usage(1); } if (argv[i][0] == '/') { /* * Absolute directory... */ cupsdSetString(&ConfigurationFile, argv[i]); } else { /* * Relative directory... */ char *current; /* Current directory */ /* * Allocate a buffer for the current working directory to * reduce run-time stack usage; this approximates the * behavior of some implementations of getcwd() when they * are passed a NULL pointer. */ if ((current = malloc(1024)) == NULL) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory.")); return (1); } if (!getcwd(current, 1024)) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory.")); free(current); return (1); } cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); free(current); } break; case 'f' : /* Run in foreground... */ fg = 1; disconnect = 0; close_all = 0; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ fg = 1; close_all = 0; break; case 'h' : /* Show usage/help */ usage(0); break; case 'l' : /* Started by launchd/systemd/upstart... */ #if defined(HAVE_ONDEMAND) OnDemand = 1; fg = 1; close_all = 0; disconnect = 0; #else _cupsLangPuts(stderr, _("cupsd: On-demand support not compiled " "in, running in normal mode.")); fg = 0; disconnect = 1; close_all = 1; #endif /* HAVE_ONDEMAND */ break; case 'p' : /* Stop immediately for profiling */ fputs("cupsd: -p (startup profiling) is for internal testing " "use only!\n", stderr); stop_scheduler = 1; fg = 1; disconnect = 0; close_all = 0; break; case 'P' : /* Disable security profiles */ fputs("cupsd: -P (disable sandboxing) is for internal testing use only.\n", stderr); UseSandboxing = 0; break; case 's' : /* Set cups-files.conf location */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("cupsd: Expected cups-files.conf " "filename after \"-s\" option.")); usage(1); } if (argv[i][0] != '/') { /* * Relative filename not allowed... */ _cupsLangPuts(stderr, _("cupsd: Relative cups-files.conf " "filename not allowed.")); usage(1); } cupsdSetString(&CupsFilesFile, argv[i]); break; #ifdef __APPLE__ case 'S' : /* Disable system management functions */ fputs("cupsd: -S (disable system management) for internal " "testing use only!\n", stderr); use_sysman = 0; break; #endif /* __APPLE__ */ case 't' : /* Test the cupsd.conf file... */ TestConfigFile = 1; fg = 1; disconnect = 0; close_all = 0; break; case 'T' : /* Print security profile */ print_profile = 1; fg = 1; disconnect = 0; close_all = 0; break; default : /* Unknown option */ _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - " "aborting."), *opt); usage(1); break; } else { _cupsLangPrintf(stderr, _("cupsd: Unknown argument \"%s\" - aborting."), argv[i]); usage(1); } if (!ConfigurationFile) cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); if (!CupsFilesFile) { char *filename, /* Copy of cupsd.conf filename */ *slash; /* Final slash in cupsd.conf filename */ size_t len; /* Size of buffer */ len = strlen(ConfigurationFile) + 15; if ((filename = malloc(len)) == NULL) { _cupsLangPrintf(stderr, _("cupsd: Unable to get path to " "cups-files.conf file.")); return (1); } strlcpy(filename, ConfigurationFile, len); if ((slash = strrchr(filename, '/')) == NULL) { _cupsLangPrintf(stderr, _("cupsd: Unable to get path to " "cups-files.conf file.")); return (1); } strlcpy(slash, "/cups-files.conf", len - (size_t)(slash - filename)); cupsdSetString(&CupsFilesFile, filename); free(filename); } if (disconnect) { /* * Make sure we aren't tying up any filesystems... */ chdir("/"); /* * Disconnect from the controlling terminal... */ setsid(); } if (close_all) { /* * Close all open files... */ getrlimit(RLIMIT_NOFILE, &limit); for (i = 0; i < (int)limit.rlim_cur && i < 1024; i ++) close(i); /* * Redirect stdin/out/err to /dev/null... */ if ((i = open("/dev/null", O_RDONLY)) != 0) { dup2(i, 0); close(i); } if ((i = open("/dev/null", O_WRONLY)) != 1) { dup2(i, 1); close(i); } if ((i = open("/dev/null", O_WRONLY)) != 2) { dup2(i, 2); close(i); } } else LogStderr = cupsFileStderr(); /* * Run in the background as needed... */ if (!fg) { /* * Setup signal handlers for the parent... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGUSR1, parent_handler); sigset(SIGCHLD, parent_handler); sigset(SIGHUP, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGUSR1); action.sa_handler = parent_handler; sigaction(SIGUSR1, &action, NULL); sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGHUP, &action, NULL); #else signal(SIGUSR1, parent_handler); signal(SIGCLD, parent_handler); signal(SIGHUP, SIG_IGN); #endif /* HAVE_SIGSET */ if (fork() > 0) { /* * OK, wait for the child to startup and send us SIGUSR1 or to crash * and the OS send us SIGCHLD... We also need to ignore SIGHUP which * might be sent by the init script to restart the scheduler... */ for (; parent_signal == 0;) sleep(1); if (parent_signal == SIGUSR1) return (0); if (wait(&i) < 0) { perror("cupsd"); return (1); } else if (WIFEXITED(i)) { fprintf(stderr, "cupsd: Child exited with status %d\n", WEXITSTATUS(i)); return (2); } else { fprintf(stderr, "cupsd: Child exited on signal %d\n", WTERMSIG(i)); return (3); } } #if defined(__OpenBSD__) && OpenBSD < 201211 /* * Call _thread_sys_closefrom() so the child process doesn't reset the * parent's file descriptors to be blocking. This is a workaround for a * limitation of userland libpthread on older versions of OpenBSD. */ _thread_sys_closefrom(0); #endif /* __OpenBSD__ && OpenBSD < 201211 */ /* * Since many system libraries create fork-unsafe data on execution of a * program, we need to re-execute the background cupsd with the "-C" and "-s" * options to avoid problems. Unfortunately, we also have to assume that * argv[0] contains the name of the cupsd executable - there is no portable * way to get the real pathname... */ execlp(argv[0], argv[0], "-C", ConfigurationFile, "-s", CupsFilesFile, (char *)0); exit(errno); } /* * Set the timezone info... */ tzset(); #ifdef LC_TIME setlocale(LC_TIME, ""); #endif /* LC_TIME */ #ifdef HAVE_DBUS_THREADS_INIT /* * Enable threading support for D-BUS... */ dbus_threads_init_default(); #endif /* HAVE_DBUS_THREADS_INIT */ /* * Set the maximum number of files... */ getrlimit(RLIMIT_NOFILE, &limit); #if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE) if (limit.rlim_max > FD_SETSIZE) MaxFDs = FD_SETSIZE; else #endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */ #ifdef RLIM_INFINITY if (limit.rlim_max == RLIM_INFINITY) MaxFDs = 16384; else #endif /* RLIM_INFINITY */ MaxFDs = limit.rlim_max; limit.rlim_cur = (rlim_t)MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); cupsdStartSelect(); /* * Read configuration... */ if (!cupsdReadConfiguration()) return (1); else if (TestConfigFile) { printf("\"%s\" is OK.\n", CupsFilesFile); printf("\"%s\" is OK.\n", ConfigurationFile); return (0); } else if (print_profile) { cups_file_t *fp; /* File pointer */ const char *profile = cupsdCreateProfile(42, 0); /* Profile */ char line[1024]; /* Line from file */ if ((fp = cupsFileOpen(profile, "r")) == NULL) { printf("Unable to open profile file \"%s\": %s\n", profile ? profile : "(null)", strerror(errno)); return (1); } while (cupsFileGets(fp, line, sizeof(line))) puts(line); cupsFileClose(fp); return (0); } /* * Clean out old temp files and printer cache data. */ if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot))) cupsdCleanFiles(TempDir, NULL); cupsdCleanFiles(CacheDir, "*.ipp"); #if defined(HAVE_ONDEMAND) if (OnDemand) { /* * If we were started on demand by launchd or systemd get the listen sockets * file descriptors... */ service_checkin(); service_checkout(); } #endif /* HAVE_ONDEMAND */ /* * Startup the server... */ httpInitialize(); cupsdStartServer(); /* * Catch hangup and child signals and ignore broken pipes... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGCHLD, sigchld_handler); sigset(SIGHUP, sighup_handler); sigset(SIGPIPE, SIG_IGN); sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigchld_handler; sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGHUP); action.sa_handler = sighup_handler; sigaction(SIGHUP, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */ signal(SIGHUP, sighup_handler); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ /* * Initialize authentication certificates... */ cupsdInitCerts(); /* * If we are running in the background, signal the parent process that * we are up and running... */ if (!fg || run_as_child) { /* * Send a signal to the parent process, but only if the parent is * not PID 1 (init). This avoids accidentally shutting down the * system on OpenBSD if you CTRL-C the server before it is up... */ i = getppid(); /* Save parent PID to avoid race condition */ if (i != 1) kill(i, SIGUSR1); } #ifdef __APPLE__ /* * Start power management framework... */ if (use_sysman) cupsdStartSystemMonitor(); #endif /* __APPLE__ */ /* * Send server-started event... */ #if defined(HAVE_ONDEMAND) if (OnDemand) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started on demand."); else #endif /* HAVE_ONDEMAND */ if (fg) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in foreground."); else cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in background."); /* * Start any pending print jobs... */ cupsdCheckJobs(); /* * Loop forever... */ current_time = time(NULL); event_time = current_time; expire_time = current_time; fds = 1; report_time = 0; senddoc_time = current_time; while (!stop_scheduler) { /* * Check if there are dead children to handle... */ if (dead_children) process_children(); /* * Check if we need to load the server configuration file... */ if (NeedReload) { /* * Close any idle clients... */ if (cupsArrayCount(Clients) > 0) { for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) if (httpGetState(con->http) == HTTP_WAITING) cupsdCloseClient(con); else con->http->keep_alive = HTTP_KEEPALIVE_OFF; cupsdPauseListening(); } /* * Restart if all clients are closed and all jobs finished, or * if the reload timeout has elapsed... */ if ((cupsArrayCount(Clients) == 0 && (cupsArrayCount(PrintingJobs) == 0 || NeedReload != RELOAD_ALL)) || (time(NULL) - ReloadTime) >= ReloadTimeout) { /* * Shutdown the server... */ #ifdef HAVE_ONDEMAND if (OnDemand) break; #endif /* HAVE_ONDEMAND */ DoingShutdown = 1; cupsdStopServer(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { #ifdef HAVE_SYSTEMD_SD_JOURNAL_H sd_journal_print(LOG_ERR, "Unable to read configuration file \"%s\" - exiting.", ConfigurationFile); #else syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting.", ConfigurationFile); #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ break; } /* * Startup the server... */ DoingShutdown = 0; cupsdStartServer(); /* * Send a server-restarted event... */ cupsdAddEvent(CUPSD_EVENT_SERVER_RESTARTED, NULL, NULL, "Scheduler restarted."); } } /* * Check for available input or ready output. If cupsdDoSelect() * returns 0 or -1, something bad happened and we should exit * immediately. * * Note that we at least have one listening socket open at all * times. */ if ((timeout = select_timeout(fds)) > 1 && LastEvent) timeout = 1; #ifdef HAVE_ONDEMAND /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (timeout == 86400 && OnDemand && IdleExitTimeout && !cupsArrayCount(ActiveJobs) && # ifdef HAVE_SYSTEMD !WebInterface && # endif /* HAVE_SYSTEMD */ (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { timeout = IdleExitTimeout; service_idle_exit = 1; } else service_idle_exit = 0; #endif /* HAVE_ONDEMAND */ if ((fds = cupsdDoSelect(timeout)) < 0) { /* * Got an error from select! */ #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) cupsd_printer_t *p; /* Current printer */ #endif /* HAVE_DNSSD || HAVE_AVAHI */ if (errno == EINTR) /* Just interrupted by a signal */ continue; /* * Log all sorts of debug info to help track down the problem. */ cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!", strerror(errno)); for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients); con; i ++, con = (cupsd_client_t *)cupsArrayNext(Clients)) cupsdLogMessage(CUPSD_LOG_EMERG, "Clients[%d] = %d, file = %d, state = %d", i, con->number, con->file, httpGetState(con->http)); for (i = 0, lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd); cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]); #ifdef __APPLE__ cupsdLogMessage(CUPSD_LOG_EMERG, "SysEventPipes[0] = %d", SysEventPipes[0]); #endif /* __APPLE__ */ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) cupsdLogMessage(CUPSD_LOG_EMERG, "Jobs[%d] = %d < [%d %d] > [%d %d]", job->id, job->status_buffer ? job->status_buffer->fd : -1, job->print_pipes[0], job->print_pipes[1], job->back_pipes[0], job->back_pipes[1]); #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] reg_name=\"%s\"", p->name, p->reg_name ? p->reg_name : "(null)"); #endif /* HAVE_DNSSD || HAVE_AVAHI */ break; } current_time = time(NULL); /* * Write dirty config/state files... */ if (DirtyCleanTime && current_time >= DirtyCleanTime) cupsdCleanDirty(); #ifdef __APPLE__ /* * If we are going to sleep and still have pending jobs, stop them after * a period of time... */ if (SleepJobs > 0 && current_time >= SleepJobs && cupsArrayCount(PrintingJobs) > 0) { SleepJobs = 0; cupsdStopAllJobs(CUPSD_JOB_DEFAULT, 5); } #endif /* __APPLE__ */ #ifndef __APPLE__ /* * Update the network interfaces once a minute... */ if ((current_time - netif_time) >= 60) { netif_time = current_time; NetIFUpdate = 1; } #endif /* !__APPLE__ */ #ifdef HAVE_ONDEMAND /* * If no other work was scheduled and we're being controlled by launchd, * systemd, or upstart then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (!fds && service_idle_exit) { cupsdLogMessage(CUPSD_LOG_INFO, "Printer sharing is off and there are no jobs pending, " "will restart on demand."); stop_scheduler = 1; break; } #endif /* HAVE_ONDEMAND */ /* * Resume listening for new connections as needed... */ if (ListeningPaused && ListeningPaused <= current_time && cupsArrayCount(Clients) < MaxClients) cupsdResumeListening(); /* * Expire subscriptions and unload completed jobs as needed... */ if (current_time > expire_time) { if (cupsArrayCount(Subscriptions) > 0) cupsdExpireSubscriptions(NULL, NULL); cupsdUnloadCompletedJobs(); expire_time = current_time; } #ifndef HAVE_AUTHORIZATION_H /* * Update the root certificate once every 5 minutes if we have client * connections... */ if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration && !RunUser && cupsArrayCount(Clients)) { /* * Update the root certificate... */ cupsdDeleteCert(0); cupsdAddCert(0, "root", cupsdDefaultAuthType()); } #endif /* !HAVE_AUTHORIZATION_H */ /* * Check for new data on the client sockets... */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) { /* * Process pending data in the input buffer... */ if (httpGetReady(con->http)) { cupsdReadClient(con); continue; } /* * Check the activity and close old clients... */ activity = current_time - Timeout; if (httpGetActivity(con->http) < activity && !con->pipe_pid) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity.", con->number, Timeout); cupsdCloseClient(con); continue; } } /* * Update any pending multi-file documents... */ if ((current_time - senddoc_time) >= 10) { cupsdCheckJobs(); senddoc_time = current_time; } /* * Clean job history... */ if (JobHistoryUpdate && current_time >= JobHistoryUpdate) cupsdCleanJobs(); /* * Log statistics at most once a minute when in debug mode... */ if ((current_time - report_time) >= 60 && LogLevel >= CUPSD_LOG_DEBUG) { size_t string_count, /* String count */ alloc_bytes, /* Allocated string bytes */ total_bytes; /* Total string bytes */ #ifdef HAVE_MALLINFO struct mallinfo mem; /* Malloc information */ mem = mallinfo(); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-arena=%lu", mem.arena); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-used=%lu", mem.usmblks + mem.uordblks); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-free=%lu", mem.fsmblks + mem.fordblks); #endif /* HAVE_MALLINFO */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: clients=%d", cupsArrayCount(Clients)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs=%d", cupsArrayCount(Jobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs-active=%d", cupsArrayCount(ActiveJobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d", cupsArrayCount(Printers)); string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-string-count=" CUPS_LLFMT, CUPS_LLCAST string_count); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-alloc-bytes=" CUPS_LLFMT, CUPS_LLCAST alloc_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-total-bytes=" CUPS_LLFMT, CUPS_LLCAST total_bytes); report_time = current_time; } /* * Handle OS-specific event notification for any events that have * accumulated. Don't send these more than once a second... */ if (LastEvent && (current_time - event_time) >= 1) { #ifdef HAVE_NOTIFY_POST if (LastEvent & (CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_DELETED | CUPSD_EVENT_PRINTER_MODIFIED)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerListChange\")"); notify_post("com.apple.printerListChange"); } if (LastEvent & CUPSD_EVENT_PRINTER_STATE_CHANGED) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerHistoryChange\")"); notify_post("com.apple.printerHistoryChange"); } if (LastEvent & (CUPSD_EVENT_JOB_STATE_CHANGED | CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_PROGRESS)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.jobChange\")"); notify_post("com.apple.jobChange"); } #endif /* HAVE_NOTIFY_POST */ /* * Reset the accumulated events... */ LastEvent = CUPSD_EVENT_NONE; event_time = current_time; } } /* * Log a message based on what happened... */ if (stop_scheduler) { cupsdLogMessage(CUPSD_LOG_INFO, "Scheduler shutting down normally."); cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL, "Scheduler shutting down normally."); } else { cupsdLogMessage(CUPSD_LOG_ERROR, "Scheduler shutting down due to program error."); cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL, "Scheduler shutting down due to program error."); } /* * Close all network clients... */ DoingShutdown = 1; cupsdStopServer(); #ifdef HAVE_ONDEMAND /* * Update the keep-alive file as needed... */ if (OnDemand) service_checkout(); #endif /* HAVE_ONDEMAND */ /* * Stop all jobs... */ cupsdFreeAllJobs(); #ifdef __APPLE__ /* * Stop monitoring system event monitoring... */ if (use_sysman) cupsdStopSystemMonitor(); #endif /* __APPLE__ */ cupsdStopSelect(); return (!stop_scheduler); }