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