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
58 extern int DEBUGLEVEL;
60 extern pstring user_socket_options;
63 #define GLOBAL_NAME "global"
68 #define PRINTCAP_NAME "/etc/qconfig"
70 #define PRINTCAP_NAME "/etc/printcap"
75 #define PRINTERS_NAME "printers"
79 #define HOMES_NAME "homes"
82 /* some helpful bits */
83 #define pSERVICE(i) ServicePtrs[i]
84 #define iSERVICE(i) (*pSERVICE(i))
85 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
86 #define VALID(i) iSERVICE(i).valid
88 /* these are the types of parameter we have */
91 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_STRING,P_GSTRING
96 P_LOCAL,P_GLOBAL,P_NONE
100 extern BOOL use_getwd_cache;
102 extern int extra_time_offset;
104 extern int coding_system;
108 * This structure describes global (ie., server-wide) parameters.
112 char *szPrintcapname;
115 char *szDefaultService;
119 char *szServerString;
120 char *szAutoServices;
121 char *szPasswdProgram;
125 char *szSMBPasswdFile;
126 char *szPasswordServer;
127 char *szSocketOptions;
130 char *szDomainController;
132 char *szCharacterSet;
153 BOOL bPreferredMaster;
156 BOOL bEncryptPasswords;
163 BOOL bReadPrediction;
169 static global Globals;
174 * This structure describes a single service.
182 char *szGuestaccount;
183 char *szInvalidUsers;
191 char *szRootPostExec;
192 char *szPrintcommand;
195 char *szLppausecommand;
196 char *szLpresumecommand;
218 BOOL bShortCasePreserve;
242 BOOL bDeleteReadonly;
243 char dummy[3]; /* for alignment */
247 /* This is a default service used to prime a services structure */
248 static service sDefault =
251 NULL, /* szService */
253 NULL, /* szUsername */
254 NULL, /* szGuestAccount */
255 NULL, /* szInvalidUsers */
256 NULL, /* szValidUsers */
257 NULL, /* szAdminUsers */
259 NULL, /* szInclude */
260 NULL, /* szPreExec */
261 NULL, /* szPostExec */
262 NULL, /* szRootPreExec */
263 NULL, /* szRootPostExec */
264 NULL, /* szPrintcommand */
265 NULL, /* szLpqcommand */
266 NULL, /* szLprmcommand */
267 NULL, /* szLppausecommand */
268 NULL, /* szLpresumecommand */
269 NULL, /* szPrintername */
270 NULL, /* szDontdescend */
271 NULL, /* szHostsallow */
272 NULL, /* szHostsdeny */
273 NULL, /* szMagicScript */
274 NULL, /* szMagicOutput */
275 NULL, /* szMangledMap */
277 NULL, /* force user */
278 NULL, /* force group */
280 NULL, /* writelist */
282 0, /* iMinPrintSpace */
283 0755, /* iCreate_mode */
284 0, /* iMaxConnections */
285 CASE_LOWER, /* iDefaultCase */
286 False, /* bAlternatePerm */
287 False, /* revalidate */
288 False, /* case sensitive */
289 False, /* case preserve */
290 False, /* short case preserve */
291 False, /* case mangle */
293 True, /* bHideDotFiles */
294 True, /* bBrowseable */
295 True, /* bAvailable */
296 True, /* bRead_only */
297 True, /* bNo_set_dir */
298 False, /* bGuest_only */
299 False, /* bGuest_ok */
300 False, /* bPrint_ok */
301 False, /* bPostscript */
302 False, /* bMap_system */
303 False, /* bMap_hidden */
304 True, /* bMap_archive */
306 False, /* bStrictLocking */
307 True, /* bShareModes */
308 False, /* bOnlyUser */
309 True, /* bMangledNames */
310 True, /* bWidelinks */
311 False, /* bSyncAlways */
312 '~', /* magic char */
314 False, /* bDeleteReadonly */
320 /* local variables */
321 static service **ServicePtrs = NULL;
322 static int iNumServices = 0;
323 static int iServiceIndex = 0;
324 static BOOL bInGlobalSection = True;
325 static BOOL bGlobalOnly = False;
328 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
330 /* prototypes for the special type handlers */
331 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
332 static BOOL handle_include(char *pszParmValue, char **ptr);
333 static BOOL handle_copy(char *pszParmValue, char **ptr);
334 static BOOL handle_protocol(char *pszParmValue,int *val);
335 static BOOL handle_security(char *pszParmValue,int *val);
336 static BOOL handle_case(char *pszParmValue,int *val);
337 static BOOL handle_printing(char *pszParmValue,int *val);
338 static BOOL handle_character_set(char *pszParmValue,int *val);
340 static BOOL handle_coding_system(char *pszParmValue,int *val);
352 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
353 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
354 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
355 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
356 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
357 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
358 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
359 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
360 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
361 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
362 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
363 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
364 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
365 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
366 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
367 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
368 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
369 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
370 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
371 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
372 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
373 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
374 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
375 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
376 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
377 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
378 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
379 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
380 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
381 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
382 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
383 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
384 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
385 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
386 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
387 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
388 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
389 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
390 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
391 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
392 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
393 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
394 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
395 {"workgroup", P_STRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
396 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
397 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
398 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
399 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
400 {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
401 {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
402 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
403 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
404 {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
405 {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
406 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
407 {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
408 {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
409 {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
410 {"read size", P_INTEGER, P_GLOBAL, &ReadSize, NULL},
412 {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
414 {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
415 {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
416 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
417 {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
418 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
419 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
420 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
421 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
422 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
423 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
425 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
426 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
427 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
428 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
429 {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
430 {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
431 {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
432 {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
433 {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
434 {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
435 {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
436 {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
437 {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
438 {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
439 {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
440 {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
441 {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
442 {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
443 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
444 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
445 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
446 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
447 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
448 {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
449 {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
450 {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
451 {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
452 {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
453 {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
454 {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
455 {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
456 {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
457 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
458 {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
459 {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
460 {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
461 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
462 {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
463 {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
464 {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
465 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
466 {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
467 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
468 {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
469 {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
470 {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
471 {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
472 {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
473 {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
474 {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
475 {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
476 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
477 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
478 {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
479 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
480 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
481 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
482 {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
483 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
484 {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
485 {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
486 {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
487 {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
488 {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
489 {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
490 {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
491 {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
492 {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
493 {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
494 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
495 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
496 {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
497 {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
498 {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
499 {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
500 {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
501 {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
502 {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
503 {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
504 {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
506 {NULL, P_BOOL, P_NONE, NULL, NULL}
511 /***************************************************************************
512 Initialise the global parameter structure.
513 ***************************************************************************/
514 static void init_globals(void)
516 static BOOL done_init = False;
522 bzero((void *)&Globals,sizeof(Globals));
524 for (i = 0; parm_table[i].label; i++)
525 if (parm_table[i].type == P_STRING &&
527 string_init(parm_table[i].ptr,"");
529 string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
535 DEBUG(3,("Initialising global parameters\n"));
537 #ifdef SMB_PASSWD_FILE
538 string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
540 string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
541 string_set(&Globals.szWorkGroup, WORKGROUP);
543 string_set(&Globals.szPasswdProgram, SMB_PASSWD);
545 string_set(&Globals.szPasswdProgram, "/bin/passwd");
547 string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
548 string_set(&Globals.szLockDir, LOCKDIR);
549 string_set(&Globals.szRootdir, "/");
550 string_set(&Globals.szSmbrun, SMBRUN);
551 sprintf(s,"Samba %s",VERSION);
552 string_set(&Globals.szServerString,s);
553 Globals.bLoadPrinters = True;
554 Globals.bUseRhosts = False;
555 Globals.max_packet = 65535;
556 Globals.mangled_stack = 50;
557 Globals.max_xmit = Globals.max_packet;
559 Globals.lpqcachetime = 10;
560 Globals.pwordlevel = 0;
561 Globals.deadtime = 0;
562 Globals.max_log_size = 5000;
563 Globals.maxprotocol = PROTOCOL_NT1;
564 Globals.security = SEC_SHARE;
565 Globals.bEncryptPasswords = False;
566 Globals.printing = DEFAULT_PRINTING;
567 Globals.bReadRaw = True;
568 Globals.bWriteRaw = True;
569 Globals.bReadPrediction = False;
570 Globals.bReadbmpx = True;
571 Globals.bNullPasswords = False;
572 Globals.bStripDot = False;
574 Globals.bSyslogOnly = False;
575 Globals.os_level = 0;
576 Globals.max_ttl = 60*60*4; /* 2 hours default */
577 Globals.bPreferredMaster = True;
578 Globals.bDomainMaster = False;
579 Globals.bDomainLogons = False;
580 Globals.bBrowseList = True;
581 Globals.bWINSsupport = True;
582 Globals.bWINSproxy = False;
585 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
590 /***************************************************************************
591 check if a string is initialised and if not then initialise it
592 ***************************************************************************/
593 static void string_initial(char **s,char *v)
600 /***************************************************************************
601 Initialise the sDefault parameter structure.
602 ***************************************************************************/
603 static void init_locals(void)
605 /* choose defaults depending on the type of printing */
606 switch (Globals.printing)
611 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
612 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
613 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
618 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
619 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
620 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
622 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
623 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
628 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
629 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
630 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
638 /*******************************************************************
639 a convenience rooutine to grab string parameters into a rotating
640 static buffer, and run standard_sub_basic on them. The buffers
641 can be written to by callers
642 ********************************************************************/
643 char *lp_string(char *s)
645 static pstring bufs[10];
649 ret = &bufs[next][0];
655 StrnCpy(ret,s,sizeof(pstring)-1);
657 standard_sub_basic(ret);
663 In this section all the functions that are used to access the
664 parameters from the rest of the program are defined
667 #define FN_GLOBAL_STRING(fn_name,ptr) \
668 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
669 #define FN_GLOBAL_BOOL(fn_name,ptr) \
670 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
671 #define FN_GLOBAL_CHAR(fn_name,ptr) \
672 char fn_name(void) {return(*(char *)(ptr));}
673 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
674 int fn_name(void) {return(*(int *)(ptr));}
676 #define FN_LOCAL_STRING(fn_name,val) \
677 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
678 #define FN_LOCAL_BOOL(fn_name,val) \
679 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
680 #define FN_LOCAL_CHAR(fn_name,val) \
681 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
682 #define FN_LOCAL_INTEGER(fn_name,val) \
683 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
685 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
686 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
687 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
688 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
689 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
690 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
691 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
692 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
693 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
694 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
695 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
696 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
697 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
698 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
699 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
700 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
701 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
702 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
703 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
704 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
705 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
706 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
708 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
709 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
710 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
711 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
712 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
713 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
714 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
715 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
716 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
717 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
718 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
719 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
720 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
721 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
722 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
723 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
724 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
726 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
727 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
728 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
729 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
730 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
731 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
732 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
733 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
734 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
735 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
736 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
737 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
738 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
739 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
740 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
741 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
743 FN_LOCAL_STRING(lp_preexec,szPreExec)
744 FN_LOCAL_STRING(lp_postexec,szPostExec)
745 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
746 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
747 FN_LOCAL_STRING(lp_servicename,szService)
748 FN_LOCAL_STRING(lp_pathname,szPath)
749 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
750 FN_LOCAL_STRING(lp_username,szUsername)
751 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
752 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
753 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
754 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
755 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
756 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
757 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
758 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
759 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
760 FN_LOCAL_STRING(lp_printername,szPrintername)
761 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
762 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
763 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
764 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
765 FN_LOCAL_STRING(lp_comment,comment)
766 FN_LOCAL_STRING(lp_force_user,force_user)
767 FN_LOCAL_STRING(lp_force_group,force_group)
768 FN_LOCAL_STRING(lp_readlist,readlist)
769 FN_LOCAL_STRING(lp_writelist,writelist)
770 FN_LOCAL_STRING(lp_volume,volume)
771 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
773 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
774 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
775 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
776 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
777 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
778 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
779 FN_LOCAL_BOOL(lp_status,status)
780 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
781 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
782 FN_LOCAL_BOOL(lp_readonly,bRead_only)
783 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
784 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
785 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
786 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
787 FN_LOCAL_BOOL(lp_postscript,bPostscript)
788 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
789 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
790 FN_LOCAL_BOOL(lp_locking,bLocking)
791 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
792 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
793 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
794 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
795 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
796 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
797 FN_LOCAL_BOOL(lp_map_system,bMap_system)
798 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
800 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
801 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
802 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
803 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
805 FN_LOCAL_CHAR(lp_magicchar,magic_char)
809 /* local prototypes */
810 static int strwicmp( char *psz1, char *psz2 );
811 static int map_parameter( char *pszParmName);
812 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
813 static int getservicebyname(char *pszServiceName, service *pserviceDest);
814 static void copy_service( service *pserviceDest,
815 service *pserviceSource,
816 BOOL *pcopymapDest );
817 static BOOL service_ok(int iService);
818 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
819 static BOOL do_section(char *pszSectionName);
820 static void dump_globals(void);
821 static void dump_a_service(service *pService);
822 static void init_copymap(service *pservice);
825 /***************************************************************************
826 initialise a service to the defaults
827 ***************************************************************************/
828 static void init_service(service *pservice)
830 bzero((char *)pservice,sizeof(service));
831 copy_service(pservice,&sDefault,NULL);
835 /***************************************************************************
836 free the dynamically allocated parts of a service struct
837 ***************************************************************************/
838 static void free_service(service *pservice)
844 for (i=0;parm_table[i].label;i++)
845 if (parm_table[i].type == P_STRING && parm_table[i].class == P_LOCAL)
846 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
849 /***************************************************************************
850 add a new service to the services array initialising it with the given
852 ***************************************************************************/
853 static int add_a_service(service *pservice, char *name)
857 int num_to_alloc = iNumServices+1;
859 tservice = *pservice;
861 /* it might already exist */
864 i = getservicebyname(name,NULL);
869 /* find an invalid one */
870 for (i=0;i<iNumServices;i++)
871 if (!pSERVICE(i)->valid)
874 /* if not, then create one */
875 if (i == iNumServices)
877 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
879 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
881 if (!ServicePtrs || !pSERVICE(iNumServices))
887 free_service(pSERVICE(i));
889 pSERVICE(i)->valid = True;
891 init_service(pSERVICE(i));
892 copy_service(pSERVICE(i),&tservice,NULL);
894 string_set(&iSERVICE(i).szService,name);
899 /***************************************************************************
900 add a new home service, with the specified home directory, defaults coming
902 ***************************************************************************/
903 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
905 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
910 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
911 string_set(&iSERVICE(i).szPath,pszHomedir);
912 if (!(*(iSERVICE(i).comment)))
915 sprintf(comment,"Home directory of %s",pszHomename);
916 string_set(&iSERVICE(i).comment,comment);
918 iSERVICE(i).bAvailable = sDefault.bAvailable;
919 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
921 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
926 /***************************************************************************
927 add a new service, based on an old one
928 ***************************************************************************/
929 int lp_add_service(char *pszService, int iDefaultService)
931 return(add_a_service(pSERVICE(iDefaultService),pszService));
935 /***************************************************************************
937 ***************************************************************************/
938 static BOOL lp_add_ipc(void)
941 int i = add_a_service(&sDefault,"IPC$");
946 sprintf(comment,"IPC Service (%s)",lp_serverstring());
948 string_set(&iSERVICE(i).szPath,"/tmp");
949 string_set(&iSERVICE(i).szUsername,"");
950 string_set(&iSERVICE(i).comment,comment);
951 iSERVICE(i).status = False;
952 iSERVICE(i).iMaxConnections = 0;
953 iSERVICE(i).bAvailable = True;
954 iSERVICE(i).bRead_only = True;
955 iSERVICE(i).bGuest_only = False;
956 iSERVICE(i).bGuest_ok = True;
957 iSERVICE(i).bPrint_ok = False;
958 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
960 DEBUG(3,("adding IPC service\n"));
966 /***************************************************************************
967 add a new printer service, with defaults coming from service iFrom
968 ***************************************************************************/
969 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
971 char *comment = "From Printcap";
972 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
977 /* note that we do NOT default the availability flag to True - */
978 /* we take it from the default service passed. This allows all */
979 /* dynamic printers to be disabled by disabling the [printers] */
980 /* entry (if/when the 'available' keyword is implemented!). */
982 /* the printer name is set to the service name. */
983 string_set(&iSERVICE(i).szPrintername,pszPrintername);
984 string_set(&iSERVICE(i).comment,comment);
985 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
987 DEBUG(3,("adding printer service %s\n",pszPrintername));
993 /***************************************************************************
994 Do a case-insensitive, whitespace-ignoring string compare.
995 ***************************************************************************/
996 static int strwicmp(char *psz1, char *psz2)
998 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
999 /* appropriate value. */
1009 /* sync the strings on first non-whitespace */
1012 while (isspace(*psz1))
1014 while (isspace(*psz2))
1016 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1021 return (*psz1 - *psz2);
1024 /***************************************************************************
1025 Map a parameter's string representation to something we can use.
1026 Returns False if the parameter string is not recognised, else TRUE.
1027 ***************************************************************************/
1028 static int map_parameter(char *pszParmName)
1032 if (*pszParmName == '-')
1035 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1036 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1039 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1044 /***************************************************************************
1045 Set a boolean variable from the text value stored in the passed string.
1046 Returns True in success, False if the passed string does not correctly
1047 represent a boolean.
1048 ***************************************************************************/
1049 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1054 if (strwicmp(pszParmValue, "yes") == 0 ||
1055 strwicmp(pszParmValue, "true") == 0 ||
1056 strwicmp(pszParmValue, "1") == 0)
1059 if (strwicmp(pszParmValue, "no") == 0 ||
1060 strwicmp(pszParmValue, "False") == 0 ||
1061 strwicmp(pszParmValue, "0") == 0)
1065 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1072 /***************************************************************************
1073 Find a service by name. Otherwise works like get_service.
1074 ***************************************************************************/
1075 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1079 for (iService = iNumServices - 1; iService >= 0; iService--)
1080 if (VALID(iService) &&
1081 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1083 if (pserviceDest != NULL)
1084 copy_service(pserviceDest, pSERVICE(iService), NULL);
1093 /***************************************************************************
1094 Copy a service structure to another
1096 If pcopymapDest is NULL then copy all fields
1097 ***************************************************************************/
1098 static void copy_service(service *pserviceDest,
1099 service *pserviceSource,
1103 BOOL bcopyall = (pcopymapDest == NULL);
1105 for (i=0;parm_table[i].label;i++)
1106 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1107 (bcopyall || pcopymapDest[i]))
1109 void *def_ptr = parm_table[i].ptr;
1111 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1113 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1115 switch (parm_table[i].type)
1119 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1124 *(int *)dest_ptr = *(int *)src_ptr;
1128 *(char *)dest_ptr = *(char *)src_ptr;
1132 string_set(dest_ptr,*(char **)src_ptr);
1141 init_copymap(pserviceDest);
1142 if (pserviceSource->copymap)
1143 memcpy((void *)pserviceDest->copymap,
1144 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1148 /***************************************************************************
1149 Check a service for consistency. Return False if the service is in any way
1150 incomplete or faulty, else True.
1151 ***************************************************************************/
1152 static BOOL service_ok(int iService)
1157 if (iSERVICE(iService).szService[0] == '\0')
1159 DEBUG(0,( "The following message indicates an internal error:\n"));
1160 DEBUG(0,( "No service name in service entry.\n"));
1164 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1165 /* I can't see why you'd want a non-printable printer service... */
1166 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1167 if (!iSERVICE(iService).bPrint_ok)
1169 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1170 iSERVICE(iService).szService));
1171 iSERVICE(iService).bPrint_ok = True;
1174 if (iSERVICE(iService).szPath[0] == '\0' &&
1175 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1177 DEBUG(0,("No path in service %s - using /tmp\n",iSERVICE(iService).szService));
1178 string_set(&iSERVICE(iService).szPath,"/tmp");
1181 /* If a service is flagged unavailable, log the fact at level 0. */
1182 if (!iSERVICE(iService).bAvailable)
1183 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1184 iSERVICE(iService).szService));
1189 static struct file_lists {
1190 struct file_lists *next;
1193 } *file_lists = NULL;
1195 /*******************************************************************
1196 keep a linked list of all config files so we know when one has changed
1197 it's date and needs to be reloaded
1198 ********************************************************************/
1199 static void add_to_file_list(char *fname)
1201 struct file_lists *f=file_lists;
1204 if (f->name && !strcmp(f->name,fname)) break;
1209 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1211 f->next = file_lists;
1212 f->name = strdup(fname);
1223 standard_sub_basic(n2);
1224 f->modtime = file_modtime(n2);
1229 /*******************************************************************
1230 check if a config file has changed date
1231 ********************************************************************/
1232 BOOL lp_file_list_changed(void)
1234 struct file_lists *f = file_lists;
1238 standard_sub_basic(n2);
1239 if (f->modtime != file_modtime(n2)) return(True);
1246 /***************************************************************************
1247 handle the interpretation of the coding system parameter
1248 *************************************************************************/
1249 static BOOL handle_coding_system(char *pszParmValue,int *val)
1251 *val = interpret_coding_system(pszParmValue,*val);
1256 /***************************************************************************
1257 handle the interpretation of the character set system parameter
1258 ***************************************************************************/
1259 static BOOL handle_character_set(char *pszParmValue,int *val)
1261 string_set(&Globals.szCharacterSet,pszParmValue);
1262 *val = interpret_character_set(pszParmValue,*val);
1267 /***************************************************************************
1268 handle the interpretation of the protocol parameter
1269 ***************************************************************************/
1270 static BOOL handle_protocol(char *pszParmValue,int *val)
1272 *val = interpret_protocol(pszParmValue,*val);
1276 /***************************************************************************
1277 handle the interpretation of the security parameter
1278 ***************************************************************************/
1279 static BOOL handle_security(char *pszParmValue,int *val)
1281 *val = interpret_security(pszParmValue,*val);
1285 /***************************************************************************
1286 handle the interpretation of the default case
1287 ***************************************************************************/
1288 static BOOL handle_case(char *pszParmValue,int *val)
1290 if (strequal(pszParmValue,"LOWER"))
1292 else if (strequal(pszParmValue,"UPPER"))
1297 /***************************************************************************
1298 handle the interpretation of the printing system
1299 ***************************************************************************/
1300 static BOOL handle_printing(char *pszParmValue,int *val)
1302 if (strequal(pszParmValue,"sysv"))
1304 else if (strequal(pszParmValue,"aix"))
1306 else if (strequal(pszParmValue,"hpux"))
1308 else if (strequal(pszParmValue,"bsd"))
1310 else if (strequal(pszParmValue,"qnx"))
1312 else if (strequal(pszParmValue,"plp"))
1317 /***************************************************************************
1318 handle the valid chars lines
1319 ***************************************************************************/
1320 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1322 string_set(ptr,pszParmValue);
1324 add_char_string(pszParmValue);
1329 /***************************************************************************
1330 handle the include operation
1331 ***************************************************************************/
1332 static BOOL handle_include(char *pszParmValue,char **ptr)
1335 strcpy(fname,pszParmValue);
1337 add_to_file_list(fname);
1339 standard_sub_basic(fname);
1341 string_set(ptr,fname);
1343 if (file_exist(fname,NULL))
1344 return(pm_process(fname, do_section, do_parameter));
1346 DEBUG(2,("Can't find include file %s\n",fname));
1352 /***************************************************************************
1353 handle the interpretation of the copy parameter
1354 ***************************************************************************/
1355 static BOOL handle_copy(char *pszParmValue,char **ptr)
1359 service serviceTemp;
1361 string_set(ptr,pszParmValue);
1363 init_service(&serviceTemp);
1367 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1369 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1371 if (iTemp == iServiceIndex)
1373 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1378 copy_service(pSERVICE(iServiceIndex),
1380 iSERVICE(iServiceIndex).copymap);
1386 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1391 free_service(&serviceTemp);
1396 /***************************************************************************
1397 initialise a copymap
1398 ***************************************************************************/
1399 static void init_copymap(service *pservice)
1402 if (pservice->copymap) free(pservice->copymap);
1403 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1404 if (!pservice->copymap)
1405 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1407 for (i=0;i<NUMPARAMETERS;i++)
1408 pservice->copymap[i] = True;
1412 /***************************************************************************
1413 Process a parameter.
1414 ***************************************************************************/
1415 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1418 void *parm_ptr=NULL; /* where we are going to store the result */
1421 if (!bInGlobalSection && bGlobalOnly) return(True);
1423 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1425 parmnum = map_parameter(pszParmName);
1429 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1433 def_ptr = parm_table[parmnum].ptr;
1435 /* we might point at a service, the default service or a global */
1436 if (bInGlobalSection)
1440 if (parm_table[parmnum].class == P_GLOBAL)
1442 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1445 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1448 if (!bInGlobalSection)
1451 if (!iSERVICE(iServiceIndex).copymap)
1452 init_copymap(pSERVICE(iServiceIndex));
1454 /* this handles the aliases - set the copymap for other entries with
1455 the same data pointer */
1456 for (i=0;parm_table[i].label;i++)
1457 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1458 iSERVICE(iServiceIndex).copymap[i] = False;
1461 /* if it is a special case then go ahead */
1462 if (parm_table[parmnum].special)
1464 parm_table[parmnum].special(pszParmValue,parm_ptr);
1468 /* now switch on the type of variable it is */
1469 switch (parm_table[parmnum].type)
1472 set_boolean(parm_ptr,pszParmValue);
1476 set_boolean(parm_ptr,pszParmValue);
1477 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1481 *(int *)parm_ptr = atoi(pszParmValue);
1485 *(char *)parm_ptr = *pszParmValue;
1489 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1493 string_set(parm_ptr,pszParmValue);
1497 strcpy((char *)parm_ptr,pszParmValue);
1504 /***************************************************************************
1505 print a parameter of the specified type
1506 ***************************************************************************/
1507 static void print_parameter(parm_type type,void *ptr)
1512 printf("%s",BOOLSTR(*(BOOL *)ptr));
1516 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1520 printf("%d",*(int *)ptr);
1524 printf("%c",*(char *)ptr);
1528 printf("0%o",*(int *)ptr);
1533 printf("%s",(char *)ptr);
1538 printf("%s",*(char **)ptr);
1544 /***************************************************************************
1545 check if two parameters are equal
1546 ***************************************************************************/
1547 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1553 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1557 return(*((int *)ptr1) == *((int *)ptr2));
1560 return(*((char *)ptr1) == *((char *)ptr2));
1564 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1565 if (p1 && !*p1) p1 = NULL;
1566 if (p2 && !*p2) p2 = NULL;
1567 return(p1==p2 || strequal(p1,p2));
1571 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1572 if (p1 && !*p1) p1 = NULL;
1573 if (p2 && !*p2) p2 = NULL;
1574 return(p1==p2 || strequal(p1,p2));
1580 /***************************************************************************
1581 Process a new section (service). At this stage all sections are services.
1582 Later we'll have special sections that permit server parameters to be set.
1583 Returns True on success, False on failure.
1584 ***************************************************************************/
1585 static BOOL do_section(char *pszSectionName)
1588 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1589 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1592 /* if we were in a global section then do the local inits */
1593 if (bInGlobalSection && !isglobal)
1596 /* if we've just struck a global section, note the fact. */
1597 bInGlobalSection = isglobal;
1599 /* check for multiple global sections */
1600 if (bInGlobalSection)
1602 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1606 if (!bInGlobalSection && bGlobalOnly) return(True);
1608 /* if we have a current service, tidy it up before moving on */
1611 if (iServiceIndex >= 0)
1612 bRetval = service_ok(iServiceIndex);
1614 /* if all is still well, move to the next record in the services array */
1617 /* We put this here to avoid an odd message order if messages are */
1618 /* issued by the post-processing of a previous section. */
1619 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1621 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1623 DEBUG(0,("Failed to add a new service\n"));
1631 /***************************************************************************
1632 Display the contents of the global structure.
1633 ***************************************************************************/
1634 static void dump_globals(void)
1637 printf("Global parameters:\n");
1639 for (i=0;parm_table[i].label;i++)
1640 if (parm_table[i].class == P_GLOBAL &&
1641 parm_table[i].ptr &&
1642 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1644 printf("\t%s: ",parm_table[i].label);
1645 print_parameter(parm_table[i].type,parm_table[i].ptr);
1650 /***************************************************************************
1651 Display the contents of a single services record.
1652 ***************************************************************************/
1653 static void dump_a_service(service *pService)
1656 if (pService == &sDefault)
1657 printf("\nDefault service parameters:\n");
1659 printf("\nService parameters [%s]:\n",pService->szService);
1661 for (i=0;parm_table[i].label;i++)
1662 if (parm_table[i].class == P_LOCAL &&
1663 parm_table[i].ptr &&
1664 (*parm_table[i].label != '-') &&
1665 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1667 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1669 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1670 ((char *)pService) + pdiff,
1671 ((char *)&sDefault) + pdiff))
1673 printf("\t%s: ",parm_table[i].label);
1674 print_parameter(parm_table[i].type,
1675 ((char *)pService) + pdiff);
1682 /***************************************************************************
1683 Display the contents of a single copy structure.
1684 ***************************************************************************/
1685 static void dump_copy_map(BOOL *pcopymap)
1688 if (!pcopymap) return;
1690 printf("\n\tNon-Copied parameters:\n");
1692 for (i=0;parm_table[i].label;i++)
1693 if (parm_table[i].class == P_LOCAL &&
1694 parm_table[i].ptr && !pcopymap[i] &&
1695 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1697 printf("\t\t%s\n",parm_table[i].label);
1702 /***************************************************************************
1703 Return TRUE if the passed service number is within range.
1704 ***************************************************************************/
1705 BOOL lp_snum_ok(int iService)
1707 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1711 /***************************************************************************
1712 auto-load some homes and printer services
1713 ***************************************************************************/
1714 static void lp_add_auto_services(char *str)
1718 int homes = lp_servicenumber(HOMES_NAME);
1719 int printers = lp_servicenumber(PRINTERS_NAME);
1727 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1729 char *home = get_home_dir(p);
1731 if (lp_servicenumber(p) >= 0) continue;
1733 if (home && homes >= 0)
1735 lp_add_home(p,homes,home);
1739 if (printers >= 0 && pcap_printername_ok(p,NULL))
1740 lp_add_printer(p,printers);
1745 /***************************************************************************
1746 auto-load one printer
1747 ***************************************************************************/
1748 static void lp_add_one_printer(char *name,char *comment)
1750 int printers = lp_servicenumber(PRINTERS_NAME);
1753 if (lp_servicenumber(name) < 0)
1755 lp_add_printer(name,printers);
1756 if ((i=lp_servicenumber(name)) >= 0)
1757 string_set(&iSERVICE(i).comment,comment);
1762 /***************************************************************************
1763 auto-load printer services
1764 ***************************************************************************/
1765 static void lp_add_all_printers(void)
1767 int printers = lp_servicenumber(PRINTERS_NAME);
1769 if (printers < 0) return;
1771 pcap_printer_fn(lp_add_one_printer);
1774 /***************************************************************************
1775 have we loaded a services file yet?
1776 ***************************************************************************/
1777 BOOL lp_loaded(void)
1782 /***************************************************************************
1783 unload unused services
1784 ***************************************************************************/
1785 void lp_killunused(BOOL (*snumused)(int ))
1788 for (i=0;i<iNumServices;i++)
1789 if (VALID(i) && !snumused(i))
1791 iSERVICE(i).valid = False;
1792 free_service(pSERVICE(i));
1796 /***************************************************************************
1797 Load the services array from the services file. Return True on success,
1799 ***************************************************************************/
1800 BOOL lp_load(char *pszFname,BOOL global_only)
1805 add_to_file_list(pszFname);
1809 bInGlobalSection = True;
1810 bGlobalOnly = global_only;
1814 strcpy(n2,pszFname);
1815 standard_sub_basic(n2);
1817 /* We get sections first, so have to start 'behind' to make up */
1819 bRetval = pm_process(n2, do_section, do_parameter);
1821 /* finish up the last section */
1822 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1824 if (iServiceIndex >= 0)
1825 bRetval = service_ok(iServiceIndex);
1827 lp_add_auto_services(lp_auto_services());
1828 if (lp_load_printers())
1829 lp_add_all_printers();
1839 /***************************************************************************
1840 return the max number of services
1841 ***************************************************************************/
1842 int lp_numservices(void)
1844 return(iNumServices);
1847 /***************************************************************************
1848 Display the contents of the services array in human-readable form.
1849 ***************************************************************************/
1856 dump_a_service(&sDefault);
1858 for (iService = 0; iService < iNumServices; iService++)
1860 if (VALID(iService))
1862 if (iSERVICE(iService).szService[0] == '\0')
1864 dump_a_service(pSERVICE(iService));
1869 /***************************************************************************
1870 Return the number of the service with the given name, or -1 if it doesn't
1871 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1872 getservicebyname()! This works ONLY if all services have been loaded, and
1873 does not copy the found service.
1874 ***************************************************************************/
1875 int lp_servicenumber(char *pszServiceName)
1879 for (iService = iNumServices - 1; iService >= 0; iService--)
1880 if (VALID(iService) &&
1881 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1885 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1893 /*******************************************************************
1894 get a workgroup - but map to standalone if '*'
1895 ******************************************************************/
1896 char *my_workgroup(void)
1898 char *res = lp_workgroup();
1899 if (*res == '*') return("STANDALONE");
1903 /*******************************************************************
1904 a useful volume label function
1905 ******************************************************************/
1906 char *volume_label(int snum)
1908 char *ret = lp_volume(snum);
1909 if (!*ret) return(lp_servicename(snum));