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;
151 BOOL bPreferredMaster;
154 BOOL bEncryptPasswords;
161 BOOL bReadPrediction;
165 BOOL bProxyNameResolution;
168 static global Globals;
173 * This structure describes a single service.
181 char *szGuestaccount;
182 char *szInvalidUsers;
190 char *szRootPostExec;
191 char *szPrintcommand;
194 char *szLppausecommand;
195 char *szLpresumecommand;
217 BOOL bShortCasePreserve;
241 BOOL bDeleteReadonly;
242 char dummy[3]; /* for alignment */
246 /* This is a default service used to prime a services structure */
247 static service sDefault =
250 NULL, /* szService */
252 NULL, /* szUsername */
253 NULL, /* szGuestAccount */
254 NULL, /* szInvalidUsers */
255 NULL, /* szValidUsers */
256 NULL, /* szAdminUsers */
258 NULL, /* szInclude */
259 NULL, /* szPreExec */
260 NULL, /* szPostExec */
261 NULL, /* szRootPreExec */
262 NULL, /* szRootPostExec */
263 NULL, /* szPrintcommand */
264 NULL, /* szLpqcommand */
265 NULL, /* szLprmcommand */
266 NULL, /* szLppausecommand */
267 NULL, /* szLpresumecommand */
268 NULL, /* szPrintername */
269 NULL, /* szDontdescend */
270 NULL, /* szHostsallow */
271 NULL, /* szHostsdeny */
272 NULL, /* szMagicScript */
273 NULL, /* szMagicOutput */
274 NULL, /* szMangledMap */
276 NULL, /* force user */
277 NULL, /* force group */
279 NULL, /* writelist */
281 0, /* iMinPrintSpace */
282 0755, /* iCreate_mode */
283 0, /* iMaxConnections */
284 CASE_LOWER, /* iDefaultCase */
285 False, /* bAlternatePerm */
286 False, /* revalidate */
287 False, /* case sensitive */
288 False, /* case preserve */
289 False, /* short case preserve */
290 False, /* case mangle */
292 True, /* bHideDotFiles */
293 True, /* bBrowseable */
294 True, /* bAvailable */
295 True, /* bRead_only */
296 True, /* bNo_set_dir */
297 False, /* bGuest_only */
298 False, /* bGuest_ok */
299 False, /* bPrint_ok */
300 False, /* bPostscript */
301 False, /* bMap_system */
302 False, /* bMap_hidden */
303 True, /* bMap_archive */
305 False, /* bStrictLocking */
306 True, /* bShareModes */
307 False, /* bOnlyUser */
308 True, /* bMangledNames */
309 True, /* bWidelinks */
310 False, /* bSyncAlways */
311 '~', /* magic char */
313 False, /* bDeleteReadonly */
319 /* local variables */
320 static service **ServicePtrs = NULL;
321 static int iNumServices = 0;
322 static int iServiceIndex = 0;
323 static BOOL bInGlobalSection = True;
324 static BOOL bGlobalOnly = False;
327 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
329 /* prototypes for the special type handlers */
330 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
331 static BOOL handle_include(char *pszParmValue, char **ptr);
332 static BOOL handle_copy(char *pszParmValue, char **ptr);
333 static BOOL handle_protocol(char *pszParmValue,int *val);
334 static BOOL handle_security(char *pszParmValue,int *val);
335 static BOOL handle_case(char *pszParmValue,int *val);
336 static BOOL handle_printing(char *pszParmValue,int *val);
337 static BOOL handle_character_set(char *pszParmValue,int *val);
339 static BOOL handle_coding_system(char *pszParmValue,int *val);
351 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
352 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
353 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
354 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
355 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
356 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
357 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
358 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
359 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
360 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
361 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
362 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
363 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
364 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
365 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
366 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
367 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
368 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
369 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
370 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
371 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
372 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
373 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
374 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
375 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
376 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
377 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
378 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
379 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
380 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
381 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
382 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
383 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
384 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
385 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
386 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
387 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
388 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
389 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
390 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
391 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
392 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
393 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
394 {"workgroup", P_STRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
395 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
396 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
397 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
398 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
399 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, 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 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
417 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
418 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
419 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
420 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
421 {"proxy name resolution",P_BOOL,P_GLOBAL,&Globals.bProxyNameResolution,NULL},
423 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
424 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
425 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
426 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
427 {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
428 {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
429 {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
430 {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
431 {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
432 {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
433 {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
434 {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
435 {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
436 {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
437 {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
438 {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
439 {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
440 {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
441 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
442 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
443 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
444 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
445 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
446 {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
447 {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
448 {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
449 {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
450 {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
451 {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
452 {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
453 {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
454 {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
455 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
456 {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
457 {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
458 {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
459 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
460 {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
461 {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
462 {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
463 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
464 {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
465 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
466 {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
467 {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
468 {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
469 {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
470 {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
471 {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
472 {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
473 {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
474 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
475 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
476 {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
477 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
478 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
479 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
480 {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
481 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
482 {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
483 {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
484 {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
485 {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
486 {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
487 {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
488 {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
489 {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
490 {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
491 {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
492 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
493 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
494 {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
495 {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
496 {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
497 {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
498 {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
499 {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
500 {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
501 {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
502 {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
504 {NULL, P_BOOL, P_NONE, NULL, NULL}
509 /***************************************************************************
510 Initialise the global parameter structure.
511 ***************************************************************************/
512 static void init_globals(void)
514 static BOOL done_init = False;
520 bzero((void *)&Globals,sizeof(Globals));
522 for (i = 0; parm_table[i].label; i++)
523 if (parm_table[i].type == P_STRING &&
525 string_init(parm_table[i].ptr,"");
527 string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
533 DEBUG(3,("Initialising global parameters\n"));
535 #ifdef SMB_PASSWD_FILE
536 string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
538 string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
539 string_set(&Globals.szWorkGroup, WORKGROUP);
541 string_set(&Globals.szPasswdProgram, SMB_PASSWD);
543 string_set(&Globals.szPasswdProgram, "/bin/passwd");
545 string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
546 string_set(&Globals.szLockDir, LOCKDIR);
547 string_set(&Globals.szRootdir, "/");
548 string_set(&Globals.szSmbrun, SMBRUN);
549 sprintf(s,"Samba %s",VERSION);
550 string_set(&Globals.szServerString,s);
551 Globals.bLoadPrinters = True;
552 Globals.bUseRhosts = False;
553 Globals.max_packet = 65535;
554 Globals.mangled_stack = 50;
555 Globals.max_xmit = Globals.max_packet;
557 Globals.lpqcachetime = 10;
558 Globals.pwordlevel = 0;
559 Globals.deadtime = 0;
560 Globals.max_log_size = 5000;
561 Globals.maxprotocol = PROTOCOL_NT1;
562 Globals.security = SEC_SHARE;
563 Globals.bEncryptPasswords = False;
564 Globals.printing = DEFAULT_PRINTING;
565 Globals.bReadRaw = True;
566 Globals.bWriteRaw = True;
567 Globals.bReadPrediction = False;
568 Globals.bReadbmpx = True;
569 Globals.bNullPasswords = False;
570 Globals.bStripDot = False;
572 Globals.bSyslogOnly = False;
573 Globals.os_level = 0;
574 Globals.max_ttl = 60*60*4; /* 2 hours default */
575 Globals.bPreferredMaster = True;
576 Globals.bDomainMaster = False;
577 Globals.bDomainLogons = False;
578 Globals.bBrowseList = True;
579 Globals.bProxyNameResolution = True;
582 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
587 /***************************************************************************
588 check if a string is initialised and if not then initialise it
589 ***************************************************************************/
590 static void string_initial(char **s,char *v)
597 /***************************************************************************
598 Initialise the sDefault parameter structure.
599 ***************************************************************************/
600 static void init_locals(void)
602 /* choose defaults depending on the type of printing */
603 switch (Globals.printing)
608 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
609 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
610 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
615 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
616 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
617 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
619 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
620 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
625 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
626 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
627 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
635 /*******************************************************************
636 a convenience rooutine to grab string parameters into a rotating
637 static buffer, and run standard_sub_basic on them. The buffers
638 can be written to by callers
639 ********************************************************************/
640 char *lp_string(char *s)
642 static pstring bufs[10];
646 ret = &bufs[next][0];
652 StrnCpy(ret,s,sizeof(pstring)-1);
654 standard_sub_basic(ret);
660 In this section all the functions that are used to access the
661 parameters from the rest of the program are defined
664 #define FN_GLOBAL_STRING(fn_name,ptr) \
665 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
666 #define FN_GLOBAL_BOOL(fn_name,ptr) \
667 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
668 #define FN_GLOBAL_CHAR(fn_name,ptr) \
669 char fn_name(void) {return(*(char *)(ptr));}
670 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
671 int fn_name(void) {return(*(int *)(ptr));}
673 #define FN_LOCAL_STRING(fn_name,val) \
674 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
675 #define FN_LOCAL_BOOL(fn_name,val) \
676 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
677 #define FN_LOCAL_CHAR(fn_name,val) \
678 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
679 #define FN_LOCAL_INTEGER(fn_name,val) \
680 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
682 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
683 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
684 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
685 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
686 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
687 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
688 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
689 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
690 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
691 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
692 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
693 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
694 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
695 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
696 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
697 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
698 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
699 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
700 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
701 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
702 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
703 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
705 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
706 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
707 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
708 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
709 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
710 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
711 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
712 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
713 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
714 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
715 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
716 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
717 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
718 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
719 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
720 FN_GLOBAL_BOOL(lp_proxy_name_resolution,&Globals.bProxyNameResolution)
722 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
723 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
724 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
725 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
726 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
727 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
728 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
729 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
730 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
731 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
732 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
733 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
734 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
735 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
736 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
737 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
739 FN_LOCAL_STRING(lp_preexec,szPreExec)
740 FN_LOCAL_STRING(lp_postexec,szPostExec)
741 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
742 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
743 FN_LOCAL_STRING(lp_servicename,szService)
744 FN_LOCAL_STRING(lp_pathname,szPath)
745 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
746 FN_LOCAL_STRING(lp_username,szUsername)
747 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
748 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
749 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
750 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
751 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
752 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
753 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
754 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
755 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
756 FN_LOCAL_STRING(lp_printername,szPrintername)
757 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
758 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
759 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
760 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
761 FN_LOCAL_STRING(lp_comment,comment)
762 FN_LOCAL_STRING(lp_force_user,force_user)
763 FN_LOCAL_STRING(lp_force_group,force_group)
764 FN_LOCAL_STRING(lp_readlist,readlist)
765 FN_LOCAL_STRING(lp_writelist,writelist)
766 FN_LOCAL_STRING(lp_volume,volume)
767 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
769 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
770 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
771 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
772 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
773 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
774 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
775 FN_LOCAL_BOOL(lp_status,status)
776 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
777 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
778 FN_LOCAL_BOOL(lp_readonly,bRead_only)
779 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
780 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
781 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
782 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
783 FN_LOCAL_BOOL(lp_postscript,bPostscript)
784 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
785 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
786 FN_LOCAL_BOOL(lp_locking,bLocking)
787 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
788 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
789 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
790 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
791 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
792 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
793 FN_LOCAL_BOOL(lp_map_system,bMap_system)
794 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
796 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
797 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
798 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
799 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
801 FN_LOCAL_CHAR(lp_magicchar,magic_char)
805 /* local prototypes */
806 static int strwicmp( char *psz1, char *psz2 );
807 static int map_parameter( char *pszParmName);
808 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
809 static int getservicebyname(char *pszServiceName, service *pserviceDest);
810 static void copy_service( service *pserviceDest,
811 service *pserviceSource,
812 BOOL *pcopymapDest );
813 static BOOL service_ok(int iService);
814 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
815 static BOOL do_section(char *pszSectionName);
816 static void dump_globals(void);
817 static void dump_a_service(service *pService);
818 static void init_copymap(service *pservice);
821 /***************************************************************************
822 initialise a service to the defaults
823 ***************************************************************************/
824 static void init_service(service *pservice)
826 bzero((char *)pservice,sizeof(service));
827 copy_service(pservice,&sDefault,NULL);
831 /***************************************************************************
832 free the dynamically allocated parts of a service struct
833 ***************************************************************************/
834 static void free_service(service *pservice)
840 for (i=0;parm_table[i].label;i++)
841 if (parm_table[i].type == P_STRING && parm_table[i].class == P_LOCAL)
842 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
845 /***************************************************************************
846 add a new service to the services array initialising it with the given
848 ***************************************************************************/
849 static int add_a_service(service *pservice, char *name)
853 int num_to_alloc = iNumServices+1;
855 tservice = *pservice;
857 /* it might already exist */
860 i = getservicebyname(name,NULL);
865 /* find an invalid one */
866 for (i=0;i<iNumServices;i++)
867 if (!pSERVICE(i)->valid)
870 /* if not, then create one */
871 if (i == iNumServices)
873 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
875 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
877 if (!ServicePtrs || !pSERVICE(iNumServices))
883 free_service(pSERVICE(i));
885 pSERVICE(i)->valid = True;
887 init_service(pSERVICE(i));
888 copy_service(pSERVICE(i),&tservice,NULL);
890 string_set(&iSERVICE(i).szService,name);
895 /***************************************************************************
896 add a new home service, with the specified home directory, defaults coming
898 ***************************************************************************/
899 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
901 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
906 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
907 string_set(&iSERVICE(i).szPath,pszHomedir);
908 if (!(*(iSERVICE(i).comment)))
911 sprintf(comment,"Home directory of %s",pszHomename);
912 string_set(&iSERVICE(i).comment,comment);
914 iSERVICE(i).bAvailable = sDefault.bAvailable;
915 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
917 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
922 /***************************************************************************
923 add a new service, based on an old one
924 ***************************************************************************/
925 int lp_add_service(char *pszService, int iDefaultService)
927 return(add_a_service(pSERVICE(iDefaultService),pszService));
931 /***************************************************************************
933 ***************************************************************************/
934 static BOOL lp_add_ipc(void)
937 int i = add_a_service(&sDefault,"IPC$");
942 sprintf(comment,"IPC Service (%s)",lp_serverstring());
944 string_set(&iSERVICE(i).szPath,"/tmp");
945 string_set(&iSERVICE(i).szUsername,"");
946 string_set(&iSERVICE(i).comment,comment);
947 iSERVICE(i).status = False;
948 iSERVICE(i).iMaxConnections = 0;
949 iSERVICE(i).bAvailable = True;
950 iSERVICE(i).bRead_only = True;
951 iSERVICE(i).bGuest_only = False;
952 iSERVICE(i).bGuest_ok = True;
953 iSERVICE(i).bPrint_ok = False;
954 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
956 DEBUG(3,("adding IPC service\n"));
962 /***************************************************************************
963 add a new printer service, with defaults coming from service iFrom
964 ***************************************************************************/
965 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
967 char *comment = "From Printcap";
968 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
973 /* note that we do NOT default the availability flag to True - */
974 /* we take it from the default service passed. This allows all */
975 /* dynamic printers to be disabled by disabling the [printers] */
976 /* entry (if/when the 'available' keyword is implemented!). */
978 /* the printer name is set to the service name. */
979 string_set(&iSERVICE(i).szPrintername,pszPrintername);
980 string_set(&iSERVICE(i).comment,comment);
981 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
983 DEBUG(3,("adding printer service %s\n",pszPrintername));
989 /***************************************************************************
990 Do a case-insensitive, whitespace-ignoring string compare.
991 ***************************************************************************/
992 static int strwicmp(char *psz1, char *psz2)
994 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
995 /* appropriate value. */
1005 /* sync the strings on first non-whitespace */
1008 while (isspace(*psz1))
1010 while (isspace(*psz2))
1012 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1017 return (*psz1 - *psz2);
1020 /***************************************************************************
1021 Map a parameter's string representation to something we can use.
1022 Returns False if the parameter string is not recognised, else TRUE.
1023 ***************************************************************************/
1024 static int map_parameter(char *pszParmName)
1028 if (*pszParmName == '-')
1031 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1032 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1035 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1040 /***************************************************************************
1041 Set a boolean variable from the text value stored in the passed string.
1042 Returns True in success, False if the passed string does not correctly
1043 represent a boolean.
1044 ***************************************************************************/
1045 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1050 if (strwicmp(pszParmValue, "yes") == 0 ||
1051 strwicmp(pszParmValue, "true") == 0 ||
1052 strwicmp(pszParmValue, "1") == 0)
1055 if (strwicmp(pszParmValue, "no") == 0 ||
1056 strwicmp(pszParmValue, "False") == 0 ||
1057 strwicmp(pszParmValue, "0") == 0)
1061 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1068 /***************************************************************************
1069 Find a service by name. Otherwise works like get_service.
1070 ***************************************************************************/
1071 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1075 for (iService = iNumServices - 1; iService >= 0; iService--)
1076 if (VALID(iService) &&
1077 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1079 if (pserviceDest != NULL)
1080 copy_service(pserviceDest, pSERVICE(iService), NULL);
1089 /***************************************************************************
1090 Copy a service structure to another
1092 If pcopymapDest is NULL then copy all fields
1093 ***************************************************************************/
1094 static void copy_service(service *pserviceDest,
1095 service *pserviceSource,
1099 BOOL bcopyall = (pcopymapDest == NULL);
1101 for (i=0;parm_table[i].label;i++)
1102 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1103 (bcopyall || pcopymapDest[i]))
1105 void *def_ptr = parm_table[i].ptr;
1107 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1109 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1111 switch (parm_table[i].type)
1115 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1120 *(int *)dest_ptr = *(int *)src_ptr;
1124 *(char *)dest_ptr = *(char *)src_ptr;
1128 string_set(dest_ptr,*(char **)src_ptr);
1137 init_copymap(pserviceDest);
1138 if (pserviceSource->copymap)
1139 memcpy((void *)pserviceDest->copymap,
1140 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1144 /***************************************************************************
1145 Check a service for consistency. Return False if the service is in any way
1146 incomplete or faulty, else True.
1147 ***************************************************************************/
1148 static BOOL service_ok(int iService)
1153 if (iSERVICE(iService).szService[0] == '\0')
1155 DEBUG(0,( "The following message indicates an internal error:\n"));
1156 DEBUG(0,( "No service name in service entry.\n"));
1160 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1161 /* I can't see why you'd want a non-printable printer service... */
1162 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1163 if (!iSERVICE(iService).bPrint_ok)
1165 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1166 iSERVICE(iService).szService));
1167 iSERVICE(iService).bPrint_ok = True;
1170 if (iSERVICE(iService).szPath[0] == '\0' &&
1171 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1173 DEBUG(0,("No path in service %s - using /tmp\n",iSERVICE(iService).szService));
1174 string_set(&iSERVICE(iService).szPath,"/tmp");
1177 /* If a service is flagged unavailable, log the fact at level 0. */
1178 if (!iSERVICE(iService).bAvailable)
1179 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1180 iSERVICE(iService).szService));
1185 static struct file_lists {
1186 struct file_lists *next;
1189 } *file_lists = NULL;
1191 /*******************************************************************
1192 keep a linked list of all config files so we know when one has changed
1193 it's date and needs to be reloaded
1194 ********************************************************************/
1195 static void add_to_file_list(char *fname)
1197 struct file_lists *f=file_lists;
1200 if (f->name && !strcmp(f->name,fname)) break;
1205 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1207 f->next = file_lists;
1208 f->name = strdup(fname);
1219 standard_sub_basic(n2);
1220 f->modtime = file_modtime(n2);
1225 /*******************************************************************
1226 check if a config file has changed date
1227 ********************************************************************/
1228 BOOL lp_file_list_changed(void)
1230 struct file_lists *f = file_lists;
1234 standard_sub_basic(n2);
1235 if (f->modtime != file_modtime(n2)) return(True);
1242 /***************************************************************************
1243 handle the interpretation of the coding system parameter
1244 *************************************************************************/
1245 static BOOL handle_coding_system(char *pszParmValue,int *val)
1247 *val = interpret_coding_system(pszParmValue,*val);
1252 /***************************************************************************
1253 handle the interpretation of the character set system parameter
1254 ***************************************************************************/
1255 static BOOL handle_character_set(char *pszParmValue,int *val)
1257 string_set(&Globals.szCharacterSet,pszParmValue);
1258 *val = interpret_character_set(pszParmValue,*val);
1263 /***************************************************************************
1264 handle the interpretation of the protocol parameter
1265 ***************************************************************************/
1266 static BOOL handle_protocol(char *pszParmValue,int *val)
1268 *val = interpret_protocol(pszParmValue,*val);
1272 /***************************************************************************
1273 handle the interpretation of the security parameter
1274 ***************************************************************************/
1275 static BOOL handle_security(char *pszParmValue,int *val)
1277 *val = interpret_security(pszParmValue,*val);
1281 /***************************************************************************
1282 handle the interpretation of the default case
1283 ***************************************************************************/
1284 static BOOL handle_case(char *pszParmValue,int *val)
1286 if (strequal(pszParmValue,"LOWER"))
1288 else if (strequal(pszParmValue,"UPPER"))
1293 /***************************************************************************
1294 handle the interpretation of the printing system
1295 ***************************************************************************/
1296 static BOOL handle_printing(char *pszParmValue,int *val)
1298 if (strequal(pszParmValue,"sysv"))
1300 else if (strequal(pszParmValue,"aix"))
1302 else if (strequal(pszParmValue,"hpux"))
1304 else if (strequal(pszParmValue,"bsd"))
1306 else if (strequal(pszParmValue,"qnx"))
1308 else if (strequal(pszParmValue,"plp"))
1313 /***************************************************************************
1314 handle the valid chars lines
1315 ***************************************************************************/
1316 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1318 string_set(ptr,pszParmValue);
1320 add_char_string(pszParmValue);
1325 /***************************************************************************
1326 handle the include operation
1327 ***************************************************************************/
1328 static BOOL handle_include(char *pszParmValue,char **ptr)
1331 strcpy(fname,pszParmValue);
1333 add_to_file_list(fname);
1335 standard_sub_basic(fname);
1337 string_set(ptr,fname);
1339 if (file_exist(fname,NULL))
1340 return(pm_process(fname, do_section, do_parameter));
1342 DEBUG(2,("Can't find include file %s\n",fname));
1348 /***************************************************************************
1349 handle the interpretation of the copy parameter
1350 ***************************************************************************/
1351 static BOOL handle_copy(char *pszParmValue,char **ptr)
1355 service serviceTemp;
1357 string_set(ptr,pszParmValue);
1359 init_service(&serviceTemp);
1363 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1365 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1367 if (iTemp == iServiceIndex)
1369 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1374 copy_service(pSERVICE(iServiceIndex),
1376 iSERVICE(iServiceIndex).copymap);
1382 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1387 free_service(&serviceTemp);
1392 /***************************************************************************
1393 initialise a copymap
1394 ***************************************************************************/
1395 static void init_copymap(service *pservice)
1398 if (pservice->copymap) free(pservice->copymap);
1399 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1400 if (!pservice->copymap)
1401 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1403 for (i=0;i<NUMPARAMETERS;i++)
1404 pservice->copymap[i] = True;
1408 /***************************************************************************
1409 Process a parameter.
1410 ***************************************************************************/
1411 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1414 void *parm_ptr=NULL; /* where we are going to store the result */
1417 if (!bInGlobalSection && bGlobalOnly) return(True);
1419 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1421 parmnum = map_parameter(pszParmName);
1425 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1429 def_ptr = parm_table[parmnum].ptr;
1431 /* we might point at a service, the default service or a global */
1432 if (bInGlobalSection)
1436 if (parm_table[parmnum].class == P_GLOBAL)
1438 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1441 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1444 if (!bInGlobalSection)
1447 if (!iSERVICE(iServiceIndex).copymap)
1448 init_copymap(pSERVICE(iServiceIndex));
1450 /* this handles the aliases - set the copymap for other entries with
1451 the same data pointer */
1452 for (i=0;parm_table[i].label;i++)
1453 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1454 iSERVICE(iServiceIndex).copymap[i] = False;
1457 /* if it is a special case then go ahead */
1458 if (parm_table[parmnum].special)
1460 parm_table[parmnum].special(pszParmValue,parm_ptr);
1464 /* now switch on the type of variable it is */
1465 switch (parm_table[parmnum].type)
1468 set_boolean(parm_ptr,pszParmValue);
1472 set_boolean(parm_ptr,pszParmValue);
1473 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1477 *(int *)parm_ptr = atoi(pszParmValue);
1481 *(char *)parm_ptr = *pszParmValue;
1485 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1489 string_set(parm_ptr,pszParmValue);
1493 strcpy((char *)parm_ptr,pszParmValue);
1500 /***************************************************************************
1501 print a parameter of the specified type
1502 ***************************************************************************/
1503 static void print_parameter(parm_type type,void *ptr)
1508 printf("%s",BOOLSTR(*(BOOL *)ptr));
1512 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1516 printf("%d",*(int *)ptr);
1520 printf("%c",*(char *)ptr);
1524 printf("0%o",*(int *)ptr);
1529 printf("%s",(char *)ptr);
1534 printf("%s",*(char **)ptr);
1540 /***************************************************************************
1541 check if two parameters are equal
1542 ***************************************************************************/
1543 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1549 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1553 return(*((int *)ptr1) == *((int *)ptr2));
1556 return(*((char *)ptr1) == *((char *)ptr2));
1560 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1561 if (p1 && !*p1) p1 = NULL;
1562 if (p2 && !*p2) p2 = NULL;
1563 return(p1==p2 || strequal(p1,p2));
1567 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1568 if (p1 && !*p1) p1 = NULL;
1569 if (p2 && !*p2) p2 = NULL;
1570 return(p1==p2 || strequal(p1,p2));
1576 /***************************************************************************
1577 Process a new section (service). At this stage all sections are services.
1578 Later we'll have special sections that permit server parameters to be set.
1579 Returns True on success, False on failure.
1580 ***************************************************************************/
1581 static BOOL do_section(char *pszSectionName)
1584 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1585 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1588 /* if we were in a global section then do the local inits */
1589 if (bInGlobalSection && !isglobal)
1592 /* if we've just struck a global section, note the fact. */
1593 bInGlobalSection = isglobal;
1595 /* check for multiple global sections */
1596 if (bInGlobalSection)
1598 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1602 if (!bInGlobalSection && bGlobalOnly) return(True);
1604 /* if we have a current service, tidy it up before moving on */
1607 if (iServiceIndex >= 0)
1608 bRetval = service_ok(iServiceIndex);
1610 /* if all is still well, move to the next record in the services array */
1613 /* We put this here to avoid an odd message order if messages are */
1614 /* issued by the post-processing of a previous section. */
1615 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1617 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1619 DEBUG(0,("Failed to add a new service\n"));
1627 /***************************************************************************
1628 Display the contents of the global structure.
1629 ***************************************************************************/
1630 static void dump_globals(void)
1633 printf("Global parameters:\n");
1635 for (i=0;parm_table[i].label;i++)
1636 if (parm_table[i].class == P_GLOBAL &&
1637 parm_table[i].ptr &&
1638 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1640 printf("\t%s: ",parm_table[i].label);
1641 print_parameter(parm_table[i].type,parm_table[i].ptr);
1646 /***************************************************************************
1647 Display the contents of a single services record.
1648 ***************************************************************************/
1649 static void dump_a_service(service *pService)
1652 if (pService == &sDefault)
1653 printf("\nDefault service parameters:\n");
1655 printf("\nService parameters [%s]:\n",pService->szService);
1657 for (i=0;parm_table[i].label;i++)
1658 if (parm_table[i].class == P_LOCAL &&
1659 parm_table[i].ptr &&
1660 (*parm_table[i].label != '-') &&
1661 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1663 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1665 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1666 ((char *)pService) + pdiff,
1667 ((char *)&sDefault) + pdiff))
1669 printf("\t%s: ",parm_table[i].label);
1670 print_parameter(parm_table[i].type,
1671 ((char *)pService) + pdiff);
1678 /***************************************************************************
1679 Display the contents of a single copy structure.
1680 ***************************************************************************/
1681 static void dump_copy_map(BOOL *pcopymap)
1684 if (!pcopymap) return;
1686 printf("\n\tNon-Copied parameters:\n");
1688 for (i=0;parm_table[i].label;i++)
1689 if (parm_table[i].class == P_LOCAL &&
1690 parm_table[i].ptr && !pcopymap[i] &&
1691 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1693 printf("\t\t%s\n",parm_table[i].label);
1698 /***************************************************************************
1699 Return TRUE if the passed service number is within range.
1700 ***************************************************************************/
1701 BOOL lp_snum_ok(int iService)
1703 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1707 /***************************************************************************
1708 auto-load some homes and printer services
1709 ***************************************************************************/
1710 static void lp_add_auto_services(char *str)
1714 int homes = lp_servicenumber(HOMES_NAME);
1715 int printers = lp_servicenumber(PRINTERS_NAME);
1723 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1725 char *home = get_home_dir(p);
1727 if (lp_servicenumber(p) >= 0) continue;
1729 if (home && homes >= 0)
1731 lp_add_home(p,homes,home);
1735 if (printers >= 0 && pcap_printername_ok(p,NULL))
1736 lp_add_printer(p,printers);
1741 /***************************************************************************
1742 auto-load one printer
1743 ***************************************************************************/
1744 static void lp_add_one_printer(char *name,char *comment)
1746 int printers = lp_servicenumber(PRINTERS_NAME);
1749 if (lp_servicenumber(name) < 0)
1751 lp_add_printer(name,printers);
1752 if ((i=lp_servicenumber(name)) >= 0)
1753 string_set(&iSERVICE(i).comment,comment);
1758 /***************************************************************************
1759 auto-load printer services
1760 ***************************************************************************/
1761 static void lp_add_all_printers(void)
1763 int printers = lp_servicenumber(PRINTERS_NAME);
1765 if (printers < 0) return;
1767 pcap_printer_fn(lp_add_one_printer);
1770 /***************************************************************************
1771 have we loaded a services file yet?
1772 ***************************************************************************/
1773 BOOL lp_loaded(void)
1778 /***************************************************************************
1779 unload unused services
1780 ***************************************************************************/
1781 void lp_killunused(BOOL (*snumused)(int ))
1784 for (i=0;i<iNumServices;i++)
1785 if (VALID(i) && !snumused(i))
1787 iSERVICE(i).valid = False;
1788 free_service(pSERVICE(i));
1792 /***************************************************************************
1793 Load the services array from the services file. Return True on success,
1795 ***************************************************************************/
1796 BOOL lp_load(char *pszFname,BOOL global_only)
1801 add_to_file_list(pszFname);
1805 bInGlobalSection = True;
1806 bGlobalOnly = global_only;
1810 strcpy(n2,pszFname);
1811 standard_sub_basic(n2);
1813 /* We get sections first, so have to start 'behind' to make up */
1815 bRetval = pm_process(n2, do_section, do_parameter);
1817 /* finish up the last section */
1818 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1820 if (iServiceIndex >= 0)
1821 bRetval = service_ok(iServiceIndex);
1823 lp_add_auto_services(lp_auto_services());
1824 if (lp_load_printers())
1825 lp_add_all_printers();
1835 /***************************************************************************
1836 return the max number of services
1837 ***************************************************************************/
1838 int lp_numservices(void)
1840 return(iNumServices);
1843 /***************************************************************************
1844 Display the contents of the services array in human-readable form.
1845 ***************************************************************************/
1852 dump_a_service(&sDefault);
1854 for (iService = 0; iService < iNumServices; iService++)
1856 if (VALID(iService))
1858 if (iSERVICE(iService).szService[0] == '\0')
1860 dump_a_service(pSERVICE(iService));
1865 /***************************************************************************
1866 Return the number of the service with the given name, or -1 if it doesn't
1867 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1868 getservicebyname()! This works ONLY if all services have been loaded, and
1869 does not copy the found service.
1870 ***************************************************************************/
1871 int lp_servicenumber(char *pszServiceName)
1875 for (iService = iNumServices - 1; iService >= 0; iService--)
1876 if (VALID(iService) &&
1877 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1881 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1889 /*******************************************************************
1890 get a workgroup - but map to standalone if '*'
1891 ******************************************************************/
1892 char *my_workgroup(void)
1894 char *res = lp_workgroup();
1895 if (*res == '*') return("STANDALONE");
1899 /*******************************************************************
1900 a useful volume label function
1901 ******************************************************************/
1902 char *volume_label(int snum)
1904 char *ret = lp_volume(snum);
1905 if (!*ret) return(lp_servicename(snum));