2 Unix SMB/Netbios implementation.
4 Parameter loading functions
5 Copyright (C) Karl Auer 1993,1994
7 Largely re-written by Andrew Tridgell, September 1994
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * This module provides suitable callback functions for the params
28 * module. It builds the internal table of service details which is
29 * then used by the rest of the server.
33 * 1) add it to the global or service structure definition
34 * 2) add it to the parm_table
35 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
36 * 4) If it's a global then initialise it in init_globals. If a local
37 * (ie. service) parameter then initialise it in the sDefault structure
41 * The configuration file is processed sequentially for speed. It is NOT
42 * accessed randomly as happens in 'real' Windows. For this reason, there
43 * is a fair bit of sequence-dependent code here - ie., code which assumes
44 * that certain things happen before others. In particular, the code which
45 * happens at the boundary between sections is delicately poised, so be
54 extern int DEBUGLEVEL;
55 extern pstring user_socket_options;
56 extern pstring myname;
59 #define GLOBAL_NAME "global"
64 #define PRINTCAP_NAME "/etc/qconfig"
66 #define PRINTCAP_NAME "/etc/printcap"
71 #define PRINTERS_NAME "printers"
75 #define HOMES_NAME "homes"
78 /* some helpful bits */
79 #define pSERVICE(i) ServicePtrs[i]
80 #define iSERVICE(i) (*pSERVICE(i))
81 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
82 #define VALID(i) iSERVICE(i).valid
84 /* these are the types of parameter we have */
87 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
88 P_STRING,P_USTRING,P_GSTRING,P_UGSTRING
93 P_LOCAL,P_GLOBAL,P_NONE
97 extern BOOL use_getwd_cache;
99 extern int extra_time_offset;
101 extern int coding_system;
105 * This structure describes global (ie., server-wide) parameters.
109 char *szPrintcapname;
112 char *szDefaultService;
116 char *szServerString;
117 char *szAutoServices;
118 char *szPasswdProgram;
122 char *szSMBPasswdFile;
123 char *szPasswordServer;
124 char *szSocketOptions;
127 char *szDomainController;
129 char *szCharacterSet;
134 char *szRemoteAnnounce;
135 char *szSocketAddress;
154 BOOL bPreferredMaster;
157 BOOL bEncryptPasswords;
164 BOOL bReadPrediction;
170 static global Globals;
175 * This structure describes a single service.
183 char *szGuestaccount;
184 char *szInvalidUsers;
192 char *szRootPostExec;
193 char *szPrintcommand;
196 char *szLppausecommand;
197 char *szLpresumecommand;
199 char *szPrinterDriver;
220 BOOL bShortCasePreserve;
244 BOOL bDeleteReadonly;
246 char dummy[3]; /* for alignment */
250 /* This is a default service used to prime a services structure */
251 static service sDefault =
254 NULL, /* szService */
256 NULL, /* szUsername */
257 NULL, /* szGuestAccount */
258 NULL, /* szInvalidUsers */
259 NULL, /* szValidUsers */
260 NULL, /* szAdminUsers */
262 NULL, /* szInclude */
263 NULL, /* szPreExec */
264 NULL, /* szPostExec */
265 NULL, /* szRootPreExec */
266 NULL, /* szRootPostExec */
267 NULL, /* szPrintcommand */
268 NULL, /* szLpqcommand */
269 NULL, /* szLprmcommand */
270 NULL, /* szLppausecommand */
271 NULL, /* szLpresumecommand */
272 NULL, /* szPrintername */
273 NULL, /* szPrinterDriver */
274 NULL, /* szDontdescend */
275 NULL, /* szHostsallow */
276 NULL, /* szHostsdeny */
277 NULL, /* szMagicScript */
278 NULL, /* szMagicOutput */
279 NULL, /* szMangledMap */
281 NULL, /* force user */
282 NULL, /* force group */
284 NULL, /* writelist */
286 0, /* iMinPrintSpace */
287 0755, /* iCreate_mode */
288 0, /* iMaxConnections */
289 CASE_LOWER, /* iDefaultCase */
290 False, /* bAlternatePerm */
291 False, /* revalidate */
292 False, /* case sensitive */
293 False, /* case preserve */
294 False, /* short case preserve */
295 False, /* case mangle */
297 True, /* bHideDotFiles */
298 True, /* bBrowseable */
299 True, /* bAvailable */
300 True, /* bRead_only */
301 True, /* bNo_set_dir */
302 False, /* bGuest_only */
303 False, /* bGuest_ok */
304 False, /* bPrint_ok */
305 False, /* bPostscript */
306 False, /* bMap_system */
307 False, /* bMap_hidden */
308 True, /* bMap_archive */
310 False, /* bStrictLocking */
311 True, /* bShareModes */
312 False, /* bOnlyUser */
313 True, /* bMangledNames */
314 True, /* bWidelinks */
315 False, /* bSyncAlways */
316 '~', /* magic char */
318 False, /* bDeleteReadonly */
319 False, /* bFakeOplocks */
325 /* local variables */
326 static service **ServicePtrs = NULL;
327 static int iNumServices = 0;
328 static int iServiceIndex = 0;
329 static BOOL bInGlobalSection = True;
330 static BOOL bGlobalOnly = False;
333 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
335 /* prototypes for the special type handlers */
336 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
337 static BOOL handle_include(char *pszParmValue, char **ptr);
338 static BOOL handle_copy(char *pszParmValue, char **ptr);
339 static BOOL handle_protocol(char *pszParmValue,int *val);
340 static BOOL handle_security(char *pszParmValue,int *val);
341 static BOOL handle_case(char *pszParmValue,int *val);
342 static BOOL handle_printing(char *pszParmValue,int *val);
343 static BOOL handle_character_set(char *pszParmValue,int *val);
345 static BOOL handle_coding_system(char *pszParmValue,int *val);
357 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
358 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
359 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
360 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
361 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
362 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
363 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
364 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
365 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
366 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
367 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
368 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
369 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
370 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
371 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
372 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
373 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
374 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
375 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
376 {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
377 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
378 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
379 {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL},
380 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
381 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
382 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
383 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
384 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
385 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
386 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
387 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
388 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
389 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
390 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
391 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
392 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
393 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
394 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
395 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
396 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
397 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
398 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
399 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
400 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
401 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
402 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
403 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
404 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
405 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
406 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
407 {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL},
408 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL},
409 {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
410 {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
411 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
412 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
413 {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
414 {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
415 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
416 {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
417 {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
418 {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
419 {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
421 {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
423 {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
424 {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
425 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
426 {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
427 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
428 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
429 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
430 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
431 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
432 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
434 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
435 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
436 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
437 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
438 {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
439 {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
440 {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
441 {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
442 {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
443 {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
444 {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
445 {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
446 {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
447 {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
448 {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
449 {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
450 {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
451 {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
452 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
453 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
454 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
455 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
456 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
457 {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
458 {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
459 {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
460 {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
461 {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
462 {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
463 {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
464 {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
465 {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
466 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
467 {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
468 {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
469 {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
470 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
471 {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
472 {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
473 {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
474 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
475 {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
476 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
477 {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
478 {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
479 {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
480 {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
481 {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
482 {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
483 {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
484 {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
485 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
486 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
487 {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
488 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
489 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
490 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
491 {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
492 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
493 {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
494 {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
495 {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
496 {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
497 {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
498 {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL},
499 {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
500 {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
501 {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
502 {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
503 {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
504 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
505 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
506 {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL},
507 {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
508 {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
509 {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
510 {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
511 {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
512 {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
513 {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
514 {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
515 {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
517 {NULL, P_BOOL, P_NONE, NULL, NULL}
522 /***************************************************************************
523 Initialise the global parameter structure.
524 ***************************************************************************/
525 static void init_globals(void)
527 static BOOL done_init = False;
533 bzero((void *)&Globals,sizeof(Globals));
535 for (i = 0; parm_table[i].label; i++)
536 if ((parm_table[i].type == P_STRING ||
537 parm_table[i].type == P_USTRING) &&
539 string_init(parm_table[i].ptr,"");
541 string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
547 DEBUG(3,("Initialising global parameters\n"));
549 #ifdef SMB_PASSWD_FILE
550 string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
552 string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
553 string_set(&Globals.szWorkGroup, WORKGROUP);
555 string_set(&Globals.szPasswdProgram, SMB_PASSWD);
557 string_set(&Globals.szPasswdProgram, "/bin/passwd");
559 string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
560 string_set(&Globals.szLockDir, LOCKDIR);
561 string_set(&Globals.szRootdir, "/");
562 string_set(&Globals.szSmbrun, SMBRUN);
563 string_set(&Globals.szSocketAddress, "0.0.0.0");
564 sprintf(s,"Samba %s",VERSION);
565 string_set(&Globals.szServerString,s);
566 Globals.bLoadPrinters = True;
567 Globals.bUseRhosts = False;
568 Globals.max_packet = 65535;
569 Globals.mangled_stack = 50;
570 Globals.max_xmit = Globals.max_packet;
572 Globals.lpqcachetime = 10;
573 Globals.pwordlevel = 0;
574 Globals.deadtime = 0;
575 Globals.max_log_size = 5000;
576 Globals.maxprotocol = PROTOCOL_NT1;
577 Globals.security = SEC_SHARE;
578 Globals.bEncryptPasswords = False;
579 Globals.printing = DEFAULT_PRINTING;
580 Globals.bReadRaw = True;
581 Globals.bWriteRaw = True;
582 Globals.bReadPrediction = False;
583 Globals.bReadbmpx = True;
584 Globals.bNullPasswords = False;
585 Globals.bStripDot = False;
587 Globals.bSyslogOnly = False;
588 Globals.os_level = 0;
589 Globals.max_ttl = 60*60*4; /* 2 hours default */
590 Globals.bPreferredMaster = True;
591 Globals.bDomainMaster = False;
592 Globals.bDomainLogons = False;
593 Globals.bBrowseList = True;
594 Globals.bWINSsupport = True;
595 Globals.bWINSproxy = False;
596 Globals.ReadSize = 16*1024;
599 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
604 /***************************************************************************
605 check if a string is initialised and if not then initialise it
606 ***************************************************************************/
607 static void string_initial(char **s,char *v)
614 /***************************************************************************
615 Initialise the sDefault parameter structure.
616 ***************************************************************************/
617 static void init_locals(void)
619 /* choose defaults depending on the type of printing */
620 switch (Globals.printing)
626 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
627 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
628 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
633 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
634 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
635 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
637 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
638 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
643 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
644 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
645 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
653 /******************************************************************* a
654 convenience routine to grab string parameters into a rotating buffer,
655 and run standard_sub_basic on them. The buffers can be written to by
656 callers without affecting the source string.
657 ********************************************************************/
658 char *lp_string(char *s)
660 static char *bufs[10];
661 static int buflen[10];
662 static int next = -1;
665 int len = s?strlen(s):0;
676 len = MAX(len+100,sizeof(pstring)); /* the +100 is for some
679 if (buflen[next] != len) {
681 if (bufs[next]) free(bufs[next]);
682 bufs[next] = (char *)malloc(len);
684 DEBUG(0,("out of memory in lp_string()"));
689 ret = &bufs[next][0];
697 standard_sub_basic(ret);
703 In this section all the functions that are used to access the
704 parameters from the rest of the program are defined
707 #define FN_GLOBAL_STRING(fn_name,ptr) \
708 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
709 #define FN_GLOBAL_BOOL(fn_name,ptr) \
710 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
711 #define FN_GLOBAL_CHAR(fn_name,ptr) \
712 char fn_name(void) {return(*(char *)(ptr));}
713 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
714 int fn_name(void) {return(*(int *)(ptr));}
716 #define FN_LOCAL_STRING(fn_name,val) \
717 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
718 #define FN_LOCAL_BOOL(fn_name,val) \
719 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
720 #define FN_LOCAL_CHAR(fn_name,val) \
721 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
722 #define FN_LOCAL_INTEGER(fn_name,val) \
723 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
725 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
726 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
727 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
728 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
729 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
730 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
731 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
732 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
733 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
734 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
735 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
736 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
737 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
738 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
739 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
740 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
741 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
742 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
743 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
744 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
745 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
746 FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce)
747 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
748 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
749 FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
751 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
752 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
753 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
754 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
755 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
756 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
757 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
758 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
759 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
760 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
761 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
762 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
763 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
764 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
765 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
766 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
767 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
769 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
770 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
771 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
772 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
773 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
774 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
775 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
776 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
777 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
778 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
779 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
780 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
781 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
782 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
783 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
784 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
785 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
787 FN_LOCAL_STRING(lp_preexec,szPreExec)
788 FN_LOCAL_STRING(lp_postexec,szPostExec)
789 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
790 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
791 FN_LOCAL_STRING(lp_servicename,szService)
792 FN_LOCAL_STRING(lp_pathname,szPath)
793 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
794 FN_LOCAL_STRING(lp_username,szUsername)
795 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
796 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
797 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
798 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
799 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
800 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
801 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
802 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
803 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
804 FN_LOCAL_STRING(lp_printername,szPrintername)
805 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
806 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
807 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
808 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
809 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
810 FN_LOCAL_STRING(lp_comment,comment)
811 FN_LOCAL_STRING(lp_force_user,force_user)
812 FN_LOCAL_STRING(lp_force_group,force_group)
813 FN_LOCAL_STRING(lp_readlist,readlist)
814 FN_LOCAL_STRING(lp_writelist,writelist)
815 FN_LOCAL_STRING(lp_volume,volume)
816 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
818 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
819 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
820 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
821 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
822 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
823 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
824 FN_LOCAL_BOOL(lp_status,status)
825 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
826 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
827 FN_LOCAL_BOOL(lp_readonly,bRead_only)
828 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
829 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
830 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
831 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
832 FN_LOCAL_BOOL(lp_postscript,bPostscript)
833 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
834 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
835 FN_LOCAL_BOOL(lp_locking,bLocking)
836 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
837 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
838 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
839 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
840 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
841 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
842 FN_LOCAL_BOOL(lp_map_system,bMap_system)
843 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
844 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
846 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
847 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
848 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
849 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
851 FN_LOCAL_CHAR(lp_magicchar,magic_char)
855 /* local prototypes */
856 static int strwicmp( char *psz1, char *psz2 );
857 static int map_parameter( char *pszParmName);
858 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
859 static int getservicebyname(char *pszServiceName, service *pserviceDest);
860 static void copy_service( service *pserviceDest,
861 service *pserviceSource,
862 BOOL *pcopymapDest );
863 static BOOL service_ok(int iService);
864 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
865 static BOOL do_section(char *pszSectionName);
866 static void dump_globals(void);
867 static void dump_a_service(service *pService);
868 static void init_copymap(service *pservice);
871 /***************************************************************************
872 initialise a service to the defaults
873 ***************************************************************************/
874 static void init_service(service *pservice)
876 bzero((char *)pservice,sizeof(service));
877 copy_service(pservice,&sDefault,NULL);
881 /***************************************************************************
882 free the dynamically allocated parts of a service struct
883 ***************************************************************************/
884 static void free_service(service *pservice)
890 for (i=0;parm_table[i].label;i++)
891 if ((parm_table[i].type == P_STRING ||
892 parm_table[i].type == P_STRING) &&
893 parm_table[i].class == P_LOCAL)
894 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
897 /***************************************************************************
898 add a new service to the services array initialising it with the given
900 ***************************************************************************/
901 static int add_a_service(service *pservice, char *name)
905 int num_to_alloc = iNumServices+1;
907 tservice = *pservice;
909 /* it might already exist */
912 i = getservicebyname(name,NULL);
917 /* find an invalid one */
918 for (i=0;i<iNumServices;i++)
919 if (!pSERVICE(i)->valid)
922 /* if not, then create one */
923 if (i == iNumServices)
925 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
927 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
929 if (!ServicePtrs || !pSERVICE(iNumServices))
935 free_service(pSERVICE(i));
937 pSERVICE(i)->valid = True;
939 init_service(pSERVICE(i));
940 copy_service(pSERVICE(i),&tservice,NULL);
942 string_set(&iSERVICE(i).szService,name);
947 /***************************************************************************
948 add a new home service, with the specified home directory, defaults coming
950 ***************************************************************************/
951 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
953 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
958 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
959 string_set(&iSERVICE(i).szPath,pszHomedir);
960 if (!(*(iSERVICE(i).comment)))
963 sprintf(comment,"Home directory of %s",pszHomename);
964 string_set(&iSERVICE(i).comment,comment);
966 iSERVICE(i).bAvailable = sDefault.bAvailable;
967 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
969 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
974 /***************************************************************************
975 add a new service, based on an old one
976 ***************************************************************************/
977 int lp_add_service(char *pszService, int iDefaultService)
979 return(add_a_service(pSERVICE(iDefaultService),pszService));
983 /***************************************************************************
985 ***************************************************************************/
986 static BOOL lp_add_ipc(void)
989 int i = add_a_service(&sDefault,"IPC$");
994 sprintf(comment,"IPC Service (%s)",lp_serverstring());
996 string_set(&iSERVICE(i).szPath,"/tmp");
997 string_set(&iSERVICE(i).szUsername,"");
998 string_set(&iSERVICE(i).comment,comment);
999 iSERVICE(i).status = False;
1000 iSERVICE(i).iMaxConnections = 0;
1001 iSERVICE(i).bAvailable = True;
1002 iSERVICE(i).bRead_only = True;
1003 iSERVICE(i).bGuest_only = False;
1004 iSERVICE(i).bGuest_ok = True;
1005 iSERVICE(i).bPrint_ok = False;
1006 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1008 DEBUG(3,("adding IPC service\n"));
1014 /***************************************************************************
1015 add a new printer service, with defaults coming from service iFrom
1016 ***************************************************************************/
1017 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1019 char *comment = "From Printcap";
1020 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1025 /* note that we do NOT default the availability flag to True - */
1026 /* we take it from the default service passed. This allows all */
1027 /* dynamic printers to be disabled by disabling the [printers] */
1028 /* entry (if/when the 'available' keyword is implemented!). */
1030 /* the printer name is set to the service name. */
1031 string_set(&iSERVICE(i).szPrintername,pszPrintername);
1032 string_set(&iSERVICE(i).comment,comment);
1033 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1035 DEBUG(3,("adding printer service %s\n",pszPrintername));
1041 /***************************************************************************
1042 Do a case-insensitive, whitespace-ignoring string compare.
1043 ***************************************************************************/
1044 static int strwicmp(char *psz1, char *psz2)
1046 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1047 /* appropriate value. */
1057 /* sync the strings on first non-whitespace */
1060 while (isspace(*psz1))
1062 while (isspace(*psz2))
1064 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1069 return (*psz1 - *psz2);
1072 /***************************************************************************
1073 Map a parameter's string representation to something we can use.
1074 Returns False if the parameter string is not recognised, else TRUE.
1075 ***************************************************************************/
1076 static int map_parameter(char *pszParmName)
1080 if (*pszParmName == '-')
1083 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1084 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1087 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1092 /***************************************************************************
1093 Set a boolean variable from the text value stored in the passed string.
1094 Returns True in success, False if the passed string does not correctly
1095 represent a boolean.
1096 ***************************************************************************/
1097 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1102 if (strwicmp(pszParmValue, "yes") == 0 ||
1103 strwicmp(pszParmValue, "true") == 0 ||
1104 strwicmp(pszParmValue, "1") == 0)
1107 if (strwicmp(pszParmValue, "no") == 0 ||
1108 strwicmp(pszParmValue, "False") == 0 ||
1109 strwicmp(pszParmValue, "0") == 0)
1113 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1120 /***************************************************************************
1121 Find a service by name. Otherwise works like get_service.
1122 ***************************************************************************/
1123 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1127 for (iService = iNumServices - 1; iService >= 0; iService--)
1128 if (VALID(iService) &&
1129 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1131 if (pserviceDest != NULL)
1132 copy_service(pserviceDest, pSERVICE(iService), NULL);
1141 /***************************************************************************
1142 Copy a service structure to another
1144 If pcopymapDest is NULL then copy all fields
1145 ***************************************************************************/
1146 static void copy_service(service *pserviceDest,
1147 service *pserviceSource,
1151 BOOL bcopyall = (pcopymapDest == NULL);
1153 for (i=0;parm_table[i].label;i++)
1154 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1155 (bcopyall || pcopymapDest[i]))
1157 void *def_ptr = parm_table[i].ptr;
1159 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1161 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1163 switch (parm_table[i].type)
1167 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1172 *(int *)dest_ptr = *(int *)src_ptr;
1176 *(char *)dest_ptr = *(char *)src_ptr;
1180 string_set(dest_ptr,*(char **)src_ptr);
1184 string_set(dest_ptr,*(char **)src_ptr);
1185 strupper(*(char **)dest_ptr);
1194 init_copymap(pserviceDest);
1195 if (pserviceSource->copymap)
1196 memcpy((void *)pserviceDest->copymap,
1197 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1201 /***************************************************************************
1202 Check a service for consistency. Return False if the service is in any way
1203 incomplete or faulty, else True.
1204 ***************************************************************************/
1205 static BOOL service_ok(int iService)
1210 if (iSERVICE(iService).szService[0] == '\0')
1212 DEBUG(0,( "The following message indicates an internal error:\n"));
1213 DEBUG(0,( "No service name in service entry.\n"));
1217 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1218 /* I can't see why you'd want a non-printable printer service... */
1219 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1220 if (!iSERVICE(iService).bPrint_ok)
1222 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1223 iSERVICE(iService).szService));
1224 iSERVICE(iService).bPrint_ok = True;
1227 if (iSERVICE(iService).szPath[0] == '\0' &&
1228 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1230 DEBUG(0,("No path in service %s - using /tmp\n",iSERVICE(iService).szService));
1231 string_set(&iSERVICE(iService).szPath,"/tmp");
1234 /* If a service is flagged unavailable, log the fact at level 0. */
1235 if (!iSERVICE(iService).bAvailable)
1236 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1237 iSERVICE(iService).szService));
1242 static struct file_lists {
1243 struct file_lists *next;
1246 } *file_lists = NULL;
1248 /*******************************************************************
1249 keep a linked list of all config files so we know when one has changed
1250 it's date and needs to be reloaded
1251 ********************************************************************/
1252 static void add_to_file_list(char *fname)
1254 struct file_lists *f=file_lists;
1257 if (f->name && !strcmp(f->name,fname)) break;
1262 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1264 f->next = file_lists;
1265 f->name = strdup(fname);
1276 standard_sub_basic(n2);
1277 f->modtime = file_modtime(n2);
1282 /*******************************************************************
1283 check if a config file has changed date
1284 ********************************************************************/
1285 BOOL lp_file_list_changed(void)
1287 struct file_lists *f = file_lists;
1291 standard_sub_basic(n2);
1292 if (f->modtime != file_modtime(n2)) return(True);
1299 /***************************************************************************
1300 handle the interpretation of the coding system parameter
1301 *************************************************************************/
1302 static BOOL handle_coding_system(char *pszParmValue,int *val)
1304 *val = interpret_coding_system(pszParmValue,*val);
1309 /***************************************************************************
1310 handle the interpretation of the character set system parameter
1311 ***************************************************************************/
1312 static BOOL handle_character_set(char *pszParmValue,int *val)
1314 string_set(&Globals.szCharacterSet,pszParmValue);
1315 *val = interpret_character_set(pszParmValue,*val);
1320 /***************************************************************************
1321 handle the interpretation of the protocol parameter
1322 ***************************************************************************/
1323 static BOOL handle_protocol(char *pszParmValue,int *val)
1325 *val = interpret_protocol(pszParmValue,*val);
1329 /***************************************************************************
1330 handle the interpretation of the security parameter
1331 ***************************************************************************/
1332 static BOOL handle_security(char *pszParmValue,int *val)
1334 *val = interpret_security(pszParmValue,*val);
1338 /***************************************************************************
1339 handle the interpretation of the default case
1340 ***************************************************************************/
1341 static BOOL handle_case(char *pszParmValue,int *val)
1343 if (strequal(pszParmValue,"LOWER"))
1345 else if (strequal(pszParmValue,"UPPER"))
1350 /***************************************************************************
1351 handle the interpretation of the printing system
1352 ***************************************************************************/
1353 static BOOL handle_printing(char *pszParmValue,int *val)
1355 if (strequal(pszParmValue,"sysv"))
1357 else if (strequal(pszParmValue,"aix"))
1359 else if (strequal(pszParmValue,"hpux"))
1361 else if (strequal(pszParmValue,"bsd"))
1363 else if (strequal(pszParmValue,"qnx"))
1365 else if (strequal(pszParmValue,"plp"))
1367 else if (strequal(pszParmValue,"lprng"))
1372 /***************************************************************************
1373 handle the valid chars lines
1374 ***************************************************************************/
1375 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1377 string_set(ptr,pszParmValue);
1379 add_char_string(pszParmValue);
1384 /***************************************************************************
1385 handle the include operation
1386 ***************************************************************************/
1387 static BOOL handle_include(char *pszParmValue,char **ptr)
1390 strcpy(fname,pszParmValue);
1392 add_to_file_list(fname);
1394 standard_sub_basic(fname);
1396 string_set(ptr,fname);
1398 if (file_exist(fname,NULL))
1399 return(pm_process(fname, do_section, do_parameter));
1401 DEBUG(2,("Can't find include file %s\n",fname));
1407 /***************************************************************************
1408 handle the interpretation of the copy parameter
1409 ***************************************************************************/
1410 static BOOL handle_copy(char *pszParmValue,char **ptr)
1414 service serviceTemp;
1416 string_set(ptr,pszParmValue);
1418 init_service(&serviceTemp);
1422 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1424 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1426 if (iTemp == iServiceIndex)
1428 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1433 copy_service(pSERVICE(iServiceIndex),
1435 iSERVICE(iServiceIndex).copymap);
1441 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1446 free_service(&serviceTemp);
1451 /***************************************************************************
1452 initialise a copymap
1453 ***************************************************************************/
1454 static void init_copymap(service *pservice)
1457 if (pservice->copymap) free(pservice->copymap);
1458 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1459 if (!pservice->copymap)
1460 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1462 for (i=0;i<NUMPARAMETERS;i++)
1463 pservice->copymap[i] = True;
1467 /***************************************************************************
1468 Process a parameter.
1469 ***************************************************************************/
1470 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1473 void *parm_ptr=NULL; /* where we are going to store the result */
1476 if (!bInGlobalSection && bGlobalOnly) return(True);
1478 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1480 parmnum = map_parameter(pszParmName);
1484 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1488 def_ptr = parm_table[parmnum].ptr;
1490 /* we might point at a service, the default service or a global */
1491 if (bInGlobalSection)
1495 if (parm_table[parmnum].class == P_GLOBAL)
1497 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1500 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1503 if (!bInGlobalSection)
1506 if (!iSERVICE(iServiceIndex).copymap)
1507 init_copymap(pSERVICE(iServiceIndex));
1509 /* this handles the aliases - set the copymap for other entries with
1510 the same data pointer */
1511 for (i=0;parm_table[i].label;i++)
1512 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1513 iSERVICE(iServiceIndex).copymap[i] = False;
1516 /* if it is a special case then go ahead */
1517 if (parm_table[parmnum].special)
1519 parm_table[parmnum].special(pszParmValue,parm_ptr);
1523 /* now switch on the type of variable it is */
1524 switch (parm_table[parmnum].type)
1527 set_boolean(parm_ptr,pszParmValue);
1531 set_boolean(parm_ptr,pszParmValue);
1532 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1536 *(int *)parm_ptr = atoi(pszParmValue);
1540 *(char *)parm_ptr = *pszParmValue;
1544 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1548 string_set(parm_ptr,pszParmValue);
1552 string_set(parm_ptr,pszParmValue);
1553 strupper(*(char **)parm_ptr);
1557 strcpy((char *)parm_ptr,pszParmValue);
1561 strcpy((char *)parm_ptr,pszParmValue);
1562 strupper((char *)parm_ptr);
1569 /***************************************************************************
1570 print a parameter of the specified type
1571 ***************************************************************************/
1572 static void print_parameter(parm_type type,void *ptr)
1577 printf("%s",BOOLSTR(*(BOOL *)ptr));
1581 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1585 printf("%d",*(int *)ptr);
1589 printf("%c",*(char *)ptr);
1593 printf("0%o",*(int *)ptr);
1599 printf("%s",(char *)ptr);
1605 printf("%s",*(char **)ptr);
1611 /***************************************************************************
1612 check if two parameters are equal
1613 ***************************************************************************/
1614 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1620 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1624 return(*((int *)ptr1) == *((int *)ptr2));
1627 return(*((char *)ptr1) == *((char *)ptr2));
1632 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1633 if (p1 && !*p1) p1 = NULL;
1634 if (p2 && !*p2) p2 = NULL;
1635 return(p1==p2 || strequal(p1,p2));
1640 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1641 if (p1 && !*p1) p1 = NULL;
1642 if (p2 && !*p2) p2 = NULL;
1643 return(p1==p2 || strequal(p1,p2));
1649 /***************************************************************************
1650 Process a new section (service). At this stage all sections are services.
1651 Later we'll have special sections that permit server parameters to be set.
1652 Returns True on success, False on failure.
1653 ***************************************************************************/
1654 static BOOL do_section(char *pszSectionName)
1657 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1658 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1661 /* if we were in a global section then do the local inits */
1662 if (bInGlobalSection && !isglobal)
1665 /* if we've just struck a global section, note the fact. */
1666 bInGlobalSection = isglobal;
1668 /* check for multiple global sections */
1669 if (bInGlobalSection)
1671 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1675 if (!bInGlobalSection && bGlobalOnly) return(True);
1677 /* if we have a current service, tidy it up before moving on */
1680 if (iServiceIndex >= 0)
1681 bRetval = service_ok(iServiceIndex);
1683 /* if all is still well, move to the next record in the services array */
1686 /* We put this here to avoid an odd message order if messages are */
1687 /* issued by the post-processing of a previous section. */
1688 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1690 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1692 DEBUG(0,("Failed to add a new service\n"));
1700 /***************************************************************************
1701 Display the contents of the global structure.
1702 ***************************************************************************/
1703 static void dump_globals(void)
1706 printf("Global parameters:\n");
1708 for (i=0;parm_table[i].label;i++)
1709 if (parm_table[i].class == P_GLOBAL &&
1710 parm_table[i].ptr &&
1711 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1713 printf("\t%s: ",parm_table[i].label);
1714 print_parameter(parm_table[i].type,parm_table[i].ptr);
1719 /***************************************************************************
1720 Display the contents of a single services record.
1721 ***************************************************************************/
1722 static void dump_a_service(service *pService)
1725 if (pService == &sDefault)
1726 printf("\nDefault service parameters:\n");
1728 printf("\nService parameters [%s]:\n",pService->szService);
1730 for (i=0;parm_table[i].label;i++)
1731 if (parm_table[i].class == P_LOCAL &&
1732 parm_table[i].ptr &&
1733 (*parm_table[i].label != '-') &&
1734 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1736 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1738 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1739 ((char *)pService) + pdiff,
1740 ((char *)&sDefault) + pdiff))
1742 printf("\t%s: ",parm_table[i].label);
1743 print_parameter(parm_table[i].type,
1744 ((char *)pService) + pdiff);
1751 /***************************************************************************
1752 Display the contents of a single copy structure.
1753 ***************************************************************************/
1754 static void dump_copy_map(BOOL *pcopymap)
1757 if (!pcopymap) return;
1759 printf("\n\tNon-Copied parameters:\n");
1761 for (i=0;parm_table[i].label;i++)
1762 if (parm_table[i].class == P_LOCAL &&
1763 parm_table[i].ptr && !pcopymap[i] &&
1764 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1766 printf("\t\t%s\n",parm_table[i].label);
1771 /***************************************************************************
1772 Return TRUE if the passed service number is within range.
1773 ***************************************************************************/
1774 BOOL lp_snum_ok(int iService)
1776 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1780 /***************************************************************************
1781 auto-load some homes and printer services
1782 ***************************************************************************/
1783 static void lp_add_auto_services(char *str)
1787 int homes = lp_servicenumber(HOMES_NAME);
1788 int printers = lp_servicenumber(PRINTERS_NAME);
1796 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1798 char *home = get_home_dir(p);
1800 if (lp_servicenumber(p) >= 0) continue;
1802 if (home && homes >= 0)
1804 lp_add_home(p,homes,home);
1808 if (printers >= 0 && pcap_printername_ok(p,NULL))
1809 lp_add_printer(p,printers);
1814 /***************************************************************************
1815 auto-load one printer
1816 ***************************************************************************/
1817 static void lp_add_one_printer(char *name,char *comment)
1819 int printers = lp_servicenumber(PRINTERS_NAME);
1822 if (lp_servicenumber(name) < 0)
1824 lp_add_printer(name,printers);
1825 if ((i=lp_servicenumber(name)) >= 0)
1826 string_set(&iSERVICE(i).comment,comment);
1831 /***************************************************************************
1832 auto-load printer services
1833 ***************************************************************************/
1834 static void lp_add_all_printers(void)
1836 int printers = lp_servicenumber(PRINTERS_NAME);
1838 if (printers < 0) return;
1840 pcap_printer_fn(lp_add_one_printer);
1843 /***************************************************************************
1844 have we loaded a services file yet?
1845 ***************************************************************************/
1846 BOOL lp_loaded(void)
1851 /***************************************************************************
1852 unload unused services
1853 ***************************************************************************/
1854 void lp_killunused(BOOL (*snumused)(int ))
1857 for (i=0;i<iNumServices;i++)
1858 if (VALID(i) && !snumused(i))
1860 iSERVICE(i).valid = False;
1861 free_service(pSERVICE(i));
1865 /***************************************************************************
1866 Load the services array from the services file. Return True on success,
1868 ***************************************************************************/
1869 BOOL lp_load(char *pszFname,BOOL global_only)
1874 add_to_file_list(pszFname);
1878 bInGlobalSection = True;
1879 bGlobalOnly = global_only;
1883 strcpy(n2,pszFname);
1884 standard_sub_basic(n2);
1886 /* We get sections first, so have to start 'behind' to make up */
1888 bRetval = pm_process(n2, do_section, do_parameter);
1890 /* finish up the last section */
1891 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1893 if (iServiceIndex >= 0)
1894 bRetval = service_ok(iServiceIndex);
1896 lp_add_auto_services(lp_auto_services());
1897 if (lp_load_printers())
1898 lp_add_all_printers();
1908 /***************************************************************************
1909 return the max number of services
1910 ***************************************************************************/
1911 int lp_numservices(void)
1913 return(iNumServices);
1916 /***************************************************************************
1917 Display the contents of the services array in human-readable form.
1918 ***************************************************************************/
1925 dump_a_service(&sDefault);
1927 for (iService = 0; iService < iNumServices; iService++)
1929 if (VALID(iService))
1931 if (iSERVICE(iService).szService[0] == '\0')
1933 dump_a_service(pSERVICE(iService));
1938 /***************************************************************************
1939 Return the number of the service with the given name, or -1 if it doesn't
1940 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1941 getservicebyname()! This works ONLY if all services have been loaded, and
1942 does not copy the found service.
1943 ***************************************************************************/
1944 int lp_servicenumber(char *pszServiceName)
1948 for (iService = iNumServices - 1; iService >= 0; iService--)
1949 if (VALID(iService) &&
1950 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1954 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1959 /*******************************************************************
1960 a useful volume label function
1961 ******************************************************************/
1962 char *volume_label(int snum)
1964 char *ret = lp_volume(snum);
1965 if (!*ret) return(lp_servicename(snum));