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;
59 extern pstring user_socket_options;
62 #define GLOBAL_NAME "global"
67 #define PRINTCAP_NAME "/etc/qconfig"
69 #define PRINTCAP_NAME "/etc/printcap"
74 #define PRINTERS_NAME "printers"
78 #define HOMES_NAME "homes"
81 /* some helpful bits */
82 #define pSERVICE(i) ServicePtrs[i]
83 #define iSERVICE(i) (*pSERVICE(i))
84 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
85 #define VALID(i) iSERVICE(i).valid
87 /* these are the types of parameter we have */
90 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_STRING,P_GSTRING
95 P_LOCAL,P_GLOBAL,P_NONE
99 extern BOOL use_getwd_cache;
101 extern int extra_time_offset;
103 extern int coding_system;
107 * This structure describes global (ie., server-wide) parameters.
111 char *szPrintcapname;
114 char *szDefaultService;
118 char *szServerString;
119 char *szAutoServices;
120 char *szPasswdProgram;
124 char *szSMBPasswdFile;
125 char *szPasswordServer;
126 char *szSocketOptions;
129 char *szDomainController;
131 char *szCharacterSet;
154 BOOL bPreferredMaster;
157 BOOL bEncryptPasswords;
164 BOOL bReadPrediction;
170 static global Globals;
175 * This structure describes a single service.
183 char *szGuestaccount;
184 char *szInvalidUsers;
192 char *szRootPostExec;
193 char *szPrintcommand;
196 char *szLppausecommand;
197 char *szLpresumecommand;
219 BOOL bShortCasePreserve;
243 BOOL bDeleteReadonly;
244 char dummy[3]; /* for alignment */
248 /* This is a default service used to prime a services structure */
249 static service sDefault =
252 NULL, /* szService */
254 NULL, /* szUsername */
255 NULL, /* szGuestAccount */
256 NULL, /* szInvalidUsers */
257 NULL, /* szValidUsers */
258 NULL, /* szAdminUsers */
260 NULL, /* szInclude */
261 NULL, /* szPreExec */
262 NULL, /* szPostExec */
263 NULL, /* szRootPreExec */
264 NULL, /* szRootPostExec */
265 NULL, /* szPrintcommand */
266 NULL, /* szLpqcommand */
267 NULL, /* szLprmcommand */
268 NULL, /* szLppausecommand */
269 NULL, /* szLpresumecommand */
270 NULL, /* szPrintername */
271 NULL, /* szDontdescend */
272 NULL, /* szHostsallow */
273 NULL, /* szHostsdeny */
274 NULL, /* szMagicScript */
275 NULL, /* szMagicOutput */
276 NULL, /* szMangledMap */
278 NULL, /* force user */
279 NULL, /* force group */
281 NULL, /* writelist */
283 0, /* iMinPrintSpace */
284 0755, /* iCreate_mode */
285 0, /* iMaxConnections */
286 CASE_LOWER, /* iDefaultCase */
287 False, /* bAlternatePerm */
288 False, /* revalidate */
289 False, /* case sensitive */
290 False, /* case preserve */
291 False, /* short case preserve */
292 False, /* case mangle */
294 True, /* bHideDotFiles */
295 True, /* bBrowseable */
296 True, /* bAvailable */
297 True, /* bRead_only */
298 True, /* bNo_set_dir */
299 False, /* bGuest_only */
300 False, /* bGuest_ok */
301 False, /* bPrint_ok */
302 False, /* bPostscript */
303 False, /* bMap_system */
304 False, /* bMap_hidden */
305 True, /* bMap_archive */
307 False, /* bStrictLocking */
308 True, /* bShareModes */
309 False, /* bOnlyUser */
310 True, /* bMangledNames */
311 True, /* bWidelinks */
312 False, /* bSyncAlways */
313 '~', /* magic char */
315 False, /* bDeleteReadonly */
321 /* local variables */
322 static service **ServicePtrs = NULL;
323 static int iNumServices = 0;
324 static int iServiceIndex = 0;
325 static BOOL bInGlobalSection = True;
326 static BOOL bGlobalOnly = False;
329 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
331 /* prototypes for the special type handlers */
332 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
333 static BOOL handle_include(char *pszParmValue, char **ptr);
334 static BOOL handle_copy(char *pszParmValue, char **ptr);
335 static BOOL handle_protocol(char *pszParmValue,int *val);
336 static BOOL handle_security(char *pszParmValue,int *val);
337 static BOOL handle_case(char *pszParmValue,int *val);
338 static BOOL handle_printing(char *pszParmValue,int *val);
339 static BOOL handle_character_set(char *pszParmValue,int *val);
341 static BOOL handle_coding_system(char *pszParmValue,int *val);
353 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
354 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
355 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
356 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
357 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
358 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
359 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
360 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
361 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
362 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
363 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
364 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
365 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
366 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
367 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
368 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
369 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
370 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
371 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
372 {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
373 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
374 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
375 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
376 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
377 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
378 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
379 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
380 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
381 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
382 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
383 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
384 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
385 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
386 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
387 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
388 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
389 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
390 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
391 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
392 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
393 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
394 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
395 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
396 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
397 {"workgroup", P_STRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
398 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
399 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
400 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
401 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
402 {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
403 {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
404 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
405 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
406 {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
407 {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
408 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
409 {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
410 {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
411 {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
412 {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
414 {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
416 {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
417 {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
418 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
419 {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
420 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
421 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
422 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
423 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
424 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
425 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
427 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
428 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
429 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
430 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
431 {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
432 {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
433 {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
434 {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
435 {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
436 {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
437 {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
438 {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
439 {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
440 {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
441 {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
442 {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
443 {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
444 {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
445 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
446 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
447 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
448 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
449 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
450 {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
451 {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
452 {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
453 {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
454 {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
455 {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
456 {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
457 {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
458 {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
459 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
460 {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
461 {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
462 {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
463 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
464 {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
465 {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
466 {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
467 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
468 {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
469 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
470 {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
471 {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
472 {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
473 {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
474 {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
475 {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
476 {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
477 {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
478 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
479 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
480 {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
481 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
482 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
483 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
484 {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
485 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
486 {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
487 {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
488 {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
489 {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
490 {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
491 {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
492 {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
493 {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
494 {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
495 {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
496 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
497 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
498 {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
499 {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
500 {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
501 {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
502 {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
503 {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
504 {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
505 {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
506 {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
508 {NULL, P_BOOL, P_NONE, NULL, NULL}
513 /***************************************************************************
514 Initialise the global parameter structure.
515 ***************************************************************************/
516 static void init_globals(void)
518 static BOOL done_init = False;
524 bzero((void *)&Globals,sizeof(Globals));
526 for (i = 0; parm_table[i].label; i++)
527 if (parm_table[i].type == P_STRING &&
529 string_init(parm_table[i].ptr,"");
531 string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
537 DEBUG(3,("Initialising global parameters\n"));
539 #ifdef SMB_PASSWD_FILE
540 string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
542 string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
543 string_set(&Globals.szWorkGroup, WORKGROUP);
545 string_set(&Globals.szPasswdProgram, SMB_PASSWD);
547 string_set(&Globals.szPasswdProgram, "/bin/passwd");
549 string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
550 string_set(&Globals.szLockDir, LOCKDIR);
551 string_set(&Globals.szRootdir, "/");
552 string_set(&Globals.szSmbrun, SMBRUN);
553 sprintf(s,"Samba %s",VERSION);
554 string_set(&Globals.szServerString,s);
555 Globals.bLoadPrinters = True;
556 Globals.bUseRhosts = False;
557 Globals.max_packet = 65535;
558 Globals.mangled_stack = 50;
559 Globals.max_xmit = Globals.max_packet;
561 Globals.lpqcachetime = 10;
562 Globals.pwordlevel = 0;
563 Globals.deadtime = 0;
564 Globals.max_log_size = 5000;
565 Globals.maxprotocol = PROTOCOL_NT1;
566 Globals.security = SEC_SHARE;
567 Globals.bEncryptPasswords = False;
568 Globals.printing = DEFAULT_PRINTING;
569 Globals.bReadRaw = True;
570 Globals.bWriteRaw = True;
571 Globals.bReadPrediction = False;
572 Globals.bReadbmpx = True;
573 Globals.bNullPasswords = False;
574 Globals.bStripDot = False;
576 Globals.bSyslogOnly = False;
577 Globals.os_level = 0;
578 Globals.max_ttl = 60*60*4; /* 2 hours default */
579 Globals.bPreferredMaster = True;
580 Globals.bDomainMaster = False;
581 Globals.bDomainLogons = False;
582 Globals.bBrowseList = True;
583 Globals.bWINSsupport = True;
584 Globals.bWINSproxy = False;
585 Globals.ReadSize = 16*1024;
588 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
593 /***************************************************************************
594 check if a string is initialised and if not then initialise it
595 ***************************************************************************/
596 static void string_initial(char **s,char *v)
603 /***************************************************************************
604 Initialise the sDefault parameter structure.
605 ***************************************************************************/
606 static void init_locals(void)
608 /* choose defaults depending on the type of printing */
609 switch (Globals.printing)
614 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
615 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
616 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
621 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
622 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
623 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
625 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
626 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
631 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
632 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
633 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
641 /*******************************************************************
642 a convenience rooutine to grab string parameters into a rotating
643 static buffer, and run standard_sub_basic on them. The buffers
644 can be written to by callers
645 ********************************************************************/
646 char *lp_string(char *s)
648 static pstring bufs[10];
652 ret = &bufs[next][0];
658 StrnCpy(ret,s,sizeof(pstring)-1);
660 standard_sub_basic(ret);
666 In this section all the functions that are used to access the
667 parameters from the rest of the program are defined
670 #define FN_GLOBAL_STRING(fn_name,ptr) \
671 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
672 #define FN_GLOBAL_BOOL(fn_name,ptr) \
673 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
674 #define FN_GLOBAL_CHAR(fn_name,ptr) \
675 char fn_name(void) {return(*(char *)(ptr));}
676 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
677 int fn_name(void) {return(*(int *)(ptr));}
679 #define FN_LOCAL_STRING(fn_name,val) \
680 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
681 #define FN_LOCAL_BOOL(fn_name,val) \
682 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
683 #define FN_LOCAL_CHAR(fn_name,val) \
684 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
685 #define FN_LOCAL_INTEGER(fn_name,val) \
686 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
688 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
689 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
690 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
691 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
692 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
693 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
694 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
695 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
696 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
697 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
698 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
699 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
700 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
701 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
702 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
703 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
704 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
705 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
706 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
707 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
708 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
709 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
710 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
712 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
713 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
714 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
715 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
716 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
717 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
718 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
719 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
720 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
721 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
722 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
723 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
724 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
725 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
726 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
727 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
728 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
730 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
731 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
732 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
733 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
734 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
735 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
736 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
737 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
738 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
739 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
740 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
741 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
742 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
743 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
744 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
745 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
746 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
748 FN_LOCAL_STRING(lp_preexec,szPreExec)
749 FN_LOCAL_STRING(lp_postexec,szPostExec)
750 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
751 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
752 FN_LOCAL_STRING(lp_servicename,szService)
753 FN_LOCAL_STRING(lp_pathname,szPath)
754 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
755 FN_LOCAL_STRING(lp_username,szUsername)
756 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
757 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
758 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
759 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
760 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
761 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
762 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
763 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
764 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
765 FN_LOCAL_STRING(lp_printername,szPrintername)
766 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
767 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
768 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
769 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
770 FN_LOCAL_STRING(lp_comment,comment)
771 FN_LOCAL_STRING(lp_force_user,force_user)
772 FN_LOCAL_STRING(lp_force_group,force_group)
773 FN_LOCAL_STRING(lp_readlist,readlist)
774 FN_LOCAL_STRING(lp_writelist,writelist)
775 FN_LOCAL_STRING(lp_volume,volume)
776 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
778 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
779 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
780 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
781 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
782 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
783 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
784 FN_LOCAL_BOOL(lp_status,status)
785 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
786 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
787 FN_LOCAL_BOOL(lp_readonly,bRead_only)
788 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
789 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
790 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
791 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
792 FN_LOCAL_BOOL(lp_postscript,bPostscript)
793 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
794 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
795 FN_LOCAL_BOOL(lp_locking,bLocking)
796 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
797 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
798 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
799 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
800 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
801 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
802 FN_LOCAL_BOOL(lp_map_system,bMap_system)
803 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
805 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
806 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
807 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
808 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
810 FN_LOCAL_CHAR(lp_magicchar,magic_char)
814 /* local prototypes */
815 static int strwicmp( char *psz1, char *psz2 );
816 static int map_parameter( char *pszParmName);
817 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
818 static int getservicebyname(char *pszServiceName, service *pserviceDest);
819 static void copy_service( service *pserviceDest,
820 service *pserviceSource,
821 BOOL *pcopymapDest );
822 static BOOL service_ok(int iService);
823 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
824 static BOOL do_section(char *pszSectionName);
825 static void dump_globals(void);
826 static void dump_a_service(service *pService);
827 static void init_copymap(service *pservice);
830 /***************************************************************************
831 initialise a service to the defaults
832 ***************************************************************************/
833 static void init_service(service *pservice)
835 bzero((char *)pservice,sizeof(service));
836 copy_service(pservice,&sDefault,NULL);
840 /***************************************************************************
841 free the dynamically allocated parts of a service struct
842 ***************************************************************************/
843 static void free_service(service *pservice)
849 for (i=0;parm_table[i].label;i++)
850 if (parm_table[i].type == P_STRING && parm_table[i].class == P_LOCAL)
851 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
854 /***************************************************************************
855 add a new service to the services array initialising it with the given
857 ***************************************************************************/
858 static int add_a_service(service *pservice, char *name)
862 int num_to_alloc = iNumServices+1;
864 tservice = *pservice;
866 /* it might already exist */
869 i = getservicebyname(name,NULL);
874 /* find an invalid one */
875 for (i=0;i<iNumServices;i++)
876 if (!pSERVICE(i)->valid)
879 /* if not, then create one */
880 if (i == iNumServices)
882 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
884 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
886 if (!ServicePtrs || !pSERVICE(iNumServices))
892 free_service(pSERVICE(i));
894 pSERVICE(i)->valid = True;
896 init_service(pSERVICE(i));
897 copy_service(pSERVICE(i),&tservice,NULL);
899 string_set(&iSERVICE(i).szService,name);
904 /***************************************************************************
905 add a new home service, with the specified home directory, defaults coming
907 ***************************************************************************/
908 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
910 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
915 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
916 string_set(&iSERVICE(i).szPath,pszHomedir);
917 if (!(*(iSERVICE(i).comment)))
920 sprintf(comment,"Home directory of %s",pszHomename);
921 string_set(&iSERVICE(i).comment,comment);
923 iSERVICE(i).bAvailable = sDefault.bAvailable;
924 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
926 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
931 /***************************************************************************
932 add a new service, based on an old one
933 ***************************************************************************/
934 int lp_add_service(char *pszService, int iDefaultService)
936 return(add_a_service(pSERVICE(iDefaultService),pszService));
940 /***************************************************************************
942 ***************************************************************************/
943 static BOOL lp_add_ipc(void)
946 int i = add_a_service(&sDefault,"IPC$");
951 sprintf(comment,"IPC Service (%s)",lp_serverstring());
953 string_set(&iSERVICE(i).szPath,"/tmp");
954 string_set(&iSERVICE(i).szUsername,"");
955 string_set(&iSERVICE(i).comment,comment);
956 iSERVICE(i).status = False;
957 iSERVICE(i).iMaxConnections = 0;
958 iSERVICE(i).bAvailable = True;
959 iSERVICE(i).bRead_only = True;
960 iSERVICE(i).bGuest_only = False;
961 iSERVICE(i).bGuest_ok = True;
962 iSERVICE(i).bPrint_ok = False;
963 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
965 DEBUG(3,("adding IPC service\n"));
971 /***************************************************************************
972 add a new printer service, with defaults coming from service iFrom
973 ***************************************************************************/
974 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
976 char *comment = "From Printcap";
977 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
982 /* note that we do NOT default the availability flag to True - */
983 /* we take it from the default service passed. This allows all */
984 /* dynamic printers to be disabled by disabling the [printers] */
985 /* entry (if/when the 'available' keyword is implemented!). */
987 /* the printer name is set to the service name. */
988 string_set(&iSERVICE(i).szPrintername,pszPrintername);
989 string_set(&iSERVICE(i).comment,comment);
990 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
992 DEBUG(3,("adding printer service %s\n",pszPrintername));
998 /***************************************************************************
999 Do a case-insensitive, whitespace-ignoring string compare.
1000 ***************************************************************************/
1001 static int strwicmp(char *psz1, char *psz2)
1003 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1004 /* appropriate value. */
1014 /* sync the strings on first non-whitespace */
1017 while (isspace(*psz1))
1019 while (isspace(*psz2))
1021 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1026 return (*psz1 - *psz2);
1029 /***************************************************************************
1030 Map a parameter's string representation to something we can use.
1031 Returns False if the parameter string is not recognised, else TRUE.
1032 ***************************************************************************/
1033 static int map_parameter(char *pszParmName)
1037 if (*pszParmName == '-')
1040 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1041 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1044 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1049 /***************************************************************************
1050 Set a boolean variable from the text value stored in the passed string.
1051 Returns True in success, False if the passed string does not correctly
1052 represent a boolean.
1053 ***************************************************************************/
1054 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1059 if (strwicmp(pszParmValue, "yes") == 0 ||
1060 strwicmp(pszParmValue, "true") == 0 ||
1061 strwicmp(pszParmValue, "1") == 0)
1064 if (strwicmp(pszParmValue, "no") == 0 ||
1065 strwicmp(pszParmValue, "False") == 0 ||
1066 strwicmp(pszParmValue, "0") == 0)
1070 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1077 /***************************************************************************
1078 Find a service by name. Otherwise works like get_service.
1079 ***************************************************************************/
1080 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1084 for (iService = iNumServices - 1; iService >= 0; iService--)
1085 if (VALID(iService) &&
1086 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1088 if (pserviceDest != NULL)
1089 copy_service(pserviceDest, pSERVICE(iService), NULL);
1098 /***************************************************************************
1099 Copy a service structure to another
1101 If pcopymapDest is NULL then copy all fields
1102 ***************************************************************************/
1103 static void copy_service(service *pserviceDest,
1104 service *pserviceSource,
1108 BOOL bcopyall = (pcopymapDest == NULL);
1110 for (i=0;parm_table[i].label;i++)
1111 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1112 (bcopyall || pcopymapDest[i]))
1114 void *def_ptr = parm_table[i].ptr;
1116 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1118 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1120 switch (parm_table[i].type)
1124 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1129 *(int *)dest_ptr = *(int *)src_ptr;
1133 *(char *)dest_ptr = *(char *)src_ptr;
1137 string_set(dest_ptr,*(char **)src_ptr);
1146 init_copymap(pserviceDest);
1147 if (pserviceSource->copymap)
1148 memcpy((void *)pserviceDest->copymap,
1149 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1153 /***************************************************************************
1154 Check a service for consistency. Return False if the service is in any way
1155 incomplete or faulty, else True.
1156 ***************************************************************************/
1157 static BOOL service_ok(int iService)
1162 if (iSERVICE(iService).szService[0] == '\0')
1164 DEBUG(0,( "The following message indicates an internal error:\n"));
1165 DEBUG(0,( "No service name in service entry.\n"));
1169 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1170 /* I can't see why you'd want a non-printable printer service... */
1171 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1172 if (!iSERVICE(iService).bPrint_ok)
1174 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1175 iSERVICE(iService).szService));
1176 iSERVICE(iService).bPrint_ok = True;
1179 if (iSERVICE(iService).szPath[0] == '\0' &&
1180 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1182 DEBUG(0,("No path in service %s - using /tmp\n",iSERVICE(iService).szService));
1183 string_set(&iSERVICE(iService).szPath,"/tmp");
1186 /* If a service is flagged unavailable, log the fact at level 0. */
1187 if (!iSERVICE(iService).bAvailable)
1188 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1189 iSERVICE(iService).szService));
1194 static struct file_lists {
1195 struct file_lists *next;
1198 } *file_lists = NULL;
1200 /*******************************************************************
1201 keep a linked list of all config files so we know when one has changed
1202 it's date and needs to be reloaded
1203 ********************************************************************/
1204 static void add_to_file_list(char *fname)
1206 struct file_lists *f=file_lists;
1209 if (f->name && !strcmp(f->name,fname)) break;
1214 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1216 f->next = file_lists;
1217 f->name = strdup(fname);
1228 standard_sub_basic(n2);
1229 f->modtime = file_modtime(n2);
1234 /*******************************************************************
1235 check if a config file has changed date
1236 ********************************************************************/
1237 BOOL lp_file_list_changed(void)
1239 struct file_lists *f = file_lists;
1243 standard_sub_basic(n2);
1244 if (f->modtime != file_modtime(n2)) return(True);
1251 /***************************************************************************
1252 handle the interpretation of the coding system parameter
1253 *************************************************************************/
1254 static BOOL handle_coding_system(char *pszParmValue,int *val)
1256 *val = interpret_coding_system(pszParmValue,*val);
1261 /***************************************************************************
1262 handle the interpretation of the character set system parameter
1263 ***************************************************************************/
1264 static BOOL handle_character_set(char *pszParmValue,int *val)
1266 string_set(&Globals.szCharacterSet,pszParmValue);
1267 *val = interpret_character_set(pszParmValue,*val);
1272 /***************************************************************************
1273 handle the interpretation of the protocol parameter
1274 ***************************************************************************/
1275 static BOOL handle_protocol(char *pszParmValue,int *val)
1277 *val = interpret_protocol(pszParmValue,*val);
1281 /***************************************************************************
1282 handle the interpretation of the security parameter
1283 ***************************************************************************/
1284 static BOOL handle_security(char *pszParmValue,int *val)
1286 *val = interpret_security(pszParmValue,*val);
1290 /***************************************************************************
1291 handle the interpretation of the default case
1292 ***************************************************************************/
1293 static BOOL handle_case(char *pszParmValue,int *val)
1295 if (strequal(pszParmValue,"LOWER"))
1297 else if (strequal(pszParmValue,"UPPER"))
1302 /***************************************************************************
1303 handle the interpretation of the printing system
1304 ***************************************************************************/
1305 static BOOL handle_printing(char *pszParmValue,int *val)
1307 if (strequal(pszParmValue,"sysv"))
1309 else if (strequal(pszParmValue,"aix"))
1311 else if (strequal(pszParmValue,"hpux"))
1313 else if (strequal(pszParmValue,"bsd"))
1315 else if (strequal(pszParmValue,"qnx"))
1317 else if (strequal(pszParmValue,"plp"))
1322 /***************************************************************************
1323 handle the valid chars lines
1324 ***************************************************************************/
1325 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1327 string_set(ptr,pszParmValue);
1329 add_char_string(pszParmValue);
1334 /***************************************************************************
1335 handle the include operation
1336 ***************************************************************************/
1337 static BOOL handle_include(char *pszParmValue,char **ptr)
1340 strcpy(fname,pszParmValue);
1342 add_to_file_list(fname);
1344 standard_sub_basic(fname);
1346 string_set(ptr,fname);
1348 if (file_exist(fname,NULL))
1349 return(pm_process(fname, do_section, do_parameter));
1351 DEBUG(2,("Can't find include file %s\n",fname));
1357 /***************************************************************************
1358 handle the interpretation of the copy parameter
1359 ***************************************************************************/
1360 static BOOL handle_copy(char *pszParmValue,char **ptr)
1364 service serviceTemp;
1366 string_set(ptr,pszParmValue);
1368 init_service(&serviceTemp);
1372 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1374 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1376 if (iTemp == iServiceIndex)
1378 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1383 copy_service(pSERVICE(iServiceIndex),
1385 iSERVICE(iServiceIndex).copymap);
1391 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1396 free_service(&serviceTemp);
1401 /***************************************************************************
1402 initialise a copymap
1403 ***************************************************************************/
1404 static void init_copymap(service *pservice)
1407 if (pservice->copymap) free(pservice->copymap);
1408 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1409 if (!pservice->copymap)
1410 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1412 for (i=0;i<NUMPARAMETERS;i++)
1413 pservice->copymap[i] = True;
1417 /***************************************************************************
1418 Process a parameter.
1419 ***************************************************************************/
1420 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1423 void *parm_ptr=NULL; /* where we are going to store the result */
1426 if (!bInGlobalSection && bGlobalOnly) return(True);
1428 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1430 parmnum = map_parameter(pszParmName);
1434 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1438 def_ptr = parm_table[parmnum].ptr;
1440 /* we might point at a service, the default service or a global */
1441 if (bInGlobalSection)
1445 if (parm_table[parmnum].class == P_GLOBAL)
1447 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1450 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1453 if (!bInGlobalSection)
1456 if (!iSERVICE(iServiceIndex).copymap)
1457 init_copymap(pSERVICE(iServiceIndex));
1459 /* this handles the aliases - set the copymap for other entries with
1460 the same data pointer */
1461 for (i=0;parm_table[i].label;i++)
1462 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1463 iSERVICE(iServiceIndex).copymap[i] = False;
1466 /* if it is a special case then go ahead */
1467 if (parm_table[parmnum].special)
1469 parm_table[parmnum].special(pszParmValue,parm_ptr);
1473 /* now switch on the type of variable it is */
1474 switch (parm_table[parmnum].type)
1477 set_boolean(parm_ptr,pszParmValue);
1481 set_boolean(parm_ptr,pszParmValue);
1482 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1486 *(int *)parm_ptr = atoi(pszParmValue);
1490 *(char *)parm_ptr = *pszParmValue;
1494 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1498 string_set(parm_ptr,pszParmValue);
1502 strcpy((char *)parm_ptr,pszParmValue);
1509 /***************************************************************************
1510 print a parameter of the specified type
1511 ***************************************************************************/
1512 static void print_parameter(parm_type type,void *ptr)
1517 printf("%s",BOOLSTR(*(BOOL *)ptr));
1521 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1525 printf("%d",*(int *)ptr);
1529 printf("%c",*(char *)ptr);
1533 printf("0%o",*(int *)ptr);
1538 printf("%s",(char *)ptr);
1543 printf("%s",*(char **)ptr);
1549 /***************************************************************************
1550 check if two parameters are equal
1551 ***************************************************************************/
1552 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1558 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1562 return(*((int *)ptr1) == *((int *)ptr2));
1565 return(*((char *)ptr1) == *((char *)ptr2));
1569 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1570 if (p1 && !*p1) p1 = NULL;
1571 if (p2 && !*p2) p2 = NULL;
1572 return(p1==p2 || strequal(p1,p2));
1576 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1577 if (p1 && !*p1) p1 = NULL;
1578 if (p2 && !*p2) p2 = NULL;
1579 return(p1==p2 || strequal(p1,p2));
1585 /***************************************************************************
1586 Process a new section (service). At this stage all sections are services.
1587 Later we'll have special sections that permit server parameters to be set.
1588 Returns True on success, False on failure.
1589 ***************************************************************************/
1590 static BOOL do_section(char *pszSectionName)
1593 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1594 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1597 /* if we were in a global section then do the local inits */
1598 if (bInGlobalSection && !isglobal)
1601 /* if we've just struck a global section, note the fact. */
1602 bInGlobalSection = isglobal;
1604 /* check for multiple global sections */
1605 if (bInGlobalSection)
1607 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1611 if (!bInGlobalSection && bGlobalOnly) return(True);
1613 /* if we have a current service, tidy it up before moving on */
1616 if (iServiceIndex >= 0)
1617 bRetval = service_ok(iServiceIndex);
1619 /* if all is still well, move to the next record in the services array */
1622 /* We put this here to avoid an odd message order if messages are */
1623 /* issued by the post-processing of a previous section. */
1624 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1626 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1628 DEBUG(0,("Failed to add a new service\n"));
1636 /***************************************************************************
1637 Display the contents of the global structure.
1638 ***************************************************************************/
1639 static void dump_globals(void)
1642 printf("Global parameters:\n");
1644 for (i=0;parm_table[i].label;i++)
1645 if (parm_table[i].class == P_GLOBAL &&
1646 parm_table[i].ptr &&
1647 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1649 printf("\t%s: ",parm_table[i].label);
1650 print_parameter(parm_table[i].type,parm_table[i].ptr);
1655 /***************************************************************************
1656 Display the contents of a single services record.
1657 ***************************************************************************/
1658 static void dump_a_service(service *pService)
1661 if (pService == &sDefault)
1662 printf("\nDefault service parameters:\n");
1664 printf("\nService parameters [%s]:\n",pService->szService);
1666 for (i=0;parm_table[i].label;i++)
1667 if (parm_table[i].class == P_LOCAL &&
1668 parm_table[i].ptr &&
1669 (*parm_table[i].label != '-') &&
1670 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1672 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1674 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1675 ((char *)pService) + pdiff,
1676 ((char *)&sDefault) + pdiff))
1678 printf("\t%s: ",parm_table[i].label);
1679 print_parameter(parm_table[i].type,
1680 ((char *)pService) + pdiff);
1687 /***************************************************************************
1688 Display the contents of a single copy structure.
1689 ***************************************************************************/
1690 static void dump_copy_map(BOOL *pcopymap)
1693 if (!pcopymap) return;
1695 printf("\n\tNon-Copied parameters:\n");
1697 for (i=0;parm_table[i].label;i++)
1698 if (parm_table[i].class == P_LOCAL &&
1699 parm_table[i].ptr && !pcopymap[i] &&
1700 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1702 printf("\t\t%s\n",parm_table[i].label);
1707 /***************************************************************************
1708 Return TRUE if the passed service number is within range.
1709 ***************************************************************************/
1710 BOOL lp_snum_ok(int iService)
1712 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1716 /***************************************************************************
1717 auto-load some homes and printer services
1718 ***************************************************************************/
1719 static void lp_add_auto_services(char *str)
1723 int homes = lp_servicenumber(HOMES_NAME);
1724 int printers = lp_servicenumber(PRINTERS_NAME);
1732 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1734 char *home = get_home_dir(p);
1736 if (lp_servicenumber(p) >= 0) continue;
1738 if (home && homes >= 0)
1740 lp_add_home(p,homes,home);
1744 if (printers >= 0 && pcap_printername_ok(p,NULL))
1745 lp_add_printer(p,printers);
1750 /***************************************************************************
1751 auto-load one printer
1752 ***************************************************************************/
1753 static void lp_add_one_printer(char *name,char *comment)
1755 int printers = lp_servicenumber(PRINTERS_NAME);
1758 if (lp_servicenumber(name) < 0)
1760 lp_add_printer(name,printers);
1761 if ((i=lp_servicenumber(name)) >= 0)
1762 string_set(&iSERVICE(i).comment,comment);
1767 /***************************************************************************
1768 auto-load printer services
1769 ***************************************************************************/
1770 static void lp_add_all_printers(void)
1772 int printers = lp_servicenumber(PRINTERS_NAME);
1774 if (printers < 0) return;
1776 pcap_printer_fn(lp_add_one_printer);
1779 /***************************************************************************
1780 have we loaded a services file yet?
1781 ***************************************************************************/
1782 BOOL lp_loaded(void)
1787 /***************************************************************************
1788 unload unused services
1789 ***************************************************************************/
1790 void lp_killunused(BOOL (*snumused)(int ))
1793 for (i=0;i<iNumServices;i++)
1794 if (VALID(i) && !snumused(i))
1796 iSERVICE(i).valid = False;
1797 free_service(pSERVICE(i));
1801 /***************************************************************************
1802 Load the services array from the services file. Return True on success,
1804 ***************************************************************************/
1805 BOOL lp_load(char *pszFname,BOOL global_only)
1810 add_to_file_list(pszFname);
1814 bInGlobalSection = True;
1815 bGlobalOnly = global_only;
1819 strcpy(n2,pszFname);
1820 standard_sub_basic(n2);
1822 /* We get sections first, so have to start 'behind' to make up */
1824 bRetval = pm_process(n2, do_section, do_parameter);
1826 /* finish up the last section */
1827 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1829 if (iServiceIndex >= 0)
1830 bRetval = service_ok(iServiceIndex);
1832 lp_add_auto_services(lp_auto_services());
1833 if (lp_load_printers())
1834 lp_add_all_printers();
1844 /***************************************************************************
1845 return the max number of services
1846 ***************************************************************************/
1847 int lp_numservices(void)
1849 return(iNumServices);
1852 /***************************************************************************
1853 Display the contents of the services array in human-readable form.
1854 ***************************************************************************/
1861 dump_a_service(&sDefault);
1863 for (iService = 0; iService < iNumServices; iService++)
1865 if (VALID(iService))
1867 if (iSERVICE(iService).szService[0] == '\0')
1869 dump_a_service(pSERVICE(iService));
1874 /***************************************************************************
1875 Return the number of the service with the given name, or -1 if it doesn't
1876 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1877 getservicebyname()! This works ONLY if all services have been loaded, and
1878 does not copy the found service.
1879 ***************************************************************************/
1880 int lp_servicenumber(char *pszServiceName)
1884 for (iService = iNumServices - 1; iService >= 0; iService--)
1885 if (VALID(iService) &&
1886 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1890 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1898 /*******************************************************************
1899 get a workgroup - but map to standalone if '*'
1900 ******************************************************************/
1901 char *my_workgroup(void)
1903 char *res = lp_workgroup();
1904 if (*res == '*') return("STANDALONE");
1908 /*******************************************************************
1909 a useful volume label function
1910 ******************************************************************/
1911 char *volume_label(int snum)
1913 char *ret = lp_volume(snum);
1914 if (!*ret) return(lp_servicename(snum));