📄 main.c
字号:
/* * "$Id: main.c,v 1.128 2005/01/03 19:29:59 mike Exp $" * * Scheduler main loop for the Common UNIX Printing System (CUPS). * * Copyright 1997-2005 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal * copyright law. Distribution and use rights are outlined in the file * "LICENSE" which should have been included with this file. If this * file is missing or damaged please contact Easy Software Products * at: * * Attn: CUPS Licensing Information * Easy Software Products * 44141 Airport View Drive, Suite 204 * Hollywood, Maryland 20636 USA * * Voice: (301) 373-9600 * EMail: cups-info@cups.org * WWW: http://www.cups.org * * Contents: * * main() - Main entry for the CUPS scheduler. * cupsdClosePipe() - Close a pipe as necessary. * cupsdOpenPipe() - Create a pipe which is closed on exec. * CatchChildSignals() - Catch SIGCHLD signals... * HoldSignals() - Hold child and termination signals. * IgnoreChildSignals() - Ignore SIGCHLD signals... * ReleaseSignals() - Release signals for delivery. * SetString() - Set a string value. * SetStringf() - Set a formatted string value. * parent_handler() - Catch USR1/CHLD signals... * process_children() - Process all dead children... * sigchld_handler() - Handle 'child' signals from old processes. * sighup_handler() - Handle 'hangup' signals to reconfigure the scheduler. * sigterm_handler() - Handle 'terminate' signals that stop the scheduler. * select_timeout() - Calculate the select timeout value. * usage() - Show scheduler usage. *//* * Include necessary headers... */#define _MAIN_C_#include "cupsd.h"#include <sys/resource.h>#include <syslog.h>#include <grp.h>#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)# include <malloc.h>#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */#include <stdio.h>/* * Local functions... */static void parent_handler(int sig);#if 0static void process_children(void);#endifstatic void sigchld_handler(int sig);static void sighup_handler(int sig);static void sigterm_handler(int sig);static long select_timeout(int fds);static void usage(void);/* * Local globals... */static int parent_signal = 0; /* Set to signal number from child */static int holdcount = 0; /* Number of times "hold" was called */#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)static sigset_t holdmask; /* Old POSIX signal mask */#endif /* HAVE_SIGACTION && !HAVE_SIGSET */static int dead_children = 0; /* Dead children? */static int stop_scheduler = 0; /* Should the scheduler stop? *//* * 'main()' - Main entry for the CUPS scheduler. */int /* O - Exit status */main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */{ int i; /* Looping var */ char *opt; /* Option character */ int fg; /* Run in the foreground */ int fds; /* Number of ready descriptors select returns */ fd_set *input, /* Input set for select() */ *output; /* Output set for select() */ client_t *con; /* Current client */#if 0 job_t *job, /* Current job */ *next; /* Next job */#endif listener_t *lis; /* Current listener */ time_t activity; /* Activity timer */ time_t browse_time; /* Next browse send time */ time_t senddoc_time; /* Send-Document time */#ifdef HAVE_MALLINFO time_t mallinfo_time; /* Malloc information time */#endif /* HAVE_MALLINFO */ struct timeval timeout; /* select() timeout */ 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 __sgi cups_file_t *fp; /* Fake lpsched lock file */ struct stat statbuf; /* Needed for checking lpsched FIFO */#endif /* __sgi */ /* * Check for command-line arguments... */ fg = 0; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt != '\0'; opt ++) switch (*opt) { case 'c' : /* Configuration file */ i ++; if (i >= argc) usage(); if (argv[i][0] == '/') { /* * Absolute directory... */ SetString(&ConfigurationFile, argv[i]); } else { /* * Relative directory... */ char current[1024]; /* Current directory */ getcwd(current, sizeof(current)); SetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); } break; case 'f' : /* Run in foreground... */ fg = 1; break; case 'F' : /* Run in foreground, but still disconnect from terminal... */ fg = -1; break; default : /* Unknown option */ fprintf(stderr, "cupsd: Unknown option \'%c\' - aborting!\n", *opt); usage(); break; } else { fprintf(stderr, "cupsd: Unknown argument \'%s\' - aborting!\n", argv[i]); usage(); } if (!ConfigurationFile) SetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); DEBUG_printf(("Value ConfigurationFile:%s\n", ConfigurationFile)); /* * If the user hasn't specified "-f", run in the background... */ 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 (fg < 1) { /* * Make sure we aren't tying up any filesystems... */ chdir("/");#ifndef DEBUG /* * Disable core dumps... */ getrlimit(RLIMIT_CORE, &limit); limit.rlim_cur = 0; setrlimit(RLIMIT_CORE, &limit); /* * Disconnect from the controlling terminal... */ close(0); close(1); close(2); setsid();#endif /* DEBUG */ } /* * Set the timezone info... */ if (getenv("TZ") != NULL) SetStringf(&TZ, "TZ=%s", getenv("TZ")); else SetString(&TZ, ""); tzset();#ifdef LC_TIME setlocale(LC_TIME, "");#endif /* LC_TIME */ /* * Set the maximum number of files... */ getrlimit(RLIMIT_NOFILE, &limit); if (limit.rlim_max > CUPS_MAX_FDS) MaxFDs = CUPS_MAX_FDS; else MaxFDs = limit.rlim_max; limit.rlim_cur = MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); /* * Allocate memory for the input and output sets... */ SetSize = (MaxFDs + 31) / 8 + 4; if (SetSize < sizeof(fd_set)) SetSize = sizeof(fd_set); InputSet = (fd_set *)calloc(1, SetSize); OutputSet = (fd_set *)calloc(1, SetSize); input = (fd_set *)calloc(1, SetSize); output = (fd_set *)calloc(1, SetSize); if (InputSet == NULL || OutputSet == NULL || input == NULL || output == NULL) { DEBUG_printf(("Unable to allocate memory for select() sets - exiting!\n")); syslog(LOG_LPR, "Unable to allocate memory for select() sets - exiting!"); return (1); } /* * Read configuration... */ if (!ReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); return (1); } /* * Catch hangup and child signals and ignore broken pipes... */#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ if (RunAsUser) sigset(SIGHUP, sigterm_handler); else 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, SIGHUP); if (RunAsUser) action.sa_handler = sigterm_handler; else 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 if (RunAsUser) signal(SIGHUP, sigterm_handler); else signal(SIGHUP, sighup_handler); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler);#endif /* HAVE_SIGSET */#ifdef __sgi /* * Try to create a fake lpsched lock file if one is not already there. * Some Adobe applications need it under IRIX in order to enable * printing... */ if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL) { syslog(LOG_LPR, "Unable to create fake lpsched lock file " "\"/var/spool/lp/SCHEDLOCK\"\' - %s!", strerror(errno)); } else { fchmod(cupsFileNumber(fp), 0644); fchown(cupsFileNumber(fp), User, Group); cupsFileClose(fp); }#endif /* __sgi */#if 0 /* * Initialize authentication certificates... */ InitCerts();#endif /* * If we are running in the background, signal the parent process that * we are up and running... */ if (!fg) kill(getppid(), SIGUSR1); /* * If the administrator has configured the server to run as an unpriviledged * user, change to that user now... */ if (RunAsUser) { setgid(Group); setgroups(1, &Group); setuid(User); } #if 0 /* * Start any pending print jobs... */ CheckJobs();#endif /* * Loop forever... */#ifdef HAVE_MALLINFO mallinfo_time = 0;#endif /* HAVE_MALLINFO */ browse_time = time(NULL); senddoc_time = time(NULL); fds = 1; while (!stop_scheduler) {#ifdef DEBUG LogMessage(L_DEBUG2, "main: Top of loop, dead_children=%d, NeedReload=%d", dead_children, NeedReload);#endif /* DEBUG */#if 0 /* * 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) { job_t *job; /* Current job */ /* * Close any idle clients... */ if (NumClients > 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -