]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/main.c
Add strlcat() and strlcpy() checks and emulation functions.
[thirdparty/cups.git] / scheduler / main.c
CommitLineData
3840d6ba 1/*
17438bf4 2 * "$Id: main.c,v 1.72 2002/05/16 13:45:02 mike Exp $"
3840d6ba 3 *
e5cf24b2 4 * Scheduler main loop for the Common UNIX Printing System (CUPS).
3840d6ba 5 *
efb2f309 6 * Copyright 1997-2002 by Easy Software Products, all rights reserved.
3840d6ba 7 *
fd8b1cf8 8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
3840d6ba 14 *
fd8b1cf8 15 * Attn: CUPS Licensing Information
16 * Easy Software Products
8784b6a6 17 * 44141 Airport View Drive, Suite 204
fd8b1cf8 18 * Hollywood, Maryland 20636-3111 USA
3840d6ba 19 *
fd8b1cf8 20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
992cf15a 23 *
fd8b1cf8 24 * Contents:
3840d6ba 25 *
d7845573 26 * main() - Main entry for the CUPS scheduler.
27 * CatchChildSignals() - Catch SIGCHLD signals...
28 * IgnoreChildSignals() - Ignore SIGCHLD signals...
29 * sigchld_handler() - Handle 'child' signals from old processes.
30 * sighup_handler() - Handle 'hangup' signals to reconfigure the scheduler.
31 * sigterm_handler() - Handle 'terminate' signals that stop the scheduler.
32 * usage() - Show scheduler usage.
3840d6ba 33 */
34
35/*
36 * Include necessary headers...
37 */
38
39#define _MAIN_C_
40#include "cupsd.h"
8b43895a 41#include <sys/resource.h>
a3e17a89 42#include <syslog.h>
3840d6ba 43
2bdd1992 44#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
8c57ced1 45# include <malloc.h>
2bdd1992 46#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
8c57ced1 47
5ec612d5 48#ifndef FD_SETSIZE
49# define FD_SETSIZE 1024
50#endif /* !FD_SETSIZE */
51
3840d6ba 52
53/*
fd8b1cf8 54 * Local functions...
55 */
56
e5cf24b2 57static void sigchld_handler(int sig);
fd8b1cf8 58static void sighup_handler(int sig);
a3e17a89 59static void sigterm_handler(int sig);
fd8b1cf8 60static void usage(void);
61
62
63/*
64 * 'main()' - Main entry for the CUPS scheduler.
3840d6ba 65 */
66
67int /* O - Exit status */
68main(int argc, /* I - Number of command-line arguments */
69 char *argv[]) /* I - Command-line arguments */
70{
71 int i; /* Looping var */
fd8b1cf8 72 char *opt; /* Option character */
a3e17a89 73 int fg; /* Run in the foreground */
3840d6ba 74 fd_set input, /* Input set for select() */
75 output; /* Output set for select() */
fd8b1cf8 76 client_t *con; /* Current client */
6abc7437 77 job_t *job, /* Current job */
78 *next; /* Next job */
fd8b1cf8 79 listener_t *lis; /* Current listener */
992cf15a 80 time_t activity; /* Activity timer */
05ca02bc 81 time_t senddoc_time; /* Send-Document time */
2bdd1992 82#ifdef HAVE_MALLINFO
83 time_t mallinfo_time; /* Malloc information time */
84#endif /* HAVE_MALLINFO */
3840d6ba 85 struct timeval timeout; /* select() timeout */
8b43895a 86 struct rlimit limit; /* Runtime limit */
8a2c2126 87#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
e5cf24b2 88 struct sigaction action; /* Actions for POSIX signals */
8a2c2126 89#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
d646a352 90#ifdef __sgi
91 FILE *fp; /* Fake lpsched lock file */
92#endif /* __sgi */
3840d6ba 93
94
fd8b1cf8 95 /*
96 * Check for command-line arguments...
97 */
98
a3e17a89 99 fg = 0;
100
fd8b1cf8 101 for (i = 1; i < argc; i ++)
102 if (argv[i][0] == '-')
103 for (opt = argv[i] + 1; *opt != '\0'; opt ++)
104 switch (*opt)
105 {
106 case 'c' : /* Configuration file */
107 i ++;
108 if (i >= argc)
109 usage();
110
a3e17a89 111 if (argv[i][0] == '/')
112 {
113 /*
114 * Absolute directory...
115 */
116
17438bf4 117 strlcpy(ConfigurationFile, argv[i], sizeof(ConfigurationFile));
a3e17a89 118 }
119 else
120 {
121 /*
122 * Relative directory...
123 */
124
125 getcwd(ConfigurationFile, sizeof(ConfigurationFile));
17438bf4 126 strlcat(ConfigurationFile, "/", sizeof(ConfigurationFile));
127 strlcat(ConfigurationFile, argv[i], sizeof(ConfigurationFile));
a3e17a89 128 }
129 break;
130
131 case 'f' : /* Run in foreground... */
132 fg = 1;
fd8b1cf8 133 break;
134
135 default : /* Unknown option */
136 fprintf(stderr, "cupsd: Unknown option \'%c\' - aborting!\n", *opt);
137 usage();
138 break;
139 }
140 else
141 {
142 fprintf(stderr, "cupsd: Unknown argument \'%s\' - aborting!\n", argv[i]);
143 usage();
144 }
145
992cf15a 146 /*
a3e17a89 147 * If the user hasn't specified "-f", run in the background...
992cf15a 148 */
149
a3e17a89 150 if (!fg)
151 {
152 if (fork() > 0)
153 return (0);
05e63c18 154
a3e17a89 155 /*
156 * Make sure we aren't tying up any filesystems...
157 */
158
159 chdir("/");
992cf15a 160
8b43895a 161#ifndef DEBUG
a3e17a89 162 /*
163 * Disable core dumps...
164 */
165
166 getrlimit(RLIMIT_CORE, &limit);
167 limit.rlim_cur = 0;
168 setrlimit(RLIMIT_CORE, &limit);
169
170 /*
171 * Disconnect from the controlling terminal...
172 */
173
174 close(0);
175 close(1);
176 close(2);
8b43895a 177
a3e17a89 178 setsid();
179#endif /* DEBUG */
180 }
147ddbb6 181
182 /*
a3e17a89 183 * Set the timezone info...
147ddbb6 184 */
185
a3e17a89 186 if (getenv("TZ") != NULL)
a6988fb1 187 snprintf(TZ, sizeof(TZ), "TZ=%s", getenv("TZ"));
a3e17a89 188
189 tzset();
8b43895a 190
191 /*
192 * Set the maximum number of files...
193 */
194
195 getrlimit(RLIMIT_NOFILE, &limit);
5ec612d5 196 if (limit.rlim_max > FD_SETSIZE) /* Can't exceed size of FD set! */
197 MaxFDs = FD_SETSIZE;
198 else
199 MaxFDs = limit.rlim_max;
200
201 limit.rlim_cur = MaxFDs;
8b43895a 202 setrlimit(RLIMIT_NOFILE, &limit);
203
3840d6ba 204 /*
2bffb563 205 * Catch hangup and child signals and ignore broken pipes...
3840d6ba 206 */
207
e5cf24b2 208#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
f3890b95 209 if (RunAsUser)
210 sigset(SIGHUP, sigterm_handler);
211 else
0b50ddbc 212 sigset(SIGHUP, sighup_handler);
e5cf24b2 213 sigset(SIGPIPE, SIG_IGN);
a3e17a89 214 sigset(SIGTERM, sigterm_handler);
e5cf24b2 215#elif defined(HAVE_SIGACTION)
2bffb563 216 memset(&action, 0, sizeof(action));
217
f3890b95 218 sigemptyset(&action.sa_mask);
219 sigaddset(&action.sa_mask, SIGHUP);
220
221 if (RunAsUser)
222 action.sa_handler = sigterm_handler;
223 else
0b50ddbc 224 action.sa_handler = sighup_handler;
f3890b95 225
226 sigaction(SIGHUP, &action, NULL);
2bffb563 227
e5cf24b2 228 sigemptyset(&action.sa_mask);
2bffb563 229 action.sa_handler = SIG_IGN;
230 sigaction(SIGPIPE, &action, NULL);
a3e17a89 231
232 sigemptyset(&action.sa_mask);
233 sigaddset(&action.sa_mask, SIGTERM);
234 action.sa_handler = sigterm_handler;
235 sigaction(SIGTERM, &action, NULL);
e5cf24b2 236#else
f3890b95 237 if (RunAsUser)
238 signal(SIGHUP, sigterm_handler);
239 else
0b50ddbc 240 signal(SIGHUP, sighup_handler);
f3890b95 241
e5cf24b2 242 signal(SIGPIPE, SIG_IGN);
a3e17a89 243 signal(SIGTERM, sigterm_handler);
e5cf24b2 244#endif /* HAVE_SIGSET */
3840d6ba 245
902cb359 246 /*
247 * Read configuration...
248 */
249
250 if (!ReadConfiguration())
251 {
252 syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
253 ConfigurationFile);
254 return (1);
255 }
256
d646a352 257#ifdef __sgi
258 /*
259 * Try to create a fake lpsched lock file if one is not already there.
260 * Some Adobe applications need it under IRIX in order to enable
261 * printing...
262 */
263
264 if ((fp = fopen("/var/spool/lp/SCHEDLOCK", "a")) == NULL)
265 {
266 syslog(LOG_LPR, "Unable to create fake lpsched lock file "
267 "\"/var/spool/lp/SCHEDLOCK\"\' - %s!",
268 strerror(errno));
269 }
270 else
271 {
272 fclose(fp);
273
274 chmod("/var/spool/lp/SCHEDLOCK", 0644);
275 chown("/var/spool/lp/SCHEDLOCK", User, Group);
276 }
277#endif /* __sgi */
278
1049abbe 279 /*
a98634ce 280 * Initialize authentication certificates...
1049abbe 281 */
282
23bba0c3 283 InitCerts();
284
a98634ce 285 /*
286 * Load all the jobs...
287 */
288
1049abbe 289 LoadAllJobs();
290
3840d6ba 291 /*
292 * Loop forever...
293 */
294
05ca02bc 295 senddoc_time = time(NULL);
296
b6ea8f29 297#ifdef HAVE_MALLINFO
298 mallinfo_time = 0;
299#endif /* HAVE_MALLINFO */
300
a74b005d 301 for (;;)
3840d6ba 302 {
fd8b1cf8 303 /*
304 * Check if we need to load the server configuration file...
305 */
306
307 if (NeedReload)
308 {
309 if (NumClients > 0)
310 {
311 for (i = NumClients, con = Clients; i > 0; i --, con ++)
a74b005d 312 if (con->http.state == HTTP_WAITING)
fd8b1cf8 313 {
314 CloseClient(con);
315 con --;
316 }
317 else
93894a43 318 con->http.keep_alive = HTTP_KEEPALIVE_OFF;
fd8b1cf8 319
d236cb49 320 PauseListening();
fd8b1cf8 321 }
322 else if (!ReadConfiguration())
323 {
a3e17a89 324 syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
325 ConfigurationFile);
d2122fde 326 break;
fd8b1cf8 327 }
328 }
329
3840d6ba 330 /*
331 * Check for available input or ready output. If select() returns
332 * 0 or -1, something bad happened and we should exit immediately.
333 *
42d48bd2 334 * Note that we at least have one listening socket open at all
3840d6ba 335 * times.
336 */
337
338 input = InputSet;
339 output = OutputSet;
340
f736c0e3 341 timeout.tv_sec = 1;
342 timeout.tv_usec = 0;
343
fd8b1cf8 344 for (i = NumClients, con = Clients; i > 0; i --, con ++)
a74b005d 345 if (con->http.used > 0)
f736c0e3 346 {
347 timeout.tv_sec = 0;
3840d6ba 348 break;
f736c0e3 349 }
3840d6ba 350
93336dbc 351 if ((i = select(MaxFDs, &input, &output, NULL, &timeout)) < 0)
fd8b1cf8 352 {
d236cb49 353 char s[16384], /* String buffer */
354 *sptr; /* Pointer into buffer */
355 int slen; /* Length of string buffer */
356
357
886c59e2 358 /*
359 * Got an error from select!
360 */
361
362 if (errno == EINTR) /* Just interrupted by a signal */
fd8b1cf8 363 continue;
364
886c59e2 365 /*
d236cb49 366 * Log all sorts of debug info to help track down the problem.
886c59e2 367 */
368
5236f873 369 LogMessage(L_EMERG, "select() failed - %s!", strerror(errno));
d236cb49 370
371 strcpy(s, "InputSet =");
024012d6 372 slen = 10;
373 sptr = s + 10;
d236cb49 374
93336dbc 375 for (i = 0; i < MaxFDs; i ++)
d236cb49 376 if (FD_ISSET(i, &InputSet))
024012d6 377 {
04de52f8 378 snprintf(sptr, sizeof(s) - slen, " %d", i);
024012d6 379 slen += strlen(sptr);
380 sptr += strlen(sptr);
381 }
bfa1abf0 382
5236f873 383 LogMessage(L_EMERG, s);
bfa1abf0 384
d236cb49 385 strcpy(s, "OutputSet =");
024012d6 386 slen = 11;
387 sptr = s + 11;
d236cb49 388
93336dbc 389 for (i = 0; i < MaxFDs; i ++)
d236cb49 390 if (FD_ISSET(i, &OutputSet))
024012d6 391 {
04de52f8 392 snprintf(sptr, sizeof(s) - slen, " %d", i);
024012d6 393 slen += strlen(sptr);
394 sptr += strlen(sptr);
395 }
d236cb49 396
5236f873 397 LogMessage(L_EMERG, s);
886c59e2 398
882031b3 399 for (i = 0, con = Clients; i < NumClients; i ++, con ++)
5236f873 400 LogMessage(L_EMERG, "Clients[%d] = %d, file = %d, state = %d",
df47c6ae 401 i, con->http.fd, con->file, con->http.state);
886c59e2 402
403 for (i = 0, lis = Listeners; i < NumListeners; i ++, lis ++)
5236f873 404 LogMessage(L_EMERG, "Listeners[%d] = %d", i, lis->fd);
886c59e2 405
5236f873 406 LogMessage(L_EMERG, "BrowseSocket = %d", BrowseSocket);
886c59e2 407
408 for (job = Jobs; job != NULL; job = job->next)
5236f873 409 LogMessage(L_EMERG, "Jobs[%d] = %d", job->id, job->pipe);
bfa1abf0 410
3840d6ba 411 break;
fd8b1cf8 412 }
3840d6ba 413
fd8b1cf8 414 for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
415 if (FD_ISSET(lis->fd, &input))
416 AcceptClient(lis);
3840d6ba 417
fd8b1cf8 418 for (i = NumClients, con = Clients; i > 0; i --, con ++)
3840d6ba 419 {
3840d6ba 420 /*
421 * Process the input buffer...
422 */
423
a74b005d 424 if (FD_ISSET(con->http.fd, &input) || con->http.used)
fd8b1cf8 425 if (!ReadClient(con))
3840d6ba 426 {
427 con --;
3840d6ba 428 continue;
429 }
430
431 /*
432 * Write data as needed...
433 */
434
96df88bb 435 if (FD_ISSET(con->http.fd, &output) &&
436 (!con->pipe_pid || FD_ISSET(con->file, &input)))
fd8b1cf8 437 if (!WriteClient(con))
3840d6ba 438 {
439 con --;
992cf15a 440 continue;
3840d6ba 441 }
992cf15a 442
443 /*
fd8b1cf8 444 * Check the activity and close old clients...
992cf15a 445 */
446
df47c6ae 447 activity = time(NULL) - Timeout;
448 if (con->http.activity < activity && !con->pipe_pid)
992cf15a 449 {
fd8b1cf8 450 CloseClient(con);
992cf15a 451 con --;
992cf15a 452 continue;
453 }
3840d6ba 454 }
6abc7437 455
456 /*
457 * Check for status info from job filters...
458 */
459
460 for (job = Jobs; job != NULL; job = next)
461 {
462 next = job->next;
463
464 if (job->pipe && FD_ISSET(job->pipe, &input))
5236f873 465 {
466 /*
467 * Clear the input bit to avoid updating the next job
468 * using the same status pipe file descriptor...
469 */
470
471 FD_CLR(job->pipe, &input);
472
473 /*
474 * Read any status messages from the filters...
475 */
476
6abc7437 477 UpdateJob(job);
5236f873 478 }
6abc7437 479 }
d6de4648 480
481 /*
482 * Update the browse list as needed...
483 */
484
dded8a26 485 if (Browsing && BrowseProtocols)
a40c1c6f 486 {
dded8a26 487 if (BrowseSocket >= 0 && FD_ISSET(BrowseSocket, &input))
1012752f 488 UpdateCUPSBrowse();
d6de4648 489
1be73957 490 if (PollPipe >= 0 && FD_ISSET(PollPipe, &input))
38f52966 491 UpdatePolling();
492
25d465a4 493#ifdef HAVE_LIBSLP
494 if ((BrowseProtocols & BROWSE_SLP) && BrowseSLPRefresh <= time(NULL))
495 UpdateSLPBrowse();
496#endif /* HAVE_LIBSLP */
497
a40c1c6f 498 SendBrowseList();
499 }
d2122fde 500
05ca02bc 501 /*
502 * Update any pending multi-file documents...
503 */
504
f3c3b479 505 if ((time(NULL) - senddoc_time) >= 10)
05ca02bc 506 {
507 CheckJobs();
508 senddoc_time = time(NULL);
509 }
510
2bdd1992 511#ifdef HAVE_MALLINFO
d2122fde 512 /*
2bdd1992 513 * Log memory usage every minute...
d2122fde 514 */
515
2bdd1992 516 if ((time(NULL) - mallinfo_time) >= 60 && LogLevel >= L_DEBUG)
d2122fde 517 {
8c57ced1 518 struct mallinfo mem; /* Malloc information */
519
520
8c57ced1 521 mem = mallinfo();
522 LogMessage(L_DEBUG, "mallinfo: arena = %d, used = %d, free = %d\n",
523 mem.arena, mem.usmblks + mem.uordblks,
524 mem.fsmblks + mem.fordblks);
2bdd1992 525 mallinfo_time = time(NULL);
526 }
527#endif /* HAVE_MALLINFO */
8c57ced1 528
2bdd1992 529 /*
530 * Update the root certificate once every 5 minutes...
531 */
532
533 if ((time(NULL) - RootCertTime) >= 300)
534 {
8c57ced1 535 /*
536 * Update the root certificate...
537 */
538
d2122fde 539 DeleteCert(0);
540 AddCert(0, "root");
541 }
3840d6ba 542 }
543
544 /*
545 * If we get here something very bad happened and we need to exit
546 * immediately.
547 */
548
d2122fde 549 DeleteAllCerts();
fd8b1cf8 550 CloseAllClients();
551 StopListening();
552
553 return (1);
554}
3840d6ba 555
3840d6ba 556
d7845573 557/*
558 * 'CatchChildSignals()' - Catch SIGCHLD signals...
559 */
560
561void
562CatchChildSignals(void)
563{
564#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
565 struct sigaction action; /* Actions for POSIX signals */
566#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
567
568
569#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
570 sigset(SIGCHLD, sigchld_handler);
571#elif defined(HAVE_SIGACTION)
572 memset(&action, 0, sizeof(action));
573
574 sigemptyset(&action.sa_mask);
575 sigaddset(&action.sa_mask, SIGCHLD);
576 action.sa_handler = sigchld_handler;
577 sigaction(SIGCHLD, &action, NULL);
578#else
579 signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */
580#endif /* HAVE_SIGSET */
581}
582
583
584/*
585 * 'IgnoreChildSignals()' - Ignore SIGCHLD signals...
586 */
587
588void
589IgnoreChildSignals(void)
590{
591#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
592 struct sigaction action; /* Actions for POSIX signals */
593#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
594
595#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
596 sigset(SIGCHLD, SIG_IGN);
597#elif defined(HAVE_SIGACTION)
598 memset(&action, 0, sizeof(action));
599
600 sigemptyset(&action.sa_mask);
601 sigaddset(&action.sa_mask, SIGCHLD);
602 action.sa_handler = SIG_IGN;
603 sigaction(SIGCHLD, &action, NULL);
604#else
605 signal(SIGCLD, SIG_IGN); /* No, SIGCLD isn't a typo... */
606#endif /* HAVE_SIGSET */
607}
608
609
6abc7437 610/*
e5cf24b2 611 * 'sigchld_handler()' - Handle 'child' signals from old processes.
6abc7437 612 */
613
614static void
e5cf24b2 615sigchld_handler(int sig) /* I - Signal number */
6abc7437 616{
e5cf24b2 617 int status; /* Exit status of child */
618 int pid; /* Process ID of child */
619 job_t *job; /* Current job */
620 int i; /* Looping var */
6abc7437 621
622
623 (void)sig;
624
e5cf24b2 625#ifdef HAVE_WAITPID
626 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
627#elif defined(HAVE_WAIT3)
628 while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
629#else
630 if ((pid = wait(&status)) > 0)
631#endif /* HAVE_WAITPID */
632 {
633 DEBUG_printf(("sigcld_handler: pid = %d, status = %d\n", pid, status));
6abc7437 634
d2122fde 635 /*
636 * Delete certificates for CGI processes...
637 */
638
639 if (pid)
640 DeleteCert(pid);
641
642 /*
643 * Ignore SIGTERM errors - that comes when a job is cancelled...
644 */
645
6bc08d08 646 if (status == SIGTERM)
647 status = 0;
648
649 if (status)
650 {
651 if (status < 256)
5ea8888e 652 LogMessage(L_ERROR, "PID %d crashed on signal %d!", pid, status);
6bc08d08 653 else
6d8b6788 654 LogMessage(L_ERROR, "PID %d stopped with status %d!", pid,
6bc08d08 655 status / 256);
656 }
e5b7bd9c 657
e5cf24b2 658 for (job = Jobs; job != NULL; job = job->next)
1049abbe 659 if (job->state->values[0].integer == IPP_JOB_PROCESSING)
6abc7437 660 {
e5cf24b2 661 for (i = 0; job->procs[i]; i ++)
662 if (job->procs[i] == pid)
663 break;
6abc7437 664
e5cf24b2 665 if (job->procs[i])
bfa1abf0 666 {
667 /*
e5cf24b2 668 * OK, this process has gone away; what's left?
bfa1abf0 669 */
6abc7437 670
e5cf24b2 671 job->procs[i] = -pid;
6abc7437 672
bd84e0d1 673 if (status && job->status >= 0)
e5cf24b2 674 {
675 /*
bd84e0d1 676 * An error occurred; save the exit status so we know to stop
677 * the printer or cancel the job when all of the filters finish...
678 *
679 * A negative status indicates that the backend failed and the
680 * printer needs to be stopped.
e5cf24b2 681 */
682
bd84e0d1 683 if (!job->procs[i + 1])
684 job->status = -status; /* Backend failed */
685 else
686 job->status = status; /* Filter failed */
e5cf24b2 687 }
e5cf24b2 688 break;
689 }
6abc7437 690 }
e5cf24b2 691 }
692
693#ifdef HAVE_SIGSET
694 sigset(SIGCHLD, sigchld_handler);
695#elif !defined(HAVE_SIGACTION)
696 signal(SIGCLD, sigchld_handler);
697#endif /* HAVE_SIGSET */
6abc7437 698}
699
700
fd8b1cf8 701/*
702 * 'sighup_handler()' - Handle 'hangup' signals to reconfigure the scheduler.
703 */
704
705static void
706sighup_handler(int sig) /* I - Signal number */
707{
93894a43 708 (void)sig;
709
fd8b1cf8 710 NeedReload = TRUE;
a3e17a89 711
712#ifdef HAVE_SIGSET
713 sigset(SIGHUP, sighup_handler);
714#elif !defined(HAVE_SIGACTION)
715 signal(SIGHUP, sighup_handler);
716#endif /* HAVE_SIGSET */
717}
718
719
720/*
721 * 'sigterm_handler()' - Handle 'terminate' signals that stop the scheduler.
722 */
723
724static void
725sigterm_handler(int sig)
726{
d646a352 727#ifdef __sgi
728 struct stat statbuf; /* Needed for checking lpsched FIFO */
729#endif /* __sgi */
730
731
d74efa25 732 (void)sig; /* remove compiler warnings... */
733
a3e17a89 734 /*
735 * Log an error...
736 */
737
738 LogMessage(L_ERROR, "Scheduler shutting down due to SIGTERM.");
739
740 /*
741 * Close all network clients and stop all jobs...
742 */
743
744 CloseAllClients();
745 StopListening();
746 StopPolling();
747 StopBrowsing();
748
749 if (Clients != NULL)
750 free(Clients);
751
752 StopAllJobs();
753
754 if (AccessFile != NULL)
755 fclose(AccessFile);
756
757 if (ErrorFile != NULL)
758 fclose(ErrorFile);
759
760 if (PageFile != NULL)
761 fclose(PageFile);
762
763 DeleteAllLocations();
764
765 DeleteAllClasses();
766
767 if (Devices)
768 ippDelete(Devices);
769
770 if (PPDs)
771 ippDelete(PPDs);
772
773 DeleteAllPrinters();
774
775 if (MimeDatabase != NULL)
776 mimeDelete(MimeDatabase);
777
d646a352 778#ifdef __sgi
779 /*
780 * Remove the fake IRIX lpsched lock file, but only if the existing
781 * file is not a FIFO which indicates that the real IRIX lpsched is
782 * running...
783 */
784
785 if (!stat("/var/spool/lp/FIFO", &statbuf))
786 if (!S_ISFIFO(statbuf.st_mode))
787 unlink("/var/spool/lp/SCHEDLOCK");
788#endif /* __sgi */
789
a3e17a89 790 exit(1);
3840d6ba 791}
792
fd8b1cf8 793
794/*
795 * 'usage()' - Show scheduler usage.
796 */
797
798static void
799usage(void)
800{
a3e17a89 801 fputs("Usage: cupsd [-c config-file] [-f]\n", stderr);
fd8b1cf8 802 exit(1);
803}
804
805
3840d6ba 806/*
17438bf4 807 * End of "$Id: main.c,v 1.72 2002/05/16 13:45:02 mike Exp $".
3840d6ba 808 */