]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/conf.c
2 * "$Id: conf.c,v 1.39 2000/01/04 13:46:09 mike Exp $"
4 * Configuration routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2000 by Easy Software Products, all rights reserved.
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.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * ReadConfiguration() - Read the cupsd.conf file.
27 * read_configuration() - Read a configuration file.
28 * read_location() - Read a <Location path> definition.
29 * get_address() - Get an address + port number from a line.
33 * Include necessary headers...
40 #include <sys/resource.h>
44 * Possibly missing network definitions...
48 # define INADDR_NONE 0xffffffff
49 #endif /* !INADDR_NONE */
53 * Configuration variable structure...
58 char *name
; /* Name of variable */
59 void *ptr
; /* Pointer to variable */
60 int type
, /* Type (int, string, address) */
61 size
; /* Size of string */
73 static var_t variables
[] =
75 { "ServerName", ServerName
, VAR_STRING
, sizeof(ServerName
) },
76 { "ServerAdmin", ServerAdmin
, VAR_STRING
, sizeof(ServerAdmin
) },
77 { "ServerRoot", ServerRoot
, VAR_STRING
, sizeof(ServerRoot
) },
78 { "ServerBin", ServerBin
, VAR_STRING
, sizeof(ServerBin
) },
79 { "DocumentRoot", DocumentRoot
, VAR_STRING
, sizeof(DocumentRoot
) },
80 { "RequestRoot", RequestRoot
, VAR_STRING
, sizeof(RequestRoot
) },
81 { "SystemGroup", SystemGroup
, VAR_STRING
, sizeof(SystemGroup
) },
82 { "AccessLog", AccessLog
, VAR_STRING
, sizeof(AccessLog
) },
83 { "ErrorLog", ErrorLog
, VAR_STRING
, sizeof(ErrorLog
) },
84 { "PageLog", PageLog
, VAR_STRING
, sizeof(PageLog
) },
85 { "DefaultCharset", DefaultCharset
, VAR_STRING
, sizeof(DefaultCharset
) },
86 { "DefaultLanguage", DefaultLanguage
, VAR_STRING
, sizeof(DefaultLanguage
) },
87 { "RIPCache", RIPCache
, VAR_STRING
, sizeof(RIPCache
) },
88 { "TempDir", TempDir
, VAR_STRING
, sizeof(TempDir
) },
89 { "HostNameLookups", &HostNameLookups
, VAR_BOOLEAN
, 0 },
90 { "Timeout", &Timeout
, VAR_INTEGER
, 0 },
91 { "KeepAlive", &KeepAlive
, VAR_BOOLEAN
, 0 },
92 { "KeepAliveTimeout", &KeepAliveTimeout
, VAR_INTEGER
, 0 },
93 { "ImplicitClasses", &ImplicitClasses
, VAR_BOOLEAN
, 0 },
94 { "Browsing", &Browsing
, VAR_BOOLEAN
, 0 },
95 { "BrowsePort", &BrowsePort
, VAR_INTEGER
, 0 },
96 { "BrowseInterval", &BrowseInterval
, VAR_INTEGER
, 0 },
97 { "BrowseTimeout", &BrowseTimeout
, VAR_INTEGER
, 0 },
98 { "MaxClients", &MaxClients
, VAR_INTEGER
, 0 },
99 { "MaxLogSize", &MaxLogSize
, VAR_INTEGER
, 0 },
100 { "MaxRequestSize", &MaxRequestSize
, VAR_INTEGER
, 0 },
101 { "PreserveJobHistory", &JobHistory
, VAR_BOOLEAN
, 0 },
102 { "PreserveJobFiles", &JobFiles
, VAR_BOOLEAN
, 0 }
104 #define NUM_VARS (sizeof(variables) / sizeof(variables[0]))
111 static int read_configuration(FILE *fp
);
112 static int read_location(FILE *fp
, char *name
, int linenum
);
113 static int get_address(char *value
, unsigned defaddress
, int defport
,
114 struct sockaddr_in
*address
);
118 * 'ReadConfiguration()' - Read the cupsd.conf file.
121 int /* O - 1 if file read successfully, 0 otherwise */
122 ReadConfiguration(void)
124 FILE *fp
; /* Configuration file */
125 int status
; /* Return status */
126 char directory
[1024];/* Configuration directory */
127 struct rlimit limit
; /* Runtime limit */
128 char *language
; /* Language string */
129 struct passwd
*user
; /* Default user */
130 struct group
*group
; /* Default group */
134 * Close all network clients and stop all jobs...
149 if (AccessFile
!= NULL
)
156 if (ErrorFile
!= NULL
)
163 if (PageFile
!= NULL
)
171 * Clear the current configuration...
179 DeleteAllLocations();
183 gethostname(ServerName
, sizeof(ServerName
));
184 sprintf(ServerAdmin
, "root@%s", ServerName
);
185 strcpy(ServerRoot
, CUPS_SERVERROOT
);
186 strcpy(ServerBin
, CUPS_SERVERBIN
);
187 strcpy(RequestRoot
, CUPS_REQUESTS
);
188 strcpy(DocumentRoot
, CUPS_DOCROOT
);
189 strcpy(AccessLog
, CUPS_LOGDIR
"/access_log");
190 strcpy(ErrorLog
, CUPS_LOGDIR
"/error_log");
191 strcpy(PageLog
, CUPS_LOGDIR
"/page_log");
193 if ((language
= DEFAULT_LANGUAGE
) == NULL
)
195 else if (strcmp(language
, "C") == 0 || strcmp(language
, "POSIX") == 0)
198 strncpy(DefaultLanguage
, language
, sizeof(DefaultLanguage
) - 1);
199 DefaultLanguage
[sizeof(DefaultLanguage
) - 1] = '\0';
201 strcpy(DefaultCharset
, DEFAULT_CHARSET
);
202 strcpy(RIPCache
, "8m");
203 if (getenv("TMPDIR") == NULL
)
204 strcpy(TempDir
, "/var/tmp");
207 strncpy(TempDir
, getenv("TMPDIR"), sizeof(TempDir
) - 1);
208 TempDir
[sizeof(TempDir
) - 1] = '\0';
212 * Find the default system group: "sys", "system", or "root"...
215 group
= getgrnam("sys");
220 strcpy(SystemGroup
, "sys");
221 Group
= group
->gr_gid
;
225 group
= getgrnam("system");
230 strcpy(SystemGroup
, "system");
231 Group
= group
->gr_gid
;
235 group
= getgrnam("root");
240 strcpy(SystemGroup
, "root");
241 Group
= group
->gr_gid
;
245 strcpy(SystemGroup
, "unknown");
252 * Find the default user...
255 if ((user
= getpwnam("lp")) == NULL
)
256 User
= 1; /* Force to a non-priviledged account */
262 LogLevel
= LOG_ERROR
;
263 HostNameLookups
= FALSE
;
264 Timeout
= DEFAULT_TIMEOUT
;
266 KeepAliveTimeout
= DEFAULT_KEEPALIVE
;
267 ImplicitClasses
= TRUE
;
271 MaxLogSize
= 1024 * 1024;
275 BrowsePort
= ippPort();
276 BrowseInterval
= DEFAULT_INTERVAL
;
277 BrowseTimeout
= DEFAULT_TIMEOUT
;
282 DefaultPrinter
= NULL
;
286 if (MimeDatabase
!= NULL
)
287 mimeDelete(MimeDatabase
);
289 JobHistory
= DEFAULT_HISTORY
;
290 JobFiles
= DEFAULT_FILES
;
292 if ((fp
= fopen(ConfigurationFile
, "r")) == NULL
)
295 status
= read_configuration(fp
);
302 if (DocumentRoot
[0] != '/')
304 snprintf(directory
, sizeof(directory
), "%s/%s", ServerRoot
, DocumentRoot
);
305 strcpy(DocumentRoot
, directory
);
308 if (RequestRoot
[0] != '/')
310 snprintf(directory
, sizeof(directory
), "%s/%s", ServerRoot
, RequestRoot
);
311 strcpy(RequestRoot
, directory
);
314 if (ServerBin
[0] != '/')
316 snprintf(directory
, sizeof(directory
), "%s/%s", ServerRoot
, ServerBin
);
317 strcpy(ServerBin
, directory
);
320 LogMessage(LOG_DEBUG
, "ReadConfiguration() ConfigurationFile=\"%s\"",
324 * Check the MaxClients setting, and then allocate memory for it...
327 getrlimit(RLIMIT_NOFILE
, &limit
);
329 if (MaxClients
> (limit
.rlim_max
/ 3))
330 MaxClients
= limit
.rlim_max
/ 3;
332 if ((Clients
= calloc(sizeof(client_t
), MaxClients
)) == NULL
)
334 LogMessage(LOG_ERROR
, "ReadConfiguration() FATAL: unable to allocate memory for %d clients!",
339 LogMessage(LOG_INFO
, "ReadConfiguration() Configured for up to %d clients.",
343 * Read the MIME type and conversion database...
346 snprintf(directory
, sizeof(directory
), "%s/conf", ServerRoot
);
348 MimeDatabase
= mimeNew();
349 mimeMerge(MimeDatabase
, directory
);
352 * Load printers, classes, and jobs...
359 * Add a default browser if browsing is enabled and no browser addresses
363 if (Browsing
&& NumBrowsers
== 0)
367 memset(Browsers
+ 0, 0, sizeof(Browsers
[0]));
368 Browsers
[0].sin_addr
.s_addr
= htonl(INADDR_BROADCAST
);
369 Browsers
[0].sin_family
= AF_INET
;
370 Browsers
[0].sin_port
= htons(BrowsePort
);
374 * Startup all the networking stuff...
381 * Check for queued jobs...
391 * 'read_configuration()' - Read a configuration file.
394 static int /* O - 1 on success, 0 on failure */
395 read_configuration(FILE *fp
) /* I - File to read from */
397 int i
; /* Looping var */
398 int linenum
; /* Current line number */
399 int len
; /* Length of line */
400 char line
[HTTP_MAX_BUFFER
], /* Line from file */
401 name
[256], /* Parameter name */
402 *nameptr
, /* Pointer into name */
403 *value
; /* Pointer to value */
404 var_t
*var
; /* Current variable */
408 * Loop through each line in the file...
413 while (fgets(line
, sizeof(line
), fp
) != NULL
)
418 * Skip comment lines...
425 * Strip trailing newline, if any...
430 if (line
[len
- 1] == '\n')
437 * Extract the name from the beginning of the line...
440 for (value
= line
; isspace(*value
); value
++);
442 for (nameptr
= name
; *value
!= '\0' && !isspace(*value
);)
443 *nameptr
++ = *value
++;
446 while (isspace(*value
))
453 * Decode the directive...
456 if (strcmp(name
, "<Location") == 0)
462 if (line
[len
- 1] == '>')
464 line
[len
- 1] = '\0';
466 linenum
= read_location(fp
, value
, linenum
);
472 LogMessage(LOG_ERROR
, "ReadConfiguration() Syntax error on line %d.",
477 else if (strcmp(name
, "Port") == 0 ||
478 strcmp(name
, "Listen") == 0)
481 * Add a listening address to the list...
484 if (NumListeners
< MAX_BROWSERS
)
486 if (get_address(value
, INADDR_ANY
, IPP_PORT
,
487 &(Listeners
[NumListeners
].address
)))
489 LogMessage(LOG_INFO
, "Listening to %x:%d\n",
490 ntohl(Listeners
[NumListeners
].address
.sin_addr
.s_addr
),
491 ntohs(Listeners
[NumListeners
].address
.sin_port
));
495 LogMessage(LOG_ERROR
, "Bad %s address %s at line %d.", name
,
499 LogMessage(LOG_WARN
, "Too many %s directives at line %d.", name
,
502 else if (strcmp(name
, "BrowseAddress") == 0)
505 * Add a browse address to the list...
508 if (NumBrowsers
< MAX_BROWSERS
)
510 if (get_address(value
, INADDR_NONE
, BrowsePort
, Browsers
+ NumBrowsers
))
512 LogMessage(LOG_INFO
, "Sending browsing info to %x:%d\n",
513 ntohl(Browsers
[NumBrowsers
].sin_addr
.s_addr
),
514 ntohs(Browsers
[NumBrowsers
].sin_port
));
518 LogMessage(LOG_ERROR
, "Bad BrowseAddress %s at line %d.", value
,
522 LogMessage(LOG_WARN
, "Too many BrowseAddress directives at line %d.",
525 else if (strcmp(name
, "User") == 0)
528 * User ID to run as...
531 if (isdigit(value
[0]))
535 struct passwd
*p
; /* Password information */
543 LogMessage(LOG_WARN
, "ReadConfiguration() Unknown username \"%s\"",
547 else if (strcmp(name
, "Group") == 0)
550 * Group ID to run as...
553 if (isdigit(value
[0]))
557 struct group
*g
; /* Group information */
565 LogMessage(LOG_WARN
, "ReadConfiguration() Unknown groupname \"%s\"",
569 else if (strcmp(name
, "LogLevel") == 0)
572 * Amount of logging to do...
575 if (strcmp(value
, "debug") == 0)
576 LogLevel
= LOG_DEBUG
;
577 else if (strcmp(value
, "info") == 0)
579 else if (strcmp(value
, "warn") == 0)
581 else if (strcmp(value
, "error") == 0)
582 LogLevel
= LOG_ERROR
;
583 else if (strcmp(value
, "none") == 0)
589 * Find a simple variable in the list...
592 for (i
= NUM_VARS
, var
= variables
; i
> 0; i
--, var
++)
593 if (strcmp(name
, var
->name
) == 0)
599 * Unknown directive! Output an error message and continue...
602 LogMessage(LOG_ERROR
, "Unknown directive %s on line %d.", name
,
610 *((int *)var
->ptr
) = atoi(value
);
614 if (strcasecmp(value
, "true") == 0 ||
615 strcasecmp(value
, "on") == 0 ||
616 strcasecmp(value
, "enabled") == 0 ||
618 *((int *)var
->ptr
) = TRUE
;
619 else if (strcasecmp(value
, "false") == 0 ||
620 strcasecmp(value
, "off") == 0 ||
621 strcasecmp(value
, "disabled") == 0 ||
622 strcasecmp(value
, "0") == 0)
623 *((int *)var
->ptr
) = FALSE
;
625 LogMessage(LOG_ERROR
, "Unknown boolean value %s on line %d.",
630 strncpy((char *)var
->ptr
, value
, var
->size
- 1);
631 value
[var
->size
- 1] = '\0';
642 * 'read_location()' - Read a <Location path> definition.
645 static int /* O - New line number or 0 on error */
646 read_location(FILE *fp
, /* I - Configuration file */
647 char *location
, /* I - Location name/path */
648 int linenum
) /* I - Current line number */
650 location_t
*loc
; /* New location */
651 int len
; /* Length of line */
652 char line
[HTTP_MAX_BUFFER
], /* Line buffer */
653 name
[256], /* Configuration directive */
654 *nameptr
, /* Pointer into name */
655 *value
; /* Value for directive */
656 unsigned address
, /* Address value */
657 netmask
; /* Netmask value */
658 int ip
[4], /* IP address components */
659 ipcount
, /* Number of components provided */
660 mask
[4]; /* IP netmask components */
661 static unsigned netmasks
[4] = /* Standard netmasks... */
670 if ((loc
= AddLocation(location
)) == NULL
)
673 while (fgets(line
, sizeof(line
), fp
) != NULL
)
678 * Skip comment lines...
685 * Strip trailing newline, if any...
690 if (line
[len
- 1] == '\n')
697 * Extract the name from the beginning of the line...
700 for (value
= line
; isspace(*value
); value
++);
702 for (nameptr
= name
; *value
!= '\0' && !isspace(*value
);)
703 *nameptr
++ = *value
++;
706 while (isspace(*value
))
713 * Decode the directive...
716 if (strcmp(name
, "</Location>") == 0)
718 else if (strcmp(name
, "Order") == 0)
721 * "Order Deny,Allow" or "Order Allow,Deny"...
724 if (strncasecmp(value
, "deny", 4) == 0)
725 loc
->order_type
= AUTH_ALLOW
;
726 else if (strncasecmp(value
, "allow", 5) == 0)
727 loc
->order_type
= AUTH_DENY
;
729 LogMessage(LOG_ERROR
, "Unknown Order value %s on line %d.",
732 else if (strcmp(name
, "Allow") == 0 ||
733 strcmp(name
, "Deny") == 0)
736 * Allow [From] host/ip...
737 * Deny [From] host/ip...
740 if (strncasecmp(value
, "from", 4) == 0)
743 * Strip leading "from"...
748 while (isspace(*value
))
753 * Figure out what form the allow/deny address takes:
765 * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
768 if (strcasecmp(value
, "all") == 0)
774 if (strcmp(name
, "Allow") == 0)
779 else if (strcasecmp(value
, "none") == 0)
785 if (strcmp(name
, "Allow") == 0)
790 else if (value
[0] == '*' || value
[0] == '.' || !isdigit(value
[0]))
793 * Host or domain name...
799 if (strcmp(name
, "Allow") == 0)
800 AllowHost(loc
, value
);
802 DenyHost(loc
, value
);
807 * One of many IP address forms...
810 memset(ip
, 0, sizeof(ip
));
811 ipcount
= sscanf(value
, "%d.%d.%d.%d", ip
+ 0, ip
+ 1, ip
+ 2, ip
+ 3);
812 address
= (((((ip
[0] << 8) | ip
[1]) << 8) | ip
[2]) << 8) | ip
[3];
814 if ((value
= strchr(value
, '/')) != NULL
)
817 memset(mask
, 0, sizeof(mask
));
818 switch (sscanf(value
, "%d.%d.%d.%d", mask
+ 0, mask
+ 1,
822 netmask
= (0xffffffff << (32 - mask
[0])) & 0xffffffff;
825 netmask
= (((((mask
[0] << 8) | mask
[1]) << 8) |
826 mask
[2]) << 8) | mask
[3];
829 LogMessage(LOG_ERROR
, "Bad netmask value %s on line %d.",
831 netmask
= 0xffffffff;
836 netmask
= netmasks
[ipcount
- 1];
838 if (strcmp(name
, "Allow") == 0)
839 AllowIP(loc
, address
, netmask
);
841 DenyIP(loc
, address
, netmask
);
844 else if (strcmp(name
, "AuthType") == 0)
850 if (strcasecmp(value
, "basic") != 0)
851 LogMessage(LOG_WARN
, "Unknown authorization type %s on line %d.",
854 else if (strcmp(name
, "AuthClass") == 0)
857 * AuthClass anonymous, user, system, group
860 if (strcasecmp(value
, "anonymous") == 0)
861 loc
->level
= AUTH_ANON
;
862 else if (strcasecmp(value
, "user") == 0)
863 loc
->level
= AUTH_USER
;
864 else if (strcasecmp(value
, "group") == 0)
865 loc
->level
= AUTH_GROUP
;
866 else if (strcasecmp(value
, "system") == 0)
868 loc
->level
= AUTH_GROUP
;
869 strcpy(loc
->group_name
, SystemGroup
);
872 LogMessage(LOG_WARN
, "Unknown authorization class %s on line %d.",
875 else if (strcmp(name
, "AuthGroupName") == 0)
876 strncpy(loc
->group_name
, value
, sizeof(loc
->group_name
) - 1);
878 LogMessage(LOG_ERROR
, "Unknown Location directive %s on line %d.",
887 * 'get_address()' - Get an address + port number from a line.
890 static int /* O - 1 if address good, 0 if bad */
891 get_address(char *value
, /* I - Value string */
892 unsigned defaddress
, /* I - Default address */
893 int defport
, /* I - Default port */
894 struct sockaddr_in
*address
) /* O - Socket address */
896 char hostname
[256], /* Hostname or IP */
897 portname
[256]; /* Port number or name */
898 struct hostent
*host
; /* Host address */
899 struct servent
*port
; /* Port number */
903 * Initialize the socket address to the defaults...
906 memset(address
, 0, sizeof(struct sockaddr_in
));
907 address
->sin_family
= AF_INET
;
908 address
->sin_addr
.s_addr
= htonl(defaddress
);
909 address
->sin_port
= htons(defport
);
912 * Try to grab a hostname and port number...
915 switch (sscanf(value
, "%255[^:]:%255s", hostname
, portname
))
918 if (strchr(hostname
, '.') == NULL
)
921 * Hostname is a port number...
924 strcpy(portname
, hostname
);
933 LogMessage(LOG_ERROR
, "Unable to decode address \"%s\"!", value
);
938 * Decode the hostname and port number as needed...
941 if (hostname
[0] != '\0')
943 if (isdigit(hostname
[0]))
944 address
->sin_addr
.s_addr
= inet_addr(hostname
);
947 if ((host
= gethostbyname(hostname
)) == NULL
)
949 LogMessage(LOG_ERROR
, "gethostbyname(\"%s\") failed - %s!", hostname
,
954 memcpy(&(address
->sin_addr
), host
->h_addr
, host
->h_length
);
955 address
->sin_port
= htons(defport
);
959 if (portname
[0] != '\0')
961 if (isdigit(portname
[0]))
962 address
->sin_port
= htons(atoi(portname
));
965 if ((port
= getservbyname(portname
, NULL
)) == NULL
)
967 LogMessage(LOG_ERROR
, "getservbyname(\"%s\") failed - %s!", portname
,
972 address
->sin_port
= htons(port
->s_port
);
981 * End of "$Id: conf.c,v 1.39 2000/01/04 13:46:09 mike Exp $".