lpsched.c revision 96ccc8cb05e8790fcc24931dcb155b76e810295c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "limits.h"
#include "ulimit.h"
#include "lpsched.h"
#include <sys/resource.h>
#include <syslog.h>
#include <locale.h>
#include <stdio_ext.h>
int lock_fd = -1;
int isStartingForms = 0;
int Starting = 0;
int Shutdown = 0;
int DoneChildren = 0;
int Sig_Alrm = 0;
int Reserve_Fds = 0;
char *Local_System = 0;
char *SHELL = 0;
char *LP_TRAY_UNMOUNT = NULL;
char *LP_KILL_NO_PAPER = NULL;
char *LP_ALL_NEW = NULL;
#if defined(DEBUG)
unsigned long debug = 0;
static int signals = 0;
#endif
extern int errno;
extern void shutdown_messages();
int am_in_background = 0;
static void disable_signals();
static void startup();
static void process();
static void ticktock(int);
static void background();
static void usage();
static void Exit();
static void disable_signals();
/**
** main()
**/
int
{
int c;
extern char *optarg;
extern int optopt;
extern int opterr;
char * cp;
int fd_limit = 4096;
else
cp++;
/* open the syslog() */
opterr = 0;
switch(c)
{
# if defined (DEBUG)
case 'd':
goto SkipD;
case 'D':
if (*optarg == '?') {
note (
" although \"lpsched\" goes to stdout if SDB)\n"
"\n"
" EXEC (log all exec's in \"exec\")\n"
" DONE (log just exec finishes in \"exec\")\n"
" INIT (log initialization info in \"lpsched\" or stdout)\n"
" ABORT (issue abort(2) on fatal error)\n"
" SCHEDLOG (log additional debugging info in \"lpsched\")\n"
" SDB (don't start lpsched as background process)\n"
" MESSAGES (log all message traffic in \"messages\")\n"
);
note ("\
ALL (all of the above; equivalent to -d)\n"
);
exit (0);
}
else {
note ("-D flag not recognized; try -D?\n");
exit (1);
}
optarg = 0;
}
break;
case 's':
signals++;
break;
# endif /* DEBUG */
case 'f':
ET_SlowSize = 1;
break;
case 'n':
ET_NotifySize = 1;
break;
case 'r':
Reserve_Fds = 0;
break;
case 'p':
fd_limit = 4096;
break;
case '?':
if (optopt == '?') {
usage ();
exit (0);
} else
}
/* reset the fd resource limit */
startup();
process();
/*NOTREACHED*/
return (0);
}
static void
startup()
{
struct passwd *p;
Starting = 1;
getpaths();
/*
* There must be a user named "lp".
*/
fail ("Can't find the user \"lp\" on this system!\n");
/*
* Only "root" is allowed to run us.
*/
fail ("You must be \"root\" to run this program.\n");
setuid (0);
/*
* Make sure that all critical directories are present and that
* symbolic links are correct.
*/
lpfsck();
/*
* Try setting the lock file to see if another Spooler is running.
* We'll release it immediately; this allows us to fork the child
* that will run in the background. The child will relock the file.
*/
fail ("Print services already active.\n");
else
background();
/*
* We are the child process now.
*/
Close (0);
Close (2);
if (am_in_background)
Close (1);
init_memory();
note ("Print services started.\n");
Starting = 0;
}
void
{
int i;
/*
* If this is the first time here, stop all running
* child processes, and shut off the alarm clock so
* it doesn't bug us.
*/
if (!Shutdown) {
for (i = 0; i < ET_Size; i++)
terminate (&Exec_Table[i]);
alarm (0);
}
/*
* If this is an express shutdown, or if all the
* child processes have been cleaned up, clean up
* and get out.
*/
if (Shutdown == 2) {
/*
* We don't shut down the message queues until
* now, to give the children a chance to answer.
* This means an LP command may have been snuck
* in while we were waiting for the children to
* finish, but that's OK because we'll have
* stored the jobs on disk (that's part of the
* normal operation, not just during shutdown phase).
*/
(void) Unlink(Lp_Schedlock);
note ("Print services stopped.\n");
exit (0);
/*NOTREACHED*/
}
}
static void
process()
{
/*
* Call the "check_..._alert()" routines for each form/print-wheel;
* we need to do this at this point because these routines
* short-circuit themselves while we are in startup mode.
* Calling them now will kick off any necessary alerts.
*/
isStartingForms = 1;
isStartingForms = 0;
/*
* Clear the alarm, then schedule an EV_ALARM. This will clear
* all events that had been scheduled for later without waiting
* for the next tick.
*/
alarm (0);
/*
* Start the ball rolling.
*/
for (EVER) {
take_message ();
if (Sig_Alrm)
if (DoneChildren)
dowait ();
if (Shutdown)
if (Shutdown == 2)
break;
}
}
/*ARGSUSED*/
static void
{
Sig_Alrm = 1;
return;
}
static void
{
#if defined(DEBUG)
return;
#endif
switch(fork())
{
case -1:
/*NOTREACHED*/
case 0:
(void) setpgrp();
am_in_background = 1;
return;
default:
note ("Print services started.\n");
exit(0);
/* NOTREACHED */
}
}
static void
usage()
{
note ("\
usage: lpsched [ options ]\n\
[ -f #filter-slots ] (increase no. concurrent slow filters)\n\
[ -n #notify-slots ] (increase no. concurrent notifications)\n\
[ -r #reserved-fds ] (increase margin of file descriptors)\n"
);
#if defined(DEBUG)
note ("\
[ -D flag[,flag...] ] (debug modes; use -D? for usage info.)\n\
[ -d ] (same as -D ALL)\n\
[ -s ] (don't trap most signals)\n"
);
#endif
note ("\
WARNING: all these options are currently unsupported\n"
);
return;
}
static void
Exit(n)
int n;
{
fail ("Received unexpected signal %d; terminating.\n", n);
}
static void
{
int i;
# if defined(DEBUG)
if (!signals)
# endif
for (i = 0; i < NSIG; i++)
#if defined(DEBUG)
#endif
}