static void usage(FILE *fp) /* I - File to send usage to */ { if (getuid()) _cupsLangPuts(fp, _("Usage: lppasswd [-g groupname]\n")); else _cupsLangPuts(fp, _("Usage: lppasswd [-g groupname] [username]\n" " lppasswd [-g groupname] -a [username]\n" " lppasswd [-g groupname] -x [username]\n")); exit(1); }
static void usage(void) { _cupsLangPuts(stdout, _("Usage: ippdiscover [options] -a\n" " ippdiscover [options] \"service name\"\n" "\n" "Options:")); _cupsLangPuts(stdout, _(" -a Browse for all services.")); _cupsLangPuts(stdout, _(" -d domain Browse/resolve in specified domain.")); _cupsLangPuts(stdout, _(" -p program Run specified program for each service.")); _cupsLangPuts(stdout, _(" -t type Browse/resolve with specified type.")); exit(0); }
static void usage(const char *opt) /* I - Option character/string */ { if (opt) { if (*opt == '-') _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"%s\"!\n"), opt); else _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"-%c\"!\n"), *opt); } _cupsLangPuts(stdout, _("Usage: cupsctl [options] [param=value ... paramN=valueN]\n" "\n" "Options:\n" "\n" " -E Enable encryption\n" " -U username Specify username\n" " -h server[:port] Specify server address\n" "\n" " --[no-]debug-logging Turn debug logging on/off\n" " --[no-]remote-admin Turn remote administration " "on/off\n" " --[no-]remote-any Allow/prevent access from the " "Internet\n" " --[no-]remote-printers Show/hide remote printers\n" " --[no-]share-printers Turn printer sharing on/off\n" " --[no-]user-cancel-any Allow/prevent users to cancel " "any job\n")); exit(1); }
static void usage(void) { _cupsLangPuts(stderr, _("Usage: lpq [-P dest] [-U username] [-h hostname[:port]] " "[-l] [+interval]")); exit(1); }
void usage(void) { _cupsLangPuts(stdout, _("Usage: cupsaddsmb [options] printer1 ... printerN")); _cupsLangPuts(stdout, _(" cupsaddsmb [options] -a")); _cupsLangPuts(stdout, ""); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _(" -E Encrypt the connection.")); _cupsLangPuts(stdout, _(" -H samba-server Use the named SAMBA " "server.")); _cupsLangPuts(stdout, _(" -U username Specify username.")); _cupsLangPuts(stdout, _(" -a Export all printers.")); _cupsLangPuts(stdout, _(" -h server[:port] Specify server address.")); _cupsLangPuts(stdout, _(" -v Be verbose.")); exit(1); }
static void usage(void) { _cupsLangPuts(stdout, _("Usage: lpoptions [options] -d destination\n" " lpoptions [options] [-p destination] [-l]\n" " lpoptions [options] [-p destination] -o option[=value]\n" " lpoptions [options] -x destination")); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _("-d destination Set default destination")); _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port")); _cupsLangPuts(stdout, _("-l Show supported options and values")); _cupsLangPuts(stdout, _("-o name[=value] Set default option and value")); _cupsLangPuts(stdout, _("-p destination Specify a destination")); _cupsLangPuts(stdout, _("-U username Specify the username to use for authentication")); _cupsLangPuts(stdout, _("-x destination Remove default options for destination")); exit(1); }
static void usage(void) { _cupsLangPuts(stdout, _("Usage: lpoptions [-h server] [-E] -d printer\n" " lpoptions [-h server] [-E] [-p printer] -l\n" " lpoptions [-h server] [-E] -p printer -o " "option[=value] ...\n" " lpoptions [-h server] [-E] -x printer")); exit(1); }
static void usage(const char *command, /* I - Command name */ const char *opt) /* I - Incorrect option, if any */ { if (opt) _cupsLangPrintf(stderr, _("%s: Unknown option '%c'!\n"), command, *opt); if (!strcmp(command, "cupsfilter")) _cupsLangPuts(stdout, _("Usage: cupsfilter -m mime/type [ options ] filename\n" "\n" "Options:\n" "\n" " -c cupsd.conf Set cupsd.conf file to use\n" " -n copies Set number of copies\n" " -o name=value Set option(s)\n" " -p filename.ppd Set PPD file\n" " -t title Set title\n")); else _cupsLangPuts(stdout, _("Usage: convert [ options ]\n" "\n" "Options:\n" "\n" " -f filename Set file to be converted (otherwise stdin)\n" " -o filename Set file to be generated (otherwise stdout)\n" " -i mime/type Set input MIME type (otherwise auto-typed)\n" " -j mime/type Set output MIME type (otherwise application/pdf)\n" " -P filename.ppd Set PPD file\n" " -a 'name=value ...' Set option(s)\n" " -U username Set username for job\n" " -J title Set title\n" " -c copies Set number of copies\n" " -u Remove the PPD file when finished\n" " -D Remove the input file when finished\n")); exit(1); }
static void usage(void) { _cupsLangPuts(stdout, _("Usage: cupstestdsc [options] filename.ps [... " "filename.ps]")); _cupsLangPuts(stdout, _(" cupstestdsc [options] -")); _cupsLangPuts(stdout, ""); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, ""); _cupsLangPuts(stdout, _(" -h Show program usage")); _cupsLangPuts(stdout, ""); _cupsLangPuts(stdout, _("Note: this program only validates the DSC comments, " "not the PostScript itself.")); exit(1); }
static void usage(int status) /* O - Exit status */ { FILE *fp = status ? stderr : stdout; /* Output file */ _cupsLangPuts(fp, _("Usage: cupsd [options]")); _cupsLangPuts(fp, _("Options:")); _cupsLangPuts(fp, _(" -c cupsd.conf Set cupsd.conf file to use.")); _cupsLangPuts(fp, _(" -f Run in the foreground.")); _cupsLangPuts(fp, _(" -F Run in the foreground but detach from console.")); _cupsLangPuts(fp, _(" -h Show this usage message.")); #ifdef HAVE_ONDEMAND _cupsLangPuts(fp, _(" -l Run cupsd on demand.")); #endif /* HAVE_ONDEMAND */ _cupsLangPuts(fp, _(" -s cups-files.conf Set cups-files.conf file to use.")); _cupsLangPuts(fp, _(" -t Test the configuration file.")); exit(status); }
static void usage(const char *opt) /* I - Option character/string */ { if (opt) { if (*opt == '-') _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"%s\""), opt); else _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"-%c\""), *opt); } _cupsLangPuts(stdout, _("Usage: cupsctl [options] [param=value ... paramN=valueN]")); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port")); _cupsLangPuts(stdout, _("-U username Specify username to use for authentication")); _cupsLangPuts(stdout, _("--[no-]debug-logging Turn debug logging on/off")); _cupsLangPuts(stdout, _("--[no-]remote-admin Turn remote administration on/off")); _cupsLangPuts(stdout, _("--[no-]remote-any Allow/prevent access from the Internet")); _cupsLangPuts(stdout, _("--[no-]share-printers Turn printer sharing on/off")); _cupsLangPuts(stdout, _("--[no-]user-cancel-any Allow/prevent users to cancel any job")); exit(1); }
static void usage(int status) /* O - Exit status */ { FILE *fp = status ? stderr : stdout; /* Output file */ _cupsLangPuts(fp, _("Usage: cupsd [options]")); _cupsLangPuts(fp, _("Options:")); _cupsLangPuts(fp, _(" -c cupsd.conf Set cupsd.conf file to use.")); _cupsLangPuts(fp, _(" -f Run in the foreground.")); _cupsLangPuts(fp, _(" -F Run in the foreground but " "detach from console.")); _cupsLangPuts(fp, _(" -h Show this usage message.")); _cupsLangPuts(fp, _(" -l Run cupsd from launchd(8).")); _cupsLangPuts(fp, _(" -t Test the configuration " "file.")); exit(status); }
static void usage(const char *command) /* I - Command name */ { _cupsLangPrintf(stdout, _("Usage: %s [options] destination(s)"), command); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port")); _cupsLangPuts(stdout, _("-r reason Specify a reason message that others can see")); _cupsLangPuts(stdout, _("-U username Specify the username to use for authentication")); if (!strcmp(command, "cupsdisable")) _cupsLangPuts(stdout, _("--hold Hold new jobs")); if (!strcmp(command, "cupsenable")) _cupsLangPuts(stdout, _("--release Release previously held jobs")); exit(1); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[] /* I - Command-line arguments */ #ifdef PRINT_AUXV , char* envp[] #endif ) { int i; /* Looping var */ char *opt; /* Option character */ int fg; /* Run in the foreground */ 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 */ browse_time, /* Next browse send time */ senddoc_time, /* Send-Document time */ expire_time, /* Subscription expire time */ report_time, /* Malloc/client/job report time */ event_time; /* Last time an event notification was done */ 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 __sgi cups_file_t *fp; /* Fake lpsched lock file */ struct stat statbuf; /* Needed for checking lpsched FIFO */ #endif /* __sgi */ #ifdef __APPLE__ int run_as_child = 0; /* Needed for Mac OS X fork/exec */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ #if HAVE_LAUNCHD int launchd_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_LAUNCHD */ #ifdef PRINT_AUXV Elf32_auxv_t *auxv; while(*envp++ != NULL); for (auxv = (Elf32_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { if (auxv->a_type == AT_SYSINFO) { printf("AT_RANDOM is 0x%x\n", auxv->a_un.a_val); } } #endif #if UNDERSTAND_CUPS printf("[main.c::main()] cups has just started in main()\n"); #endif int count = 0; int loops_desired = -1; // loop forever unless this is set #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); } #if UNDERSTAND_CUPS printf("[main.c::main()] uid = %d, euid = %d\n", getuid(), geteuid()); #endif #endif /* HAVE_GETEUID */ /* * Check for command-line arguments... */ #if UNDERSTAND_CUPS printf("[main.c::main()] parsing command line arguments \n"); #endif fg = 0; #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { Launchd = 1; fg = 1; } #endif /* HAVE_LAUNCHD */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt != '\0'; opt ++) switch (*opt) { #ifdef __APPLE__ case 'C' : /* Run as child with config file */ run_as_child = 1; fg = -1; #endif /* __APPLE__ */ case 'c' : /* Configuration file */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("cupsd: Expected config filename " "after \"-c\" option!\n")); 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!\n")); return (1); } if (!getcwd(current, 1024)) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory!\n")); free(current); return (1); } cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); free(current); } break; case 'f' : /* Run in foreground... */ fg = 1; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ fg = -1; break; case 'h' : /* Show usage/help */ usage(0); break; case 'l' : /* Started by launchd... */ #ifdef HAVE_LAUNCHD Launchd = 1; fg = 1; #else _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " "in, running in normal mode.\n")); fg = 0; #endif /* HAVE_LAUNCHD */ break; case 'p' : /* Stop immediately for profiling */ puts("Warning: -p option is for internal testing use only!"); stop_scheduler = 1; fg = 1; break; /// XXX RAZA case 'x' : /* Number of Iterations to Perform */ i ++; loops_desired = atoi(argv[i]); break; default : /* Unknown option */ _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - " "aborting!\n"), *opt); usage(1); break; } else { _cupsLangPrintf(stderr, _("cupsd: Unknown argument \"%s\" - aborting!\n"), argv[i]); usage(1); } #if UNDERSTAND_CUPS printf("[main.c::main()] done parsing command line arguments \n"); printf("[main.c::main()] num_loops = %d, foreground = %d\n", loops_desired, fg); #endif if (!ConfigurationFile) cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); printf("[main.c::main()] configuration file = %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); } } #ifdef __APPLE__ /* * Since CoreFoundation has an overly-agressive check for whether a * process has forked but not exec'd (whether CF has been called or * not...), we now have to exec ourselves with the "-f" option to * eliminate their bogus warning messages. */ execlp(argv[0], argv[0], "-C", ConfigurationFile, (char *)0); exit(errno); #endif /* __APPLE__ */ } 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... */ setsid(); /* * Close all open files... */ getrlimit(RLIMIT_NOFILE, &limit); for (i = 0; i < limit.rlim_cur && i < 1024; i ++) close(i); #endif /* DEBUG */ } /* * Set the timezone info... */ #if UNDERSTAND_CUPS printf("[main.c::main()] setting timezone info, tzset()\n"); #endif tzset(); #ifdef LC_TIME setlocale(LC_TIME, ""); #if UNDERSTAND_CUPS printf("[main.c::main()] setting locale info, setlocale()\n"); #endif #endif /* LC_TIME */ /* * 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 = MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); #if UNDERSTAND_CUPS printf("[main.c::main()] set the maximum nuber of files = %d\n", MaxFDs); #endif cupsdStartSelect(); #if UNDERSTAND_CUPS printf("[main.c::main()] done with cupsdStartSelect() i.e. polling engine\n"); #endif /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); return (1); } printf("[main.c::main()] done with cupsdReadConfiguration\n"); if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot))) { /* * Clean out the temporary directory... */ cups_dir_t *dir; /* Temporary directory */ cups_dentry_t *dent; /* Directory entry */ char tempfile[1024]; /* Temporary filename */ printf("[main.c::main()] cleaning temp dir = %s\n", TempDir); if ((dir = cupsDirOpen(TempDir)) != NULL) { cupsdLogMessage(CUPSD_LOG_INFO, "Cleaning out old temporary files in \"%s\"...", TempDir); while ((dent = cupsDirRead(dir)) != NULL) { snprintf(tempfile, sizeof(tempfile), "%s/%s", TempDir, dent->filename); printf("[main.c::main()] deleting temp file = %s\n", tempfile); if (cupsdRemoveFile(tempfile)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove temporary file \"%s\" - %s", tempfile, strerror(errno)); printf("[main.c::main()] failed in deleting temp file = %s\n", tempfile); } else { cupsdLogMessage(CUPSD_LOG_DEBUG, "Removed temporary file \"%s\"...", tempfile); printf("[main.c::main()] deleted temp file = %s\n", tempfile); } } cupsDirClose(dir); } else { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open temporary directory \"%s\" - %s", TempDir, strerror(errno)); printf("[main.c::main()] couldn't open temp dir = %s\n", TempDir); } printf("[main.c::main()] DONE cleaning temp dir = %s\n", TempDir); } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ printf("[main.c::main()] launchd check in \n"); launchd_checkin(); } #endif /* HAVE_LAUNCHD */ #if defined(__APPLE__) && defined(HAVE_DLFCN_H) /* * Load Print Service quota enforcement library (X Server only) */ PSQLibRef = dlopen(PSQLibPath, RTLD_LAZY); if (PSQLibRef) PSQUpdateQuotaProc = dlsym(PSQLibRef, PSQLibFuncName); #endif /* __APPLE__ && HAVE_DLFCN_H */ #ifdef HAVE_GSSAPI # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ /* * Setup a Kerberos context for the scheduler to use... */ if (krb5_init_context(&KerberosContext)) { KerberosContext = NULL; printf("[main.c::main()] unable to use krb5_init_context() \n"); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context"); } else { printf("[main.c::main()] used krb5_init_context() \n"); } #endif /* HAVE_GSSAPI */ /* * Startup the server... */ 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); printf("[main.c::main()] used system V signals over POSIX\n"); #elif defined(HAVE_SIGACTION) printf("[main.c::main()] used HAVE_SIGACTION\n"); 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 printf("[main.c::main()]last signal options\n"); 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 */ #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... */ printf("[main.c::main()] creating fake lpsched lock file \n"); 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 */ /* * Initialize authentication certificates... */ cupsdInitCerts(); /* * If we are running in the background, signal the parent process that * we are up and running... */ #ifdef __APPLE__ if (!fg || run_as_child) #else if (!fg) #endif /* __APPLE__ */ { /* * 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... */ printf("[main.c::main()] starting system monitor (power management) \n"); cupsdStartSystemMonitor(); #endif /* __APPLE__ */ /* * Start any pending print jobs... */ printf("[main.c::main()] starting any pending print jobs \n"); cupsdCheckJobs(); /* * Loop forever... */ current_time = time(NULL); browse_time = current_time; event_time = current_time; expire_time = current_time; fds = 1; report_time = 0; senddoc_time = current_time; while (!stop_scheduler) { // XXX RAZA printf("[main.c::main()] scheduler loop # %d\n", count); if (count++ == loops_desired) { printf("[main.c::main()] stopping scheduler loop\n"); stop_scheduler = 1; continue; } printf("[main.c::main()] Top of loop, dead_children=%d, NeedReload=%d\n", dead_children, NeedReload); #ifdef DEBUG cupsdLogMessage(CUPSD_LOG_DEBUG2, "main: Top of loop, dead_children=%d, NeedReload=%d", dead_children, NeedReload); #endif /* DEBUG */ /* * 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 (con->http.state == HTTP_WAITING) cupsdCloseClient(con); else con->http.keep_alive = HTTP_KEEPALIVE_OFF; cupsdPauseListening(); } /* * Check for any active jobs... */ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) if (job->state_value == IPP_JOB_PROCESSING) break; /* * Restart if all clients are closed and all jobs finished, or * if the reload timeout has elapsed... */ if ((cupsArrayCount(Clients) == 0 && (!job || NeedReload != RELOAD_ALL)) || (time(NULL) - ReloadTime) >= ReloadTimeout) { /* * Shutdown the server... */ cupsdStopServer(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); break; } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ launchd_checkin(); } #endif /* HAVE_LAUNCHD */ /* * Startup the server... */ cupsdStartServer(); } } /* * 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; #if HAVE_LAUNCHD /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (timeout == 86400 && Launchd && LaunchdTimeout && !NumPolled && !cupsArrayCount(ActiveJobs) && (!Browsing || (!BrowseRemoteProtocols && (!NumBrowsers || !BrowseLocalProtocols || cupsArrayCount(Printers) == 0)))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; } else launchd_idle_exit = 0; #endif /* HAVE_LAUNCHD */ if ((fds = cupsdDoSelect(timeout)) < 0) { /* * Got an error from select! */ #ifdef HAVE_DNSSD cupsd_printer_t *p; /* Current printer */ #endif /* HAVE_DNSSD */ 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->http.fd, con->file, con->http.state); 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, "BrowseSocket = %d", BrowseSocket); 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]); #ifdef HAVE_DNSSD for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] %d", p->name, p->dnssd_ipp_fd); #endif /* HAVE_DNSSD */ break; } current_time = time(NULL); #ifndef __APPLE__ /* * Update the network interfaces once a minute... */ if ((current_time - netif_time) >= 60) { netif_time = current_time; NetIFUpdate = 1; } #endif /* !__APPLE__ */ #if HAVE_LAUNCHD /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ if (!fds && launchd_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_LAUNCHD */ /* * 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; } /* * Update the browse list as needed... */ if (Browsing) { #ifdef HAVE_LIBSLP if ((BrowseRemoteProtocols & BROWSE_SLP) && BrowseSLPRefresh <= current_time) cupsdUpdateSLPBrowse(); #endif /* HAVE_LIBSLP */ #ifdef HAVE_LDAP if ((BrowseRemoteProtocols & BROWSE_LDAP) && BrowseLDAPRefresh <= current_time) cupsdUpdateLDAPBrowse(); #endif /* HAVE_LDAP */ } if (Browsing && current_time > browse_time) { cupsdSendBrowseList(); browse_time = current_time; } /* * 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", NULL); } /* * 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 (con->http.used) { cupsdReadClient(con); continue; } /* * Check the activity and close old clients... */ activity = current_time - Timeout; if (con->http.activity < activity && !con->pipe_pid) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity...", con->http.fd, Timeout); cupsdCloseClient(con); continue; } } /* * Update any pending multi-file documents... */ if ((current_time - senddoc_time) >= 10) { cupsdCheckJobs(); senddoc_time = current_time; } /* * 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)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers-implicit=%d", cupsArrayCount(ImplicitPrinters)); 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."); else cupsdLogMessage(CUPSD_LOG_ERROR, "Scheduler shutting down due to program error."); /* * Close all network clients... */ cupsdStopServer(); #ifdef HAVE_LAUNCHD /* * Update the launchd KeepAlive file as needed... */ if (Launchd) launchd_checkout(); #endif /* HAVE_LAUNCHD */ /* * Stop all jobs... */ cupsdFreeAllJobs(); #ifdef __APPLE__ /* * Stop monitoring system event monitoring... */ cupsdStopSystemMonitor(); #endif /* __APPLE__ */ #ifdef HAVE_GSSAPI /* * Free the scheduler's Kerberos context... */ # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ if (KerberosContext) krb5_free_context(KerberosContext); #endif /* HAVE_GSSAPI */ #ifdef __APPLE__ #ifdef HAVE_DLFCN_H /* * Unload Print Service quota enforcement library (X Server only) */ PSQUpdateQuotaProc = NULL; if (PSQLibRef) { dlclose(PSQLibRef); PSQLibRef = NULL; } #endif /* HAVE_DLFCN_H */ #endif /* __APPLE__ */ #ifdef __sgi /* * Remove the fake IRIX lpsched lock file, but only if the existing * file is not a FIFO which indicates that the real IRIX lpsched is * running... */ if (!stat("/var/spool/lp/FIFO", &statbuf)) if (!S_ISFIFO(statbuf.st_mode)) unlink("/var/spool/lp/SCHEDLOCK"); #endif /* __sgi */ cupsdStopSelect(); return (!stop_scheduler); }
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 fg; /* Run in the foreground */ 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 __sgi cups_file_t *fp; /* Fake lpsched lock file */ struct stat statbuf; /* Needed for checking lpsched FIFO */ #endif /* __sgi */ int run_as_child = 0; /* Needed for background fork/exec */ #ifdef __APPLE__ int use_sysman = !getuid(); /* Use system management functions? */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ #if HAVE_LAUNCHD int launchd_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_LAUNCHD */ #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")) { Launchd = 1; fg = 1; } #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; 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; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ fg = -1; break; case 'h' : /* Show usage/help */ usage(0); break; case 'l' : /* Started by launchd... */ #ifdef HAVE_LAUNCHD Launchd = 1; fg = 1; #else _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " "in, running in normal mode.")); fg = 0; #endif /* HAVE_LAUNCHD */ 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; break; case 'P' : /* Disable security profiles */ fputs("cupsd: -P (disable security profiles) is for internal " "testing use only!\n", stderr); UseProfiles = 0; 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; 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 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); } } #ifdef __OpenBSD__ /* * 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 OpenBSD. */ _thread_sys_closefrom(0); #endif /* __OpenBSD__ */ /* * Since CoreFoundation and DBUS both create fork-unsafe data on execution of * a program, and since this kind of really unfriendly behavior seems to be * more common these days in system libraries, we need to re-execute the * background cupsd with the "-C" option 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, (char *)0); exit(errno); } 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... */ setsid(); /* * Close all open files... */ getrlimit(RLIMIT_NOFILE, &limit); for (i = 0; i < 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); } #endif /* DEBUG */ } /* * Set the timezone info... */ tzset(); #ifdef LC_TIME setlocale(LC_TIME, ""); #endif /* LC_TIME */ /* * 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 = MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); cupsdStartSelect(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { if (TestConfigFile) printf("%s contains errors\n", ConfigurationFile); else syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); return (1); } else if (TestConfigFile) { printf("%s is OK\n", ConfigurationFile); return (0); } /* * Clean out old temp files and printer cache data. */ if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot))) cupsdCleanFiles(TempDir, NULL); cupsdCleanFiles(CacheDir, "*.ipp"); #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ launchd_checkin(); launchd_checkout(); } #endif /* HAVE_LAUNCHD */ /* * 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 */ #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 */ /* * 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... */ #ifdef HAVE_LAUNCHD if (Launchd) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started via launchd."); else #endif /* HAVE_LAUNCHD */ 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 (con->http.state == 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... */ DoingShutdown = 1; cupsdStopServer(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); break; } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd, get the listen socket file * descriptors... */ launchd_checkin(); launchd_checkout(); } #endif /* HAVE_LAUNCHD */ /* * 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; #if HAVE_LAUNCHD /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (timeout == 86400 && Launchd && LaunchdTimeout && !cupsArrayCount(ActiveJobs) && (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; } else launchd_idle_exit = 0; #endif /* HAVE_LAUNCHD */ if ((fds = cupsdDoSelect(timeout)) < 0) { /* * Got an error from select! */ #ifdef HAVE_DNSSD cupsd_printer_t *p; /* Current printer */ #endif /* HAVE_DNSSD */ 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->http.fd, con->file, con->http.state); 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]); #ifdef HAVE_DNSSD 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 */ 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__ */ #if HAVE_LAUNCHD /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ if (!fds && launchd_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_LAUNCHD */ /* * 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", NULL); } #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 (con->http.used) { cupsdReadClient(con); continue; } /* * Check the activity and close old clients... */ activity = current_time - Timeout; if (con->http.activity < activity && !con->pipe_pid) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity...", con->http.fd, 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_LAUNCHD /* * Update the launchd KeepAlive file as needed... */ if (Launchd) launchd_checkout(); #endif /* HAVE_LAUNCHD */ /* * Stop all jobs... */ cupsdFreeAllJobs(); #ifdef __APPLE__ /* * Stop monitoring system event monitoring... */ if (use_sysman) cupsdStopSystemMonitor(); #endif /* __APPLE__ */ #ifdef HAVE_GSSAPI /* * Free the scheduler's Kerberos context... */ # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ if (KerberosContext) krb5_free_context(KerberosContext); #endif /* HAVE_GSSAPI */ #ifdef __sgi /* * Remove the fake IRIX lpsched lock file, but only if the existing * file is not a FIFO which indicates that the real IRIX lpsched is * running... */ if (!stat("/var/spool/lp/FIFO", &statbuf)) if (!S_ISFIFO(statbuf.st_mode)) unlink("/var/spool/lp/SCHEDLOCK"); #endif /* __sgi */ cupsdStopSelect(); return (!stop_scheduler); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { int ipv4, /* SNMP IPv4 socket */ ipv6; /* SNMP IPv6 socket */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Check command-line options... */ if (argc > 2) { _cupsLangPuts(stderr, _("Usage: snmp [host-or-ip-address]")); return (1); } /* * Set the password callback for IPP operations... */ cupsSetPasswordCB(password_cb); /* * Catch SIGALRM signals... */ #ifdef HAVE_SIGSET sigset(SIGALRM, alarm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGALRM); action.sa_handler = alarm_handler; sigaction(SIGALRM, &action, NULL); #else signal(SIGALRM, alarm_handler); #endif /* HAVE_SIGSET */ /* * Open the SNMP socket... */ if ((ipv4 = _cupsSNMPOpen(AF_INET)) < 0) return (1); #ifdef AF_INET6 if ((ipv6 = _cupsSNMPOpen(AF_INET6)) < 0) perror("DEBUG: Unable to create IPv6 socket"); #else ipv6 = -1; #endif /* AF_INET6 */ /* * Read the configuration file and any cache data... */ read_snmp_conf(argv[1]); _cupsSNMPSetDebug(DebugLevel); Devices = cupsArrayNew((cups_array_func_t)compare_cache, NULL); /* * Scan for devices... */ scan_devices(ipv4, ipv6); /* * Close, free, and return with no errors... */ _cupsSNMPClose(ipv4); if (ipv6 >= 0) _cupsSNMPClose(ipv6); free_array(Addresses); free_array(Communities); free_cache(); return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping vars */ const char *command, /* Command name */ *opt; /* Current option */ char *srctype, /* Source type */ *dsttype, /* Destination type */ super[MIME_MAX_SUPER], /* Super-type name */ type[MIME_MAX_TYPE]; /* Type name */ int compression; /* Compression of file */ int cost; /* Cost of filters */ mime_t *mime; /* MIME database */ char *infile, /* File to filter */ *outfile; /* File to create */ char cupsdconf[1024]; /* cupsd.conf file */ const char *server_root; /* CUPS_SERVERROOT environment variable */ mime_type_t *src, /* Source type */ *dst; /* Destination type */ cups_array_t *filters; /* Filters for the file */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ const char *ppdfile; /* PPD file */ const char *title, /* Title string */ *user; /* Username */ int removeppd, /* Remove PPD file */ removeinfile; /* Remove input file */ int status; /* Execution status */ /* * Setup defaults... */ if ((command = strrchr(argv[0], '/')) != NULL) command ++; else command = argv[0]; mime = NULL; srctype = NULL; compression = 0; dsttype = "application/pdf"; infile = NULL; outfile = NULL; num_options = 0; options = NULL; ppdfile = NULL; title = NULL; user = cupsUser(); removeppd = 0; removeinfile = 0; if ((server_root = getenv("CUPS_SERVERROOT")) == NULL) server_root = CUPS_SERVERROOT; snprintf(cupsdconf, sizeof(cupsdconf), "%s/cupsd.conf", server_root); /* * Process command-line arguments... */ _cupsSetLocale(argv); for (i = 1; i < argc; i ++) if (argv[i][0] == '-') { for (opt = argv[i] + 1; *opt; opt ++) switch (*opt) { case '-' : /* Next argument is a filename... */ i ++; if (i < argc && !infile) infile = argv[i]; else usage(command, opt); break; case 'a' : /* Specify option... */ i ++; if (i < argc) num_options = cupsParseOptions(argv[i], num_options, &options); else usage(command, opt); break; case 'c' : /* Specify cupsd.conf file location... */ i ++; if (i < argc) { if (!strcmp(command, "convert")) num_options = cupsAddOption("copies", argv[i], num_options, &options); else strlcpy(cupsdconf, argv[i], sizeof(cupsdconf)); } else usage(command, opt); break; case 'D' : /* Delete input file after conversion */ removeinfile = 1; break; case 'f' : /* Specify input file... */ i ++; if (i < argc && !infile) infile = argv[i]; else usage(command, opt); break; case 'i' : /* Specify source MIME type... */ i ++; if (i < argc) { if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) usage(command, opt); srctype = argv[i]; } else usage(command, opt); break; case 'j' : /* Specify destination MIME type... */ case 'm' : /* Specify destination MIME type... */ i ++; if (i < argc) { if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) usage(command, opt); dsttype = argv[i]; } else usage(command, opt); break; case 'n' : /* Specify number of copies... */ i ++; if (i < argc) num_options = cupsAddOption("copies", argv[i], num_options, &options); else usage(command, opt); break; case 'o' : /* Specify option(s) or output filename */ i ++; if (i < argc) { if (!strcmp(command, "convert")) { if (outfile) usage(command, NULL); else outfile = argv[i]; } else num_options = cupsParseOptions(argv[i], num_options, &options); } else usage(command, opt); break; case 'p' : /* Specify PPD file... */ case 'P' : /* Specify PPD file... */ i ++; if (i < argc) ppdfile = argv[i]; else usage(command, opt); break; case 't' : /* Specify title... */ case 'J' : /* Specify title... */ i ++; if (i < argc) title = argv[i]; else usage(command, opt); break; case 'u' : /* Delete PPD file after conversion */ removeinfile = 1; break; case 'U' : /* Specify username... */ i ++; if (i < argc) user = argv[i]; else usage(command, opt); break; default : /* Something we don't understand... */ usage(command, opt); break; } } else if (!infile) { if (strcmp(command, "convert")) infile = argv[i]; else { _cupsLangPuts(stderr, _("convert: Use the -f option to specify a file to " "convert.\n")); usage(command, NULL); } } else { _cupsLangPuts(stderr, _("cupsfilter: Only one filename can be specified!\n")); usage(command, NULL); } if (!infile && !srctype) usage(command, NULL); if (!title) { if (!infile) title = "(stdin)"; else if ((title = strrchr(infile, '/')) != NULL) title ++; else title = infile; } /* * Load the cupsd.conf file and create the MIME database... */ if (read_cupsd_conf(cupsdconf)) return (1); if ((mime = mimeLoad(ServerRoot, Path)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to read MIME database from \"%s\"!\n"), command, ServerRoot); return (1); } /* * Get the source and destination types... */ if (srctype) { sscanf(srctype, "%15[^/]/%255s", super, type); if ((src = mimeType(mime, super, type)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unknown source MIME type %s/%s!\n"), command, super, type); return (1); } } else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to determine MIME type of \"%s\"!\n"), command, infile); return (1); } sscanf(dsttype, "%15[^/]/%255s", super, type); if ((dst = mimeType(mime, super, type)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unknown destination MIME type %s/%s!\n"), command, super, type); return (1); } /* * Figure out how to filter the file... */ if (src == dst) { /* * Special case - no filtering needed... */ filters = cupsArrayNew(NULL, NULL); cupsArrayAdd(filters, &GZIPFilter); } else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL) { _cupsLangPrintf(stderr, _("%s: No filter to convert from %s/%s to %s/%s!\n"), command, src->super, src->type, dst->super, dst->type); return (1); } else if (compression) cupsArrayInsert(filters, &GZIPFilter); /* * Do it! */ status = exec_filters(filters, infile, outfile, ppdfile, !strcmp(command, "convert") ? "tofile" : "cupsfilter", user, title, num_options, options); /* * Remove files as needed, then exit... */ if (removeppd && ppdfile) unlink(ppdfile); if (removeinfile && infile) unlink(infile); return (status); }
static void show_status(http_t *http, /* I - HTTP connection to server */ const char *dests) /* I - Destinations */ { ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ char *printer, /* Printer name */ *device, /* Device URI */ *delimiter; /* Char search result */ ipp_pstate_t pstate; /* Printer state */ int accepting; /* Is printer accepting jobs? */ int jobcount; /* Count of current jobs */ const char *dptr, /* Pointer into destination list */ *ptr; /* Pointer into printer name */ int match; /* Non-zero if this job matches */ static const char *requested[] = /* Requested attributes */ { "device-uri", "printer-is-accepting-jobs", "printer-name", "printer-state", "queued-job-count" }; DEBUG_printf(("show_status(http=%p, dests=\"%s\")\n", http, dests)); if (http == NULL) return; /* * Build a CUPS_GET_PRINTERS request, which requires the following * attributes: * * attributes-charset * attributes-natural-language */ request = ippNewRequest(CUPS_GET_PRINTERS); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(requested) / sizeof(requested[0]), NULL, requested); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { DEBUG_puts("show_status: request succeeded..."); /* * Loop through the printers returned in the list and display * their status... */ for (attr = response->attrs; attr != NULL; attr = attr->next) { /* * Skip leading attributes until we hit a job... */ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) attr = attr->next; if (attr == NULL) break; /* * Pull the needed attributes from this job... */ printer = NULL; device = "file:/dev/null"; pstate = IPP_PRINTER_IDLE; jobcount = 0; accepting = 1; while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { if (!strcmp(attr->name, "device-uri") && attr->value_tag == IPP_TAG_URI) device = attr->values[0].string.text; else if (!strcmp(attr->name, "printer-is-accepting-jobs") && attr->value_tag == IPP_TAG_BOOLEAN) accepting = attr->values[0].boolean; else if (!strcmp(attr->name, "printer-name") && attr->value_tag == IPP_TAG_NAME) printer = attr->values[0].string.text; else if (!strcmp(attr->name, "printer-state") && attr->value_tag == IPP_TAG_ENUM) pstate = (ipp_pstate_t)attr->values[0].integer; else if (!strcmp(attr->name, "queued-job-count") && attr->value_tag == IPP_TAG_INTEGER) jobcount = attr->values[0].integer; attr = attr->next; } /* * See if we have everything needed... */ if (printer == NULL) { if (attr == NULL) break; else continue; } /* * A single 'all' printer name is special, meaning all printers. */ if (dests != NULL && !strcmp(dests, "all")) dests = NULL; /* * See if this is a printer we're interested in... */ match = dests == NULL; if (dests != NULL) { for (dptr = dests; *dptr != '\0';) { /* * Skip leading whitespace and commas... */ while (isspace(*dptr & 255) || *dptr == ',') dptr ++; if (*dptr == '\0') break; /* * Compare names... */ for (ptr = printer; *ptr != '\0' && *dptr != '\0' && *ptr == *dptr; ptr ++, dptr ++) /* do nothing */; if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255))) { match = 1; break; } /* * Skip trailing junk... */ while (!isspace(*dptr & 255) && *dptr != '\0') dptr ++; while (isspace(*dptr & 255) || *dptr == ',') dptr ++; if (*dptr == '\0') break; } } /* * Display the printer entry if needed... */ if (match) { /* * Display it... */ printf("%s:\n", printer); if (!strncmp(device, "file:", 5)) _cupsLangPrintf(stdout, _("\tprinter is on device \'%s\' speed -1"), device + 5); else { /* * Just show the scheme... */ if ((delimiter = strchr(device, ':')) != NULL ) { *delimiter = '\0'; _cupsLangPrintf(stdout, _("\tprinter is on device \'%s\' speed -1"), device); } } if (accepting) _cupsLangPuts(stdout, _("\tqueuing is enabled")); else _cupsLangPuts(stdout, _("\tqueuing is disabled")); if (pstate != IPP_PRINTER_STOPPED) _cupsLangPuts(stdout, _("\tprinting is enabled")); else _cupsLangPuts(stdout, _("\tprinting is disabled")); if (jobcount == 0) _cupsLangPuts(stdout, _("\tno entries")); else _cupsLangPrintf(stdout, _("\t%d entries"), jobcount); _cupsLangPuts(stdout, _("\tdaemon present")); } if (attr == NULL) break; } ippDelete(response); } }
static int /* O - 0 on success, 1 on failure */ check_file(const char *filename) /* I - File to read from */ { int i; /* Looping var */ cups_file_t *fp; /* File */ char line[1024]; /* Line from file */ int ch; /* Current character */ size_t bytes; /* Length of line */ int status; /* Status of test */ int linenum; /* Line number */ int binary; /* File contains binary data? */ float version; /* DSC version */ int lbrt[4]; /* Bounding box */ char page_label[256]; /* Page label string */ int page_number; /* Page number */ int last_page_number; /* Last page number seen */ int level; /* Embedded document level */ int saw_bounding_box, /* %%BoundingBox seen? */ saw_pages, /* %%Pages seen? */ saw_end_comments, /* %%EndComments seen? */ saw_begin_prolog, /* %%BeginProlog seen? */ saw_end_prolog, /* %%EndProlog seen? */ saw_begin_setup, /* %%BeginSetup seen? */ saw_end_setup, /* %%EndSetup seen? */ saw_page, /* %%Page seen? */ saw_trailer, /* %%Trailer seen? */ saw_long_line; /* Saw long lines? */ /* * Open the file... */ if (!strcmp(filename, "(stdin)")) fp = cupsFileStdin(); else fp = cupsFileOpen(filename, "r"); if (!fp) { perror(filename); return (1); } /* * Scan the file... */ binary = 0; last_page_number = 0; level = 0; linenum = 0; saw_begin_prolog = 0; saw_begin_setup = 0; saw_bounding_box = 0; saw_end_comments = 0; saw_end_prolog = 0; saw_end_setup = 0; saw_long_line = 0; saw_page = 0; saw_pages = 0; saw_trailer = 0; status = 0; version = 0.0f; /* TODO: Fixme */ printf("%s: ", filename); fflush(stdout); while ((bytes = cupsFileGetLine(fp, line, sizeof(line))) > 0) { linenum ++; if (bytes > 255) { if (!saw_long_line) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Line %d is longer than 255 characters (%d).\n" " REF: Page 25, Line Length"), linenum, (int)bytes); } saw_long_line ++; } if (linenum == 1) { if (strncmp(line, "%!PS-Adobe-", 11)) { if (!status) _cupsLangPuts(stdout, _("FAIL")); _cupsLangPuts(stdout, _(" Missing %!PS-Adobe-3.0 on first line.\n" " REF: Page 17, 3.1 Conforming Documents")); cupsFileClose(fp); return (1); } else version = atof(line + 11); } else if (level > 0) { if (!strncmp(line, "%%BeginDocument:", 16)) level ++; else if (!strncmp(line, "%%EndDocument", 13)) level --; } else if (saw_trailer) { if (!strncmp(line, "%%Pages:", 8)) { if (atoi(line + 8) <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d.\n" " REF: Page 43, %%%%Pages:"), linenum); } else saw_pages = 1; } else if (!strncmp(line, "%%BoundingBox:", 14)) { if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2, lbrt + 3) != 4) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d.\n" " REF: Page 39, %%%%BoundingBox:"), linenum); } else saw_bounding_box = 1; } } else if (!saw_end_comments) { if (!strncmp(line, "%%EndComments", 13)) saw_end_comments = 1; else if (line[0] != '%') saw_end_comments = -1; else if (!strncmp(line, "%%Pages:", 8)) { if (strstr(line + 8, "(atend)")) saw_pages = -1; else if (atoi(line + 8) <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d.\n" " REF: Page 43, %%%%Pages:"), linenum); } else saw_pages = 1; } else if (!strncmp(line, "%%BoundingBox:", 14)) { if (strstr(line, "(atend)")) saw_bounding_box = -1; else if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2, lbrt + 3) != 4) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d.\n" " REF: Page 39, %%%%BoundingBox:"), linenum); } else saw_bounding_box = 1; } } else if (saw_begin_prolog && !saw_end_prolog) { if (!strncmp(line, "%%EndProlog", 11)) saw_end_prolog = 1; } else if (saw_begin_setup && !saw_end_setup) { if (!strncmp(line, "%%EndSetup", 10)) saw_end_setup = 1; } else if (saw_end_comments) { if (!strncmp(line, "%%Page:", 7)) { if (sscanf(line + 7, "%255s%d", page_label, &page_number) != 2 || page_number != (last_page_number + 1) || page_number < 1) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%Page: on line %d.\n" " REF: Page 53, %%%%Page:"), linenum); } else { last_page_number = page_number; saw_page = 1; } } else if (!strncmp(line, "%%BeginProlog", 13)) saw_begin_prolog = 1; else if (!strncmp(line, "%%BeginSetup", 12)) saw_begin_setup = 1; else if (!strncmp(line, "%%BeginDocument:", 16)) level ++; else if (!strncmp(line, "%%EndDocument", 13)) level --; else if (!strncmp(line, "%%Trailer", 9)) saw_trailer = 1; } for (i = 0; !binary && i < bytes; i ++) { ch = line[i]; if ((ch < ' ' || (ch & 0x80)) && ch != '\n' && ch != '\r' && ch != '\t') binary = 1; } } if (saw_bounding_box <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing or bad %%BoundingBox: comment.\n" " REF: Page 39, %%BoundingBox:")); } if (saw_pages <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing or bad %%Pages: comment.\n" " REF: Page 43, %%Pages:")); } if (!saw_end_comments) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing %%EndComments comment." " REF: Page 41, %%EndComments")); } if (!saw_page) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing or bad %%Page: comments.\n" " REF: Page 53, %%Page:")); } if (level < 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Too many %%EndDocument comments.")); } else if (level > 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Too many %%BeginDocument comments.")); } if (saw_long_line > 1) _cupsLangPrintf(stderr, _(" Saw %d lines that exceeded 255 characters."), saw_long_line); if (!status) _cupsLangPuts(stdout, _("PASS")); if (binary) _cupsLangPuts(stdout, _(" Warning: file contains binary data.")); if (version < 3.0f) _cupsLangPrintf(stdout, _(" Warning: obsolete DSC version %.1f in file."), version); if (saw_end_comments < 0) _cupsLangPuts(stdout, _(" Warning: no %%EndComments comment in file.")); cupsFileClose(fp); return (status); }
static int /* O - Number of jobs in queue */ show_jobs(const char *command, /* I - Command name */ http_t *http, /* I - HTTP connection to server */ const char *dest, /* I - Destination */ const char *user, /* I - User */ const int id, /* I - Job ID */ const int longstatus) /* I - 1 if long report desired */ { ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ const char *jobdest, /* Pointer into job-printer-uri */ *jobuser, /* Pointer to job-originating-user-name */ *jobname; /* Pointer to job-name */ ipp_jstate_t jobstate; /* job-state */ int jobid, /* job-id */ jobsize, /* job-k-octets */ #ifdef __osf__ jobpriority, /* job-priority */ #endif /* __osf__ */ jobcount, /* Number of jobs */ jobcopies, /* Number of copies */ rank; /* Rank of job */ char resource[1024]; /* Resource string */ char rankstr[255]; /* Rank string */ char namestr[1024]; /* Job name string */ static const char * const jobattrs[] =/* Job attributes we want to see */ { "copies", "job-id", "job-k-octets", "job-name", "job-originating-user-name", "job-printer-uri", "job-priority", "job-state" }; static const char * const ranks[10] = /* Ranking strings */ { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" }; DEBUG_printf(("show_jobs(http=%p, dest=%p, user=%p, id=%d, longstatus%d)\n", http, dest, user, id, longstatus)); if (http == NULL) return (0); /* * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires * the following attributes: * * attributes-charset * attributes-natural-language * job-uri or printer-uri * requested-attributes * requesting-user-name */ request = ippNewRequest(id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS); if (id) { snprintf(resource, sizeof(resource), "ipp://localhost/jobs/%d", id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, resource); } else if (dest) { httpAssembleURIf(HTTP_URI_CODING_ALL, resource, sizeof(resource), "ipp", NULL, "localhost", 0, "/printers/%s", dest); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, resource); } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/"); if (user) { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(jobattrs) / sizeof(jobattrs[0])), NULL, jobattrs); /* * Do the request and get back a response... */ jobcount = 0; if ((response = cupsDoRequest(http, request, "/")) != NULL) { if (response->request.status.status_code > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); ippDelete(response); return (0); } rank = 1; /* * Loop through the job list and display them... */ for (attr = response->attrs; attr != NULL; attr = attr->next) { /* * Skip leading attributes until we hit a job... */ while (attr != NULL && attr->group_tag != IPP_TAG_JOB) attr = attr->next; if (attr == NULL) break; /* * Pull the needed attributes from this job... */ jobid = 0; jobsize = 0; #ifdef __osf__ jobpriority = 50; #endif /* __osf__ */ jobstate = IPP_JOB_PENDING; jobname = "unknown"; jobuser = "******"; jobdest = NULL; jobcopies = 1; while (attr != NULL && attr->group_tag == IPP_TAG_JOB) { if (!strcmp(attr->name, "job-id") && attr->value_tag == IPP_TAG_INTEGER) jobid = attr->values[0].integer; if (!strcmp(attr->name, "job-k-octets") && attr->value_tag == IPP_TAG_INTEGER) jobsize = attr->values[0].integer; #ifdef __osf__ if (!strcmp(attr->name, "job-priority") && attr->value_tag == IPP_TAG_INTEGER) jobpriority = attr->values[0].integer; #endif /* __osf__ */ if (!strcmp(attr->name, "job-state") && attr->value_tag == IPP_TAG_ENUM) jobstate = (ipp_jstate_t)attr->values[0].integer; if (!strcmp(attr->name, "job-printer-uri") && attr->value_tag == IPP_TAG_URI) if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL) jobdest ++; if (!strcmp(attr->name, "job-originating-user-name") && attr->value_tag == IPP_TAG_NAME) jobuser = attr->values[0].string.text; if (!strcmp(attr->name, "job-name") && attr->value_tag == IPP_TAG_NAME) jobname = attr->values[0].string.text; if (!strcmp(attr->name, "copies") && attr->value_tag == IPP_TAG_INTEGER) jobcopies = attr->values[0].integer; attr = attr->next; } /* * See if we have everything needed... */ if (jobdest == NULL || jobid == 0) { if (attr == NULL) break; else continue; } if (!longstatus && jobcount == 0) #ifdef __osf__ _cupsLangPuts(stdout, /* TRANSLATORS: Pri is job priority. */ _("Rank Owner Pri Job Files" " Total Size")); #else _cupsLangPuts(stdout, _("Rank Owner Job File(s)" " Total Size")); #endif /* __osf__ */ jobcount ++; /* * Display the job... */ if (jobstate == IPP_JOB_PROCESSING) strlcpy(rankstr, "active", sizeof(rankstr)); else { /* * Make the rank show the "correct" suffix for each number * (11-13 are the only special cases, for English anyways...) */ if ((rank % 100) >= 11 && (rank % 100) <= 13) snprintf(rankstr, sizeof(rankstr), "%dth", rank); else snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]); rank ++; } if (longstatus) { _cupsLangPuts(stdout, "\n"); if (jobcopies > 1) snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies, jobname); else strlcpy(namestr, jobname, sizeof(namestr)); _cupsLangPrintf(stdout, _("%s: %-33.33s [job %d localhost]"), jobuser, rankstr, jobid); _cupsLangPrintf(stdout, _(" %-39.39s %.0f bytes"), namestr, 1024.0 * jobsize); } else #ifdef __osf__ _cupsLangPrintf(stdout, _("%-6s %-10.10s %-4d %-10d %-27.27s %.0f bytes"), rankstr, jobuser, jobpriority, jobid, jobname, 1024.0 * jobsize); #else _cupsLangPrintf(stdout, _("%-7s %-7.7s %-7d %-31.31s %.0f bytes"), rankstr, jobuser, jobid, jobname, 1024.0 * jobsize); #endif /* __osf */ if (attr == NULL) break; } ippDelete(response); } else { _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); return (0); } if (jobcount == 0) _cupsLangPuts(stdout, _("no entries")); return (jobcount); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { http_t *http; /* Connection to server */ char line[1024], /* Input line from user */ *params; /* Pointer to parameters */ _cupsSetLocale(argv); /* * Connect to the scheduler... */ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (argc > 1) { /* * Process a single command on the command-line... */ do_command(http, argv[1], argv[2]); } else { /* * Do the command prompt thing... */ _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no-newline version */ while (fgets(line, sizeof(line), stdin) != NULL) { /* * Strip trailing whitespace... */ for (params = line + strlen(line) - 1; params >= line;) if (!isspace(*params & 255)) break; else *params-- = '\0'; /* * Strip leading whitespace... */ for (params = line; isspace(*params & 255); params ++); if (params > line) _cups_strcpy(line, params); if (!line[0]) { /* * Nothing left, just show a prompt... */ _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */ continue; } /* * Find any options in the string... */ for (params = line; *params != '\0'; params ++) if (isspace(*params & 255)) break; /* * Remove whitespace between the command and parameters... */ while (isspace(*params & 255)) *params++ = '\0'; /* * The "quit" and "exit" commands exit; otherwise, process as needed... */ if (!compare_strings(line, "quit", 1) || !compare_strings(line, "exit", 2)) break; if (*params == '\0') do_command(http, line, NULL); else do_command(http, line, params); /* * Put another prompt out to the user... */ _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */ } } /* * Close the connection to the server and return... */ httpClose(http); return (0); }
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 pointer */ const char *username; /* Pointer to username */ const char *groupname; /* Pointer to group name */ int op; /* Operation (add, change, delete) */ const char *passwd; /* Password string */ FILE *infile, /* Input file */ *outfile; /* Output file */ char line[256], /* Line from file */ userline[17], /* User from line */ groupline[17], /* Group from line */ md5line[33], /* MD5-sum from line */ md5new[33]; /* New MD5 sum */ char passwdmd5[1024], /* passwd.md5 file */ passwdold[1024], /* passwd.old file */ passwdnew[1024]; /* passwd.tmp file */ char *newpass, /* new password */ *oldpass; /* old password */ int flag; /* Password check flags... */ int fd; /* Password file descriptor */ int error; /* Write error */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ cups_lang_t *lang; /* Language info */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Signal action */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET*/ _cupsSetLocale(argv); lang = cupsLangDefault(); /* * Check to see if stdin, stdout, and stderr are still open... */ if (fcntl(0, F_GETFD, &i) || fcntl(1, F_GETFD, &i) || fcntl(2, F_GETFD, &i)) { /* * No, return exit status 2 and don't try to send any output since * someone is trying to bypass the security on the server. */ return (2); } /* * Find the server directory... */ snprintf(passwdmd5, sizeof(passwdmd5), "%s/passwd.md5", cg->cups_serverroot); snprintf(passwdold, sizeof(passwdold), "%s/passwd.old", cg->cups_serverroot); snprintf(passwdnew, sizeof(passwdnew), "%s/passwd.new", cg->cups_serverroot); /* * Find the default system group... */ if (getgrnam(CUPS_DEFAULT_GROUP)) groupname = CUPS_DEFAULT_GROUP; else groupname = "unknown"; endgrent(); username = NULL; op = CHANGE; /* * Parse command-line options... */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt; opt ++) switch (*opt) { case 'a' : /* Add */ op = ADD; break; case 'x' : /* Delete */ op = DELETE; break; case 'g' : /* Group */ i ++; if (i >= argc) usage(stderr); groupname = argv[i]; break; case 'h' : /* Help */ usage(stdout); break; default : /* Bad option */ usage(stderr); break; } else if (!username) username = argv[i]; else usage(stderr); /* * See if we are trying to add or delete a password when we aren't logged in * as root... */ if (getuid() && getuid() != geteuid() && (op != CHANGE || username)) { _cupsLangPuts(stderr, _("lppasswd: Only root can add or delete passwords!\n")); return (1); } /* * Fill in missing info... */ if (!username) username = cupsUser(); oldpass = newpass = NULL; /* * Obtain old and new password _before_ locking the database * to keep users from locking the file indefinitely. */ if (op == CHANGE && getuid()) { if ((passwd = cupsGetPassword(_("Enter old password:"******"lppasswd: Unable to copy password string: %s\n"), strerror(errno)); return (1); } } /* * Now get the new password, if necessary... */ if (op != DELETE) { if ((passwd = cupsGetPassword( _cupsLangString(lang, _("Enter password:"******"lppasswd: Unable to copy password string: %s\n"), strerror(errno)); return (1); } if ((passwd = cupsGetPassword( _cupsLangString(lang, _("Enter password again:")))) == NULL) return (1); if (strcmp(passwd, newpass) != 0) { _cupsLangPuts(stderr, _("lppasswd: Sorry, passwords don't match!\n")); return (1); } /* * Check that the password contains at least one letter and number. */ flag = 0; for (passwd = newpass; *passwd; passwd ++) if (isdigit(*passwd & 255)) flag |= 1; else if (isalpha(*passwd & 255)) flag |= 2; /* * Only allow passwords that are at least 6 chars, have a letter and * a number, and don't contain the username. */ if (strlen(newpass) < 6 || strstr(newpass, username) != NULL || flag != 3) { _cupsLangPuts(stderr, _("lppasswd: Sorry, password rejected.\n" "Your password must be at least 6 characters long, " "cannot contain\n" "your username, and must contain at least one letter " "and number.\n")); return (1); } } /* * Ignore SIGHUP, SIGINT, SIGTERM, and SIGXFSZ (if defined) for the * remainder of the time so that we won't end up with bogus password * files... */ #ifndef WIN32 # if defined(HAVE_SIGSET) sigset(SIGHUP, SIG_IGN); sigset(SIGINT, SIG_IGN); sigset(SIGTERM, SIG_IGN); # ifdef SIGXFSZ sigset(SIGXFSZ, SIG_IGN); # endif /* SIGXFSZ */ # elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGHUP, &action, NULL); sigaction(SIGINT, &action, NULL); sigaction(SIGTERM, &action, NULL); # ifdef SIGXFSZ sigaction(SIGXFSZ, &action, NULL); # endif /* SIGXFSZ */ # else signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); # ifdef SIGXFSZ signal(SIGXFSZ, SIG_IGN); # endif /* SIGXFSZ */ # endif #endif /* !WIN32 */ /* * Open the output file. */ if ((fd = open(passwdnew, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0) { if (errno == EEXIST) _cupsLangPuts(stderr, _("lppasswd: Password file busy!\n")); else _cupsLangPrintf(stderr, _("lppasswd: Unable to open password file: %s\n"), strerror(errno)); return (1); } if ((outfile = fdopen(fd, "w")) == NULL) { _cupsLangPrintf(stderr, _("lppasswd: Unable to open password file: %s\n"), strerror(errno)); unlink(passwdnew); return (1); } setbuf(outfile, NULL); /* * Open the existing password file and create a new one... */ infile = fopen(passwdmd5, "r"); if (infile == NULL && errno != ENOENT && op != ADD) { _cupsLangPrintf(stderr, _("lppasswd: Unable to open password file: %s\n"), strerror(errno)); fclose(outfile); unlink(passwdnew); return (1); } /* * Read lines from the password file; the format is: * * username:group:MD5-sum */ error = 0; userline[0] = '\0'; groupline[0] = '\0'; md5line[0] = '\0'; if (infile) { while (fgets(line, sizeof(line), infile) != NULL) { if (sscanf(line, "%16[^:]:%16[^:]:%32s", userline, groupline, md5line) != 3) continue; if (strcmp(username, userline) == 0 && strcmp(groupname, groupline) == 0) break; if (fputs(line, outfile) == EOF) { _cupsLangPrintf(stderr, _("lppasswd: Unable to write to password file: %s\n"), strerror(errno)); error = 1; break; } } if (!error) { while (fgets(line, sizeof(line), infile) != NULL) if (fputs(line, outfile) == EOF) { _cupsLangPrintf(stderr, _("lppasswd: Unable to write to password file: %s\n"), strerror(errno)); error = 1; break; } } } if (op == CHANGE && (strcmp(username, userline) || strcmp(groupname, groupline))) { _cupsLangPrintf(stderr, _("lppasswd: user \"%s\" and group \"%s\" do not exist.\n"), username, groupname); error = 1; } else if (op != DELETE) { if (oldpass && strcmp(httpMD5(username, "CUPS", oldpass, md5new), md5line) != 0) { _cupsLangPuts(stderr, _("lppasswd: Sorry, password doesn't match!\n")); error = 1; } else { snprintf(line, sizeof(line), "%s:%s:%s\n", username, groupname, httpMD5(username, "CUPS", newpass, md5new)); if (fputs(line, outfile) == EOF) { _cupsLangPrintf(stderr, _("lppasswd: Unable to write to password file: %s\n"), strerror(errno)); error = 1; } } } /* * Close the files... */ if (infile) fclose(infile); if (fclose(outfile) == EOF) error = 1; /* * Error out gracefully as needed... */ if (error) { _cupsLangPuts(stderr, _("lppasswd: Password file not updated!\n")); unlink(passwdnew); return (1); } /* * Save old passwd file */ unlink(passwdold); if (link(passwdmd5, passwdold) && errno != ENOENT) { _cupsLangPrintf(stderr, _("lppasswd: failed to backup old password file: %s\n"), strerror(errno)); unlink(passwdnew); return (1); } /* * Install new password file */ if (rename(passwdnew, passwdmd5) < 0) { _cupsLangPrintf(stderr, _("lppasswd: failed to rename password file: %s\n"), strerror(errno)); unlink(passwdnew); return (1); } return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i, /* Looping var */ num_settings; /* Number of settings */ cups_option_t *settings; /* Settings */ const char *opt; /* Current option character */ http_t *http; /* Connection to server */ /* * Process the command-line... */ _cupsSetLocale(argv); num_settings = 0; settings = NULL; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--help")) usage(NULL); else if (argv[i][0] == '-') { if (argv[i][1] == '-') { if (!strcmp(argv[i], "--debug-logging")) num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, "1", num_settings, &settings); else if (!strcmp(argv[i], "--no-debug-logging")) num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, "0", num_settings, &settings); else if (!strcmp(argv[i], "--remote-admin")) num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, "1", num_settings, &settings); else if (!strcmp(argv[i], "--no-remote-admin")) num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, "0", num_settings, &settings); else if (!strcmp(argv[i], "--remote-any")) num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, "1", num_settings, &settings); else if (!strcmp(argv[i], "--no-remote-any")) num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, "0", num_settings, &settings); else if (!strcmp(argv[i], "--share-printers")) num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, "1", num_settings, &settings); else if (!strcmp(argv[i], "--no-share-printers")) num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, "0", num_settings, &settings); else if (!strcmp(argv[i], "--user-cancel-any")) num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, "1", num_settings, &settings); else if (!strcmp(argv[i], "--no-user-cancel-any")) num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, "0", num_settings, &settings); else usage(argv[i]); } else { for (opt = argv[i] + 1; *opt; opt ++) switch (*opt) { case 'E' : cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); break; case 'U' : i ++; if (i >= argc) usage(NULL); cupsSetUser(argv[i]); break; case 'h' : i ++; if (i >= argc) usage(NULL); cupsSetServer(argv[i]); break; default : usage(opt); break; } } } else if (strchr(argv[i], '=')) num_settings = cupsParseOptions(argv[i], num_settings, &settings); else usage(argv[i]); } if (cupsGetOption("Listen", num_settings, settings) || cupsGetOption("Port", num_settings, settings)) { _cupsLangPuts(stderr, _("cupsctl: Cannot set Listen or Port directly.")); return (1); } /* * Connect to the server using the defaults... */ if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) { _cupsLangPrintf(stderr, _("cupsctl: Unable to connect to server: %s"), strerror(errno)); return (1); } /* * Set the current configuration if we have anything on the command-line... */ if (num_settings > 0) { if (!cupsAdminSetServerSettings(http, num_settings, settings)) { _cupsLangPrintf(stderr, "cupsctl: %s", cupsLastErrorString()); return (1); } } else if (!cupsAdminGetServerSettings(http, &num_settings, &settings)) { _cupsLangPrintf(stderr, "cupsctl: %s", cupsLastErrorString()); return (1); } else { for (i = 0; i < num_settings; i ++) _cupsLangPrintf(stdout, "%s=%s", settings[i].name, settings[i].value); } cupsFreeOptions(num_settings, settings); return (0); }
static void usage(const char *opt) /* I - Incorrect option, if any */ { if (opt) _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), "cupsfilter", *opt); _cupsLangPuts(stdout, _("Usage: cupsfilter [ options ] [ -- ] filename")); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _(" --list-filters List filters that will be used.")); _cupsLangPuts(stdout, _(" -D Remove the input file when finished.")); _cupsLangPuts(stdout, _(" -P filename.ppd Set PPD file.")); _cupsLangPuts(stdout, _(" -U username Specify username.")); _cupsLangPuts(stdout, _(" -c cups-files.conf Set cups-files.conf file to use.")); _cupsLangPuts(stdout, _(" -d printer Use the named printer.")); _cupsLangPuts(stdout, _(" -e Use every filter from the PPD file.")); _cupsLangPuts(stdout, _(" -i mime/type Set input MIME type (otherwise auto-typed).")); _cupsLangPuts(stdout, _(" -j job-id[,N] Filter file N from the specified job (default is file 1).")); _cupsLangPuts(stdout, _(" -m mime/type Set output MIME type (otherwise application/pdf).")); _cupsLangPuts(stdout, _(" -n copies Set number of copies.")); _cupsLangPuts(stdout, _(" -o name=value Set option(s).")); _cupsLangPuts(stdout, _(" -p filename.ppd Set PPD file.")); _cupsLangPuts(stdout, _(" -t title Set title.")); _cupsLangPuts(stdout, _(" -u Remove the PPD file when finished.")); exit(1); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i, /* Looping vars */ list_filters = 0; /* Just list the filters? */ const char *command, /* Command name */ *opt, /* Current option */ *printer; /* Printer name */ mime_type_t *printer_type, /* Printer MIME type */ *prefilter_type; /* Printer prefilter MIME type */ char *srctype, /* Source type */ *dsttype, /* Destination type */ super[MIME_MAX_SUPER], /* Super-type name */ type[MIME_MAX_TYPE]; /* Type name */ int compression; /* Compression of file */ int cost; /* Cost of filters */ mime_t *mime; /* MIME database */ char mimedir[1024]; /* MIME directory */ char *infile, /* File to filter */ *outfile; /* File to create */ char cupsfilesconf[1024]; /* cups-files.conf file */ const char *server_root; /* CUPS_SERVERROOT environment variable */ mime_type_t *src, /* Source type */ *dst; /* Destination type */ cups_array_t *filters; /* Filters for the file */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ const char *ppdfile; /* PPD file */ const char *title, /* Title string */ *user; /* Username */ int all_filters, /* Use all filters */ removeppd, /* Remove PPD file */ removeinfile; /* Remove input file */ int status; /* Execution status */ /* * Setup defaults... */ if ((command = strrchr(argv[0], '/')) != NULL) command ++; else command = argv[0]; printer = !strcmp(command, "convert") ? "tofile" : "cupsfilter"; mime = NULL; srctype = NULL; compression = 0; dsttype = "application/pdf"; infile = NULL; outfile = NULL; num_options = 0; options = NULL; ppdfile = NULL; title = NULL; user = cupsUser(); all_filters = 0; removeppd = 0; removeinfile = 0; if ((server_root = getenv("CUPS_SERVERROOT")) == NULL) server_root = CUPS_SERVERROOT; snprintf(cupsfilesconf, sizeof(cupsfilesconf), "%s/cups-files.conf", server_root); /* * Process command-line arguments... */ _cupsSetLocale(argv); for (i = 1; i < argc; i ++) { if (argv[i][0] == '-') { if (!strcmp(argv[i], "--list-filters")) { list_filters = 1; } else if (!strcmp(argv[i], "--")) { i ++; if (i < argc && !infile) infile = argv[i]; else usage(NULL); } else { for (opt = argv[i] + 1; *opt; opt ++) { switch (*opt) { case 'a' : /* Specify option... */ i ++; if (i < argc) num_options = cupsParseOptions(argv[i], num_options, &options); else usage(opt); break; case 'c' : /* Specify cups-files.conf file location... */ i ++; if (i < argc) { if (!strcmp(command, "convert")) num_options = cupsAddOption("copies", argv[i], num_options, &options); else strlcpy(cupsfilesconf, argv[i], sizeof(cupsfilesconf)); } else usage(opt); break; case 'd' : /* Specify the real printer name */ i ++; if (i < argc) printer = argv[i]; else usage(opt); break; case 'D' : /* Delete input file after conversion */ removeinfile = 1; break; case 'e' : /* Use every filter from the PPD file */ all_filters = 1; break; case 'f' : /* Specify input file... */ i ++; if (i < argc && !infile) infile = argv[i]; else usage(opt); break; case 'i' : /* Specify source MIME type... */ i ++; if (i < argc) { if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) usage(opt); srctype = argv[i]; } else usage(opt); break; case 'j' : /* Get job file or specify destination MIME type... */ if (strcmp(command, "convert")) { i ++; if (i < argc) { get_job_file(argv[i]); infile = TempFile; } else usage(opt); break; } case 'm' : /* Specify destination MIME type... */ i ++; if (i < argc) { if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) usage(opt); dsttype = argv[i]; } else usage(opt); break; case 'n' : /* Specify number of copies... */ i ++; if (i < argc) num_options = cupsAddOption("copies", argv[i], num_options, &options); else usage(opt); break; case 'o' : /* Specify option(s) or output filename */ i ++; if (i < argc) { if (!strcmp(command, "convert")) { if (outfile) usage(NULL); else outfile = argv[i]; } else num_options = cupsParseOptions(argv[i], num_options, &options); } else usage(opt); break; case 'p' : /* Specify PPD file... */ case 'P' : /* Specify PPD file... */ i ++; if (i < argc) ppdfile = argv[i]; else usage(opt); break; case 't' : /* Specify title... */ case 'J' : /* Specify title... */ i ++; if (i < argc) title = argv[i]; else usage(opt); break; case 'u' : /* Delete PPD file after conversion */ removeppd = 1; break; case 'U' : /* Specify username... */ i ++; if (i < argc) user = argv[i]; else usage(opt); break; default : /* Something we don't understand... */ usage(opt); break; } } } } else if (!infile) { if (strcmp(command, "convert")) infile = argv[i]; else usage(NULL); } else { _cupsLangPuts(stderr, _("cupsfilter: Only one filename can be specified.")); usage(NULL); } } if (!infile && !srctype) usage(NULL); if (!title) { if (!infile) title = "(stdin)"; else if ((title = strrchr(infile, '/')) != NULL) title ++; else title = infile; } /* * Load the cups-files.conf file and create the MIME database... */ if (read_cups_files_conf(cupsfilesconf)) return (1); snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir); mime = mimeLoadTypes(NULL, mimedir); mime = mimeLoadTypes(mime, ServerRoot); mime = mimeLoadFilters(mime, mimedir, Path); mime = mimeLoadFilters(mime, ServerRoot, Path); if (!mime) { _cupsLangPrintf(stderr, _("%s: Unable to read MIME database from \"%s\" or " "\"%s\"."), command, mimedir, ServerRoot); return (1); } prefilter_type = NULL; if (all_filters) printer_type = add_printer_filters(command, mime, printer, ppdfile, &prefilter_type); else printer_type = mimeType(mime, "application", "vnd.cups-postscript"); /* * Get the source and destination types... */ if (srctype) { /* sscanf return value already checked above */ sscanf(srctype, "%15[^/]/%255s", super, type); if ((src = mimeType(mime, super, type)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unknown source MIME type %s/%s."), command, super, type); return (1); } } else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to determine MIME type of \"%s\"."), command, infile); return (1); } /* sscanf return value already checked above */ sscanf(dsttype, "%15[^/]/%255s", super, type); if (!_cups_strcasecmp(super, "printer")) dst = printer_type; else if ((dst = mimeType(mime, super, type)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unknown destination MIME type %s/%s."), command, super, type); return (1); } /* * Figure out how to filter the file... */ if (src == dst) { /* * Special case - no filtering needed... */ filters = cupsArrayNew(NULL, NULL); cupsArrayAdd(filters, &GZIPFilter); GZIPFilter.src = src; GZIPFilter.dst = dst; } else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL) { _cupsLangPrintf(stderr, _("%s: No filter to convert from %s/%s to %s/%s."), command, src->super, src->type, dst->super, dst->type); return (1); } else if (compression) cupsArrayInsert(filters, &GZIPFilter); if (prefilter_type) { /* * Add pre-filters... */ mime_filter_t *filter, /* Current filter */ *prefilter; /* Current pre-filter */ cups_array_t *prefilters = cupsArrayNew(NULL, NULL); /* New filters array */ for (filter = (mime_filter_t *)cupsArrayFirst(filters); filter; filter = (mime_filter_t *)cupsArrayNext(filters)) { if ((prefilter = mimeFilterLookup(mime, filter->src, prefilter_type)) != NULL) cupsArrayAdd(prefilters, prefilter); cupsArrayAdd(prefilters, filter); } cupsArrayDelete(filters); filters = prefilters; } if (list_filters) { /* * List filters... */ mime_filter_t *filter; /* Current filter */ for (filter = (mime_filter_t *)cupsArrayFirst(filters); filter; filter = (mime_filter_t *)cupsArrayNext(filters)) if (strcmp(filter->filter, "-")) _cupsLangPuts(stdout, filter->filter); status = 0; } else { /* * Run filters... */ status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user, title, num_options, options); } /* * Remove files as needed, then exit... */ if (TempFile[0]) unlink(TempFile); if (removeppd && ppdfile) unlink(ppdfile); if (removeinfile && infile) unlink(infile); return (status); }
static int /* O - File descriptor or -1 on error */ open_device(const char *uri, /* I - Device URI */ int *use_bc) /* O - Set to 0 for unidirectional */ { int fd; /* File descriptor */ /* * The generic implementation just treats the URI as a device filename... * Specific operating systems may also support using the device serial * number and/or make/model. */ if (!strncmp(uri, "usb:/dev/", 9)) #ifdef __linux { /* * Do not allow direct devices anymore... */ errno = ENODEV; return (-1); } else if (!strncmp(uri, "usb://", 6)) { /* * For Linux, try looking up the device serial number or model... */ int i; /* Looping var */ int busy; /* Are any ports busy? */ char device[255], /* Device filename */ device_id[1024], /* Device ID string */ make_model[1024], /* Make and model */ device_uri[1024]; /* Device URI string */ /* * Find the correct USB device... */ for (;;) { for (busy = 0, i = 0; i < 16; i ++) { /* * Linux has a long history of changing the standard filenames used * for USB printer devices. We get the honor of trying them all... */ sprintf(device, "/dev/usblp%d", i); if ((fd = open(device, O_RDWR | O_EXCL)) < 0 && errno == ENOENT) { sprintf(device, "/dev/usb/lp%d", i); if ((fd = open(device, O_RDWR | O_EXCL)) < 0 && errno == ENOENT) { sprintf(device, "/dev/usb/usblp%d", i); if ((fd = open(device, O_RDWR | O_EXCL)) < 0 && errno == ENOENT) continue; } } if (fd >= 0) { backendGetDeviceID(fd, device_id, sizeof(device_id), make_model, sizeof(make_model), "usb", device_uri, sizeof(device_uri)); } else { /* * If the open failed because it was busy, flag it so we retry * as needed... */ if (errno == EBUSY) busy = 1; device_uri[0] = '\0'; } if (!strcmp(uri, device_uri)) { /* * Yes, return this file descriptor... */ fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device); return (fd); } /* * This wasn't the one... */ if (fd >= 0) close(fd); } /* * If we get here and at least one of the printer ports showed up * as "busy", then sleep for a bit and retry... */ if (busy) _cupsLangPuts(stderr, _("INFO: Printer busy; will retry in 5 seconds...\n")); sleep(5); } } #elif defined(__sun) && defined(ECPPIOC_GETDEVID) { /* * Do not allow direct devices anymore... */ errno = ENODEV; return (-1); } else if (!strncmp(uri, "usb://", 6))
static int /* O - 0 on success, 1 on fail */ delete_printer_from_class( http_t *http, /* I - Server connection */ char *printer, /* I - Printer to remove */ char *pclass) /* I - Class to remove from */ { int i, j, k; /* Looping vars */ ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr, /* Current attribute */ *members; /* Members in class */ char uri[HTTP_MAX_URI]; /* URI for printer/class */ DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http, printer, pclass)); /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name */ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/classes/%s", pclass); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/classes/")) == NULL || response->request.status.status_code == IPP_NOT_FOUND) { _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); ippDelete(response); return (1); } /* * See if the printer is already in the class... */ if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL) { _cupsLangPuts(stderr, _("lpadmin: No member names were seen.")); ippDelete(response); return (1); } for (i = 0; i < members->num_values; i ++) if (!_cups_strcasecmp(printer, members->values[i].string.text)) break; if (i >= members->num_values) { _cupsLangPrintf(stderr, _("lpadmin: Printer %s is not a member of class %s."), printer, pclass); ippDelete(response); return (1); } if (members->num_values == 1) { /* * Build a CUPS_DELETE_CLASS request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name */ request = ippNewRequest(CUPS_DELETE_CLASS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); } else { /* * Build a CUPS_ADD_MODIFY_CLASS request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name * member-uris */ request = ippNewRequest(CUPS_ADD_MODIFY_CLASS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Delete the printer from the class... */ members = ippFindAttribute(response, "member-uris", IPP_TAG_URI); attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", members->num_values - 1, NULL, NULL); for (j = 0, k = 0; j < members->num_values; j ++) if (j != i) attr->values[k ++].string.text = _cupsStrAlloc(members->values[j].string.text); } /* * Then send the request... */ ippDelete(response); ippDelete(cupsDoRequest(http, request, "/admin/")); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); return (1); } else return (0); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ http_t *http; /* Connection to server */ char *printer, /* Destination printer */ *pclass, /* Printer class name */ *val; /* Pointer to allow/deny value */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ char *file; /* New PPD file/interface script */ _cupsSetLocale(argv); http = NULL; printer = NULL; num_options = 0; options = NULL; file = NULL; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') switch (argv[i][1]) { case 'c' : /* Add printer to class */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to add a printer to the class:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) pclass = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected class name after \"-c\" " "option.")); return (1); } pclass = argv[i]; } if (!validate_name(pclass)) { _cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable " "characters.")); return (1); } if (add_printer_to_class(http, printer, pclass)) return (1); break; case 'd' : /* Set as default destination */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer name after \"-d\" " "option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } if (default_printer(http, printer)) return (1); i = argc; break; case 'h' : /* Connect to host */ if (http) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected hostname after \"-h\" " "option.")); return (1); } cupsSetServer(argv[i]); } break; case 'i' : /* Use the specified interface script */ if (argv[i][2]) file = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected interface after \"-i\" " "option.")); return (1); } file = argv[i]; } break; case 'E' : /* Enable the printer */ if (printer == NULL) { #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ break; } if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (enable_printer(http, printer)) return (1); break; case 'm' : /* Use the specified standard script/PPD file */ if (argv[i][2]) num_options = cupsAddOption("ppd-name", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected model after \"-m\" " "option.")); return (1); } num_options = cupsAddOption("ppd-name", argv[i], num_options, &options); } break; case 'o' : /* Set option */ if (argv[i][2]) num_options = cupsParseOptions(argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected name=value after \"-o\" " "option.")); return (1); } num_options = cupsParseOptions(argv[i], num_options, &options); } break; case 'p' : /* Add/modify a printer */ if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer after \"-p\" " "option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } break; case 'r' : /* Remove printer from class */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to remove a printer from the " "class:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) pclass = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected class after \"-r\" " "option.")); return (1); } pclass = argv[i]; } if (!validate_name(pclass)) { _cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable " "characters.")); return (1); } if (delete_printer_from_class(http, printer, pclass)) return (1); break; case 'R' : /* Remove option */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to delete option:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) val = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected name after \"-R\" " "option.")); return (1); } val = argv[i]; } if (delete_printer_option(http, printer, val)) return (1); break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\"-U\" option."), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'u' : /* Allow/deny users */ if (argv[i][2]) val = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected allow/deny:userlist after " "\"-u\" option.")); return (1); } val = argv[i]; } if (!_cups_strncasecmp(val, "allow:", 6)) num_options = cupsAddOption("requesting-user-name-allowed", val + 6, num_options, &options); else if (!_cups_strncasecmp(val, "deny:", 5)) num_options = cupsAddOption("requesting-user-name-denied", val + 5, num_options, &options); else { _cupsLangPrintf(stderr, _("lpadmin: Unknown allow/deny option \"%s\"."), val); return (1); } break; case 'v' : /* Set the device-uri attribute */ if (argv[i][2]) num_options = cupsAddOption("device-uri", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected device URI after \"-v\" " "option.")); return (1); } num_options = cupsAddOption("device-uri", argv[i], num_options, &options); } break; case 'x' : /* Delete a printer */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer or class after " "\"-x\" option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } if (delete_printer(http, printer)) return (1); i = argc; break; case 'D' : /* Set the printer-info attribute */ if (argv[i][2]) num_options = cupsAddOption("printer-info", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected description after " "\"-D\" option.")); return (1); } num_options = cupsAddOption("printer-info", argv[i], num_options, &options); } break; case 'I' : /* Set the supported file types (ignored) */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected file type(s) after \"-I\" " "option.")); return (1); } _cupsLangPuts(stderr, _("lpadmin: Warning - content type list ignored.")); break; case 'L' : /* Set the printer-location attribute */ if (argv[i][2]) num_options = cupsAddOption("printer-location", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected location after \"-L\" " "option.")); return (1); } num_options = cupsAddOption("printer-location", argv[i], num_options, &options); } break; case 'P' : /* Use the specified PPD file */ if (argv[i][2]) file = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected PPD after \"-P\" option.")); return (1); } file = argv[i]; } break; default : _cupsLangPrintf(stderr, _("lpadmin: Unknown option \"%c\"."), argv[i][1]); return (1); } else { _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."), argv[i]); return (1); } /* * Set options as needed... */ if (num_options || file) { if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to set the printer options:\n" " You must specify a printer name first.")); return (1); } if (set_printer_options(http, printer, num_options, options, file)) return (1); } if (printer == NULL) { _cupsLangPuts(stdout, _("Usage:\n" "\n" " lpadmin [-h server] -d destination\n" " lpadmin [-h server] -x destination\n" " lpadmin [-h server] -p printer [-c add-class] " "[-i interface] [-m model]\n" " [-r remove-class] [-v device] " "[-D description]\n" " [-P ppd-file] [-o name=value]\n" " [-u allow:user,user] " "[-u deny:user,user]")); } if (http) httpClose(http); return (0); }
int /* O - Exit status */ print_device(const char *uri, /* I - Device URI */ const char *hostname, /* I - Hostname/manufacturer */ const char *resource, /* I - Resource/modelname */ char *options, /* I - Device options/serial number */ int print_fd, /* I - File descriptor to print */ int copies, /* I - Copies to print */ int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { int use_bc; /* Use backchannel path? */ int device_fd; /* USB device */ size_t tbytes; /* Total number of bytes written */ struct termios opts; /* Parallel port options */ (void)argc; (void)argv; /* * Open the USB port device... */ fputs("STATE: +connecting-to-device\n", stderr); do { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) /* * *BSD's ulpt driver currently does not support the * back-channel, incorrectly returns data ready on a select(), * and locks up on read()... */ use_bc = 0; #else /* * Disable backchannel data when printing to Brother, Canon, or * Minolta USB printers - apparently these printers will return * the IEEE-1284 device ID over and over and over when they get * a read request... */ use_bc = strcasecmp(hostname, "Brother") && strcasecmp(hostname, "Canon") && strncasecmp(hostname, "Konica", 6) && strncasecmp(hostname, "Minolta", 7); #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */ if ((device_fd = open_device(uri, &use_bc)) == -1) { if (getenv("CLASS") != NULL) { /* * If the CLASS environment variable is set, the job was submitted * to a class and not to a specific queue. In this case, we want * to abort immediately so that the job can be requeued on the next * available printer in the class. */ _cupsLangPuts(stderr, _("INFO: Unable to contact printer, queuing on next " "printer in class...\n")); /* * Sleep 5 seconds to keep the job from requeuing too rapidly... */ sleep(5); return (CUPS_BACKEND_FAILED); } if (errno == EBUSY) { _cupsLangPuts(stderr, _("INFO: Printer busy; will retry in 10 seconds...\n")); sleep(10); } else if (errno == ENXIO || errno == EIO || errno == ENOENT || errno == ENODEV) { _cupsLangPuts(stderr, _("INFO: Printer not connected; will retry in 30 " "seconds...\n")); sleep(30); } else { _cupsLangPrintf(stderr, _("ERROR: Unable to open device file \"%s\": %s\n"), resource, strerror(errno)); return (CUPS_BACKEND_FAILED); } } } while (device_fd < 0); fputs("STATE: -connecting-to-device\n", stderr); /* * Set any options provided... */ tcgetattr(device_fd, &opts); opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ /**** No options supported yet ****/ tcsetattr(device_fd, TCSANOW, &opts); /* * Finally, send the print file... */ tbytes = 0; while (copies > 0 && tbytes >= 0) { copies --; if (print_fd != 0) { fputs("PAGE: 1 1\n", stderr); lseek(print_fd, 0, SEEK_SET); } tbytes = backendRunLoop(print_fd, device_fd, use_bc, side_cb); if (print_fd != 0 && tbytes >= 0) _cupsLangPrintf(stderr, #ifdef HAVE_LONG_LONG _("INFO: Sent print file, %lld bytes...\n"), #else _("INFO: Sent print file, %ld bytes...\n"), #endif /* HAVE_LONG_LONG */ CUPS_LLCAST tbytes); } /* * Close the USB port and return... */ close(device_fd); return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK); }
ssize_t /* O - Total bytes on success, -1 on error */ backendRunLoop( int print_fd, /* I - Print file descriptor */ int device_fd, /* I - Device file descriptor */ int snmp_fd, /* I - SNMP socket or -1 if none */ http_addr_t *addr, /* I - Address of device */ int use_bc, /* I - Use back-channel? */ int update_state, /* I - Update printer-state-reasons? */ int (*side_cb)(int, int, int, http_addr_t *, int)) /* I - Side-channel callback */ { int nfds; /* Maximum file descriptor value + 1 */ fd_set input, /* Input set for reading */ output; /* Output set for writing */ ssize_t print_bytes, /* Print bytes read */ bc_bytes, /* Backchannel bytes read */ total_bytes, /* Total bytes written */ bytes; /* Bytes written */ int paperout; /* "Paper out" status */ int offline; /* "Off-line" status */ char print_buffer[8192], /* Print data buffer */ *print_ptr, /* Pointer into print data buffer */ bc_buffer[1024]; /* Back-channel data buffer */ struct timeval timeout; /* Timeout for select() */ time_t curtime, /* Current time */ snmp_update = 0; #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ fprintf(stderr, "DEBUG: backendRunLoop(print_fd=%d, device_fd=%d, snmp_fd=%d, " "addr=%p, use_bc=%d, side_cb=%p)\n", print_fd, device_fd, snmp_fd, addr, use_bc, side_cb); /* * If we are printing data from a print driver on stdin, ignore SIGTERM * so that the driver can finish out any page data, e.g. to eject the * current page. We only do this for stdin printing as otherwise there * is no way to cancel a raw print job... */ if (!print_fd) { #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGTERM, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGTERM, &action, NULL); #else signal(SIGTERM, SIG_IGN); #endif /* HAVE_SIGSET */ } else if (print_fd < 0) { /* * Copy print data from stdin, but don't mess with the signal handlers... */ print_fd = 0; } /* * Figure out the maximum file descriptor value to use with select()... */ nfds = (print_fd > device_fd ? print_fd : device_fd) + 1; /* * Now loop until we are out of data from print_fd... */ for (print_bytes = 0, print_ptr = print_buffer, offline = -1, paperout = -1, total_bytes = 0;;) { /* * Use select() to determine whether we have data to copy around... */ FD_ZERO(&input); if (!print_bytes) FD_SET(print_fd, &input); if (use_bc) FD_SET(device_fd, &input); if (!print_bytes && side_cb) FD_SET(CUPS_SC_FD, &input); FD_ZERO(&output); if (print_bytes || (!use_bc && !side_cb)) FD_SET(device_fd, &output); if (use_bc || side_cb) { timeout.tv_sec = 5; timeout.tv_usec = 0; if (select(nfds, &input, &output, NULL, &timeout) < 0) { /* * Pause printing to clear any pending errors... */ if (errno == ENXIO && offline != 1 && update_state) { fputs("STATE: +offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is currently offline.\n")); offline = 1; } else if (errno == EINTR && total_bytes == 0) { fputs("DEBUG: Received an interrupt before any bytes were " "written, aborting!\n", stderr); return (0); } sleep(1); continue; } } /* * Check if we have a side-channel request ready... */ if (side_cb && FD_ISSET(CUPS_SC_FD, &input)) { /* * Do the side-channel request, then start back over in the select * loop since it may have read from print_fd... */ if ((*side_cb)(print_fd, device_fd, snmp_fd, addr, use_bc)) side_cb = NULL; continue; } /* * Check if we have back-channel data ready... */ if (FD_ISSET(device_fd, &input)) { if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0) { fprintf(stderr, "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n", CUPS_LLCAST bc_bytes); cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0); } else if (bc_bytes < 0 && errno != EAGAIN && errno != EINTR) { fprintf(stderr, "DEBUG: Error reading back-channel data: %s\n", strerror(errno)); use_bc = 0; } } /* * Check if we have print data ready... */ if (FD_ISSET(print_fd, &input)) { if ((print_bytes = read(print_fd, print_buffer, sizeof(print_buffer))) < 0) { /* * Read error - bail if we don't see EAGAIN or EINTR... */ if (errno != EAGAIN || errno != EINTR) { perror("ERROR: Unable to read print data"); return (-1); } print_bytes = 0; } else if (print_bytes == 0) { /* * End of file, break out of the loop... */ break; } print_ptr = print_buffer; fprintf(stderr, "DEBUG: Read %d bytes of print data...\n", (int)print_bytes); } /* * Check if the device is ready to receive data and we have data to * send... */ if (print_bytes && FD_ISSET(device_fd, &output)) { if ((bytes = write(device_fd, print_ptr, print_bytes)) < 0) { /* * Write error - bail if we don't see an error we can retry... */ if (errno == ENOSPC) { if (paperout != 1 && update_state) { fputs("STATE: +media-empty-warning\n", stderr); _cupsLangPuts(stderr, _("ERROR: Out of paper!\n")); paperout = 1; } } else if (errno == ENXIO) { if (offline != 1 && update_state) { fputs("STATE: +offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is currently off-line.\n")); offline = 1; } } else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY) { fprintf(stderr, _("ERROR: Unable to write print data: %s\n"), strerror(errno)); return (-1); } } else { if (paperout && update_state) { fputs("STATE: -media-empty-warning\n", stderr); paperout = 0; } if (offline && update_state) { fputs("STATE: -offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is now online.\n")); offline = 0; } fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes); print_bytes -= bytes; print_ptr += bytes; total_bytes += bytes; } } /* * Do SNMP updates periodically... */ if (snmp_fd >= 0 && time(&curtime) >= snmp_update) { if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL)) snmp_update = INT_MAX; else snmp_update = curtime + 5; } } /* * Return with success... */ return (total_bytes); }