2 Unix SMB/Netbios implementation.
4 Parameter loading functions
5 Copyright (C) Karl Auer 1993,1994
7 Largely re-written by Andrew Tridgell, September 1994
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * This module provides suitable callback functions for the params
28 * module. It builds the internal table of service details which is
29 * then used by the rest of the server.
33 * 1) add it to the global or service structure definition
34 * 2) add it to the parm_table
35 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
36 * 4) If it's a global then initialise it in init_globals. If a local
37 * (ie. service) parameter then initialise it in the sDefault structure
41 * The configuration file is processed sequentially for speed. It is NOT
42 * accessed randomly as happens in 'real' Windows. For this reason, there
43 * is a fair bit of sequence-dependent code here - ie., code which assumes
44 * that certain things happen before others. In particular, the code which
45 * happens at the boundary between sections is delicately poised, so be
54 extern int DEBUGLEVEL;
55 extern pstring user_socket_options;
58 #define GLOBAL_NAME "global"
63 #define PRINTCAP_NAME "/etc/qconfig"
65 #define PRINTCAP_NAME "/etc/printcap"
70 #define PRINTERS_NAME "printers"
74 #define HOMES_NAME "homes"
77 /* some helpful bits */
78 #define pSERVICE(i) ServicePtrs[i]
79 #define iSERVICE(i) (*pSERVICE(i))
80 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
81 #define VALID(i) iSERVICE(i).valid
83 /* these are the types of parameter we have */
86 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_STRING,P_GSTRING
91 P_LOCAL,P_GLOBAL,P_NONE
95 extern BOOL use_getwd_cache;
97 extern int extra_time_offset;
99 extern int coding_system;
103 * This structure describes global (ie., server-wide) parameters.
107 char *szPrintcapname;
110 char *szDefaultService;
114 char *szServerString;
115 char *szAutoServices;
116 char *szPasswdProgram;
120 char *szSMBPasswdFile;
121 char *szPasswordServer;
122 char *szSocketOptions;
125 char *szDomainController;
127 char *szCharacterSet;
150 BOOL bPreferredMaster;
153 BOOL bEncryptPasswords;
160 BOOL bReadPrediction;
166 static global Globals;
171 * This structure describes a single service.
179 char *szGuestaccount;
180 char *szInvalidUsers;
188 char *szRootPostExec;
189 char *szPrintcommand;
192 char *szLppausecommand;
193 char *szLpresumecommand;
215 BOOL bShortCasePreserve;
239 BOOL bDeleteReadonly;
240 char dummy[3]; /* for alignment */
244 /* This is a default service used to prime a services structure */
245 static service sDefault =
248 NULL, /* szService */
250 NULL, /* szUsername */
251 NULL, /* szGuestAccount */
252 NULL, /* szInvalidUsers */
253 NULL, /* szValidUsers */
254 NULL, /* szAdminUsers */
256 NULL, /* szInclude */
257 NULL, /* szPreExec */
258 NULL, /* szPostExec */
259 NULL, /* szRootPreExec */
260 NULL, /* szRootPostExec */
261 NULL, /* szPrintcommand */
262 NULL, /* szLpqcommand */
263 NULL, /* szLprmcommand */
264 NULL, /* szLppausecommand */
265 NULL, /* szLpresumecommand */
266 NULL, /* szPrintername */
267 NULL, /* szDontdescend */
268 NULL, /* szHostsallow */
269 NULL, /* szHostsdeny */
270 NULL, /* szMagicScript */
271 NULL, /* szMagicOutput */
272 NULL, /* szMangledMap */
274 NULL, /* force user */
275 NULL, /* force group */
277 NULL, /* writelist */
279 0, /* iMinPrintSpace */
280 0755, /* iCreate_mode */
281 0, /* iMaxConnections */
282 CASE_LOWER, /* iDefaultCase */
283 False, /* bAlternatePerm */
284 False, /* revalidate */
285 False, /* case sensitive */
286 False, /* case preserve */
287 False, /* short case preserve */
288 False, /* case mangle */
290 True, /* bHideDotFiles */
291 True, /* bBrowseable */
292 True, /* bAvailable */
293 True, /* bRead_only */
294 True, /* bNo_set_dir */
295 False, /* bGuest_only */
296 False, /* bGuest_ok */
297 False, /* bPrint_ok */
298 False, /* bPostscript */
299 False, /* bMap_system */
300 False, /* bMap_hidden */
301 True, /* bMap_archive */
303 False, /* bStrictLocking */
304 True, /* bShareModes */
305 False, /* bOnlyUser */
306 True, /* bMangledNames */
307 True, /* bWidelinks */
308 False, /* bSyncAlways */
309 '~', /* magic char */
311 False, /* bDeleteReadonly */
317 /* local variables */
318 static service **ServicePtrs = NULL;
319 static int iNumServices = 0;
320 static int iServiceIndex = 0;
321 static BOOL bInGlobalSection = True;
322 static BOOL bGlobalOnly = False;
325 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
327 /* prototypes for the special type handlers */
328 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
329 static BOOL handle_include(char *pszParmValue, char **ptr);
330 static BOOL handle_copy(char *pszParmValue, char **ptr);
331 static BOOL handle_protocol(char *pszParmValue,int *val);
332 static BOOL handle_security(char *pszParmValue,int *val);
333 static BOOL handle_case(char *pszParmValue,int *val);
334 static BOOL handle_printing(char *pszParmValue,int *val);
335 static BOOL handle_character_set(char *pszParmValue,int *val);
337 static BOOL handle_coding_system(char *pszParmValue,int *val);
349 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
350 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
351 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
352 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
353 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
354 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
355 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
356 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
357 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
358 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
359 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
360 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
361 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
362 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
363 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
364 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
365 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
366 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
367 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
368 {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
369 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
370 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
371 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
372 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
373 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
374 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
375 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
376 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
377 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
378 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
379 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
380 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
381 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
382 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
383 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
384 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
385 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
386 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
387 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
388 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
389 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
390 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
391 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
392 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
393 {"workgroup", P_STRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
394 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
395 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
396 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
397 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
398 {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
399 {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
400 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
401 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
402 {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
403 {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
404 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
405 {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
406 {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
407 {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
408 {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
410 {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
412 {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
413 {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
414 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
415 {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
416 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
417 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
418 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
419 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
420 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
421 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, 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.bWINSsupport = True;
580 Globals.bWINSproxy = False;
581 Globals.ReadSize = 16*1024;
584 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
589 /***************************************************************************
590 check if a string is initialised and if not then initialise it
591 ***************************************************************************/
592 static void string_initial(char **s,char *v)
599 /***************************************************************************
600 Initialise the sDefault parameter structure.
601 ***************************************************************************/
602 static void init_locals(void)
604 /* choose defaults depending on the type of printing */
605 switch (Globals.printing)
610 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
611 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
612 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
617 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
618 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
619 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
621 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
622 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
627 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
628 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
629 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
637 /*******************************************************************
638 a convenience rooutine to grab string parameters into a rotating
639 static buffer, and run standard_sub_basic on them. The buffers
640 can be written to by callers
641 ********************************************************************/
642 char *lp_string(char *s)
644 static pstring bufs[10];
648 ret = &bufs[next][0];
654 StrnCpy(ret,s,sizeof(pstring)-1);
656 standard_sub_basic(ret);
662 In this section all the functions that are used to access the
663 parameters from the rest of the program are defined
666 #define FN_GLOBAL_STRING(fn_name,ptr) \
667 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
668 #define FN_GLOBAL_BOOL(fn_name,ptr) \
669 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
670 #define FN_GLOBAL_CHAR(fn_name,ptr) \
671 char fn_name(void) {return(*(char *)(ptr));}
672 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
673 int fn_name(void) {return(*(int *)(ptr));}
675 #define FN_LOCAL_STRING(fn_name,val) \
676 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
677 #define FN_LOCAL_BOOL(fn_name,val) \
678 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
679 #define FN_LOCAL_CHAR(fn_name,val) \
680 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
681 #define FN_LOCAL_INTEGER(fn_name,val) \
682 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
684 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
685 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
686 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
687 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
688 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
689 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
690 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
691 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
692 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
693 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
694 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
695 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
696 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
697 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
698 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
699 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
700 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
701 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
702 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
703 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
704 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
705 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
706 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
708 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
709 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
710 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
711 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
712 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
713 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
714 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
715 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
716 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
717 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
718 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
719 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
720 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
721 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
722 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
723 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
724 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
726 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
727 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
728 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
729 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
730 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
731 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
732 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
733 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
734 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
735 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
736 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
737 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
738 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
739 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
740 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
741 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
742 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
744 FN_LOCAL_STRING(lp_preexec,szPreExec)
745 FN_LOCAL_STRING(lp_postexec,szPostExec)
746 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
747 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
748 FN_LOCAL_STRING(lp_servicename,szService)
749 FN_LOCAL_STRING(lp_pathname,szPath)
750 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
751 FN_LOCAL_STRING(lp_username,szUsername)
752 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
753 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
754 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
755 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
756 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
757 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
758 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
759 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
760 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
761 FN_LOCAL_STRING(lp_printername,szPrintername)
762 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
763 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
764 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
765 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
766 FN_LOCAL_STRING(lp_comment,comment)
767 FN_LOCAL_STRING(lp_force_user,force_user)
768 FN_LOCAL_STRING(lp_force_group,force_group)
769 FN_LOCAL_STRING(lp_readlist,readlist)
770 FN_LOCAL_STRING(lp_writelist,writelist)
771 FN_LOCAL_STRING(lp_volume,volume)
772 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
774 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
775 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
776 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
777 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
778 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
779 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
780 FN_LOCAL_BOOL(lp_status,status)
781 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
782 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
783 FN_LOCAL_BOOL(lp_readonly,bRead_only)
784 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
785 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
786 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
787 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
788 FN_LOCAL_BOOL(lp_postscript,bPostscript)
789 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
790 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
791 FN_LOCAL_BOOL(lp_locking,bLocking)
792 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
793 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
794 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
795 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
796 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
797 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
798 FN_LOCAL_BOOL(lp_map_system,bMap_system)
799 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
801 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
802 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
803 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
804 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
806 FN_LOCAL_CHAR(lp_magicchar,magic_char)
810 /* local prototypes */
811 static int strwicmp( char *psz1, char *psz2 );
812 static int map_parameter( char *pszParmName);
813 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
814 static int getservicebyname(char *pszServiceName, service *pserviceDest);
815 static void copy_service( service *pserviceDest,
816 service *pserviceSource,
817 BOOL *pcopymapDest );
818 static BOOL service_ok(int iService);
819 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
820 static BOOL do_section(char *pszSectionName);
821 static void dump_globals(void);
822 static void dump_a_service(service *pService);
823 static void init_copymap(service *pservice);
826 /***************************************************************************
827 initialise a service to the defaults
828 ***************************************************************************/
829 static void init_service(service *pservice)
831 bzero((char *)pservice,sizeof(service));
832 copy_service(pservice,&sDefault,NULL);
836 /***************************************************************************
837 free the dynamically allocated parts of a service struct
838 ***************************************************************************/
839 static void free_service(service *pservice)
845 for (i=0;parm_table[i].label;i++)
846 if (parm_table[i].type == P_STRING && parm_table[i].class == P_LOCAL)
847 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
850 /***************************************************************************
851 add a new service to the services array initialising it with the given
853 ***************************************************************************/
854 static int add_a_service(service *pservice, char *name)
858 int num_to_alloc = iNumServices+1;
860 tservice = *pservice;
862 /* it might already exist */
865 i = getservicebyname(name,NULL);
870 /* find an invalid one */
871 for (i=0;i<iNumServices;i++)
872 if (!pSERVICE(i)->valid)
875 /* if not, then create one */
876 if (i == iNumServices)
878 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
880 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
882 if (!ServicePtrs || !pSERVICE(iNumServices))
888 free_service(pSERVICE(i));
890 pSERVICE(i)->valid = True;
892 init_service(pSERVICE(i));
893 copy_service(pSERVICE(i),&tservice,NULL);
895 string_set(&iSERVICE(i).szService,name);
900 /***************************************************************************
901 add a new home service, with the specified home directory, defaults coming
903 ***************************************************************************/
904 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
906 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
911 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
912 string_set(&iSERVICE(i).szPath,pszHomedir);
913 if (!(*(iSERVICE(i).comment)))
916 sprintf(comment,"Home directory of %s",pszHomename);
917 string_set(&iSERVICE(i).comment,comment);
919 iSERVICE(i).bAvailable = sDefault.bAvailable;
920 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
922 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
927 /***************************************************************************
928 add a new service, based on an old one
929 ***************************************************************************/
930 int lp_add_service(char *pszService, int iDefaultService)
932 return(add_a_service(pSERVICE(iDefaultService),pszService));
936 /***************************************************************************
938 ***************************************************************************/
939 static BOOL lp_add_ipc(void)
942 int i = add_a_service(&sDefault,"IPC$");
947 sprintf(comment,"IPC Service (%s)",lp_serverstring());
949 string_set(&iSERVICE(i).szPath,"/tmp");
950 string_set(&iSERVICE(i).szUsername,"");
951 string_set(&iSERVICE(i).comment,comment);
952 iSERVICE(i).status = False;
953 iSERVICE(i).iMaxConnections = 0;
954 iSERVICE(i).bAvailable = True;
955 iSERVICE(i).bRead_only = True;
956 iSERVICE(i).bGuest_only = False;
957 iSERVICE(i).bGuest_ok = True;
958 iSERVICE(i).bPrint_ok = False;
959 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
961 DEBUG(3,("adding IPC service\n"));
967 /***************************************************************************
968 add a new printer service, with defaults coming from service iFrom
969 ***************************************************************************/
970 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
972 char *comment = "From Printcap";
973 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
978 /* note that we do NOT default the availability flag to True - */
979 /* we take it from the default service passed. This allows all */
980 /* dynamic printers to be disabled by disabling the [printers] */
981 /* entry (if/when the 'available' keyword is implemented!). */
983 /* the printer name is set to the service name. */
984 string_set(&iSERVICE(i).szPrintername,pszPrintername);
985 string_set(&iSERVICE(i).comment,comment);
986 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
988 DEBUG(3,("adding printer service %s\n",pszPrintername));
994 /***************************************************************************
995 Do a case-insensitive, whitespace-ignoring string compare.
996 ***************************************************************************/
997 static int strwicmp(char *psz1, char *psz2)
999 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1000 /* appropriate value. */
1010 /* sync the strings on first non-whitespace */
1013 while (isspace(*psz1))
1015 while (isspace(*psz2))
1017 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1022 return (*psz1 - *psz2);
1025 /***************************************************************************
1026 Map a parameter's string representation to something we can use.
1027 Returns False if the parameter string is not recognised, else TRUE.
1028 ***************************************************************************/
1029 static int map_parameter(char *pszParmName)
1033 if (*pszParmName == '-')
1036 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1037 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1040 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1045 /***************************************************************************
1046 Set a boolean variable from the text value stored in the passed string.
1047 Returns True in success, False if the passed string does not correctly
1048 represent a boolean.
1049 ***************************************************************************/
1050 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1055 if (strwicmp(pszParmValue, "yes") == 0 ||
1056 strwicmp(pszParmValue, "true") == 0 ||
1057 strwicmp(pszParmValue, "1") == 0)
1060 if (strwicmp(pszParmValue, "no") == 0 ||
1061 strwicmp(pszParmValue, "False") == 0 ||
1062 strwicmp(pszParmValue, "0") == 0)
1066 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1073 /***************************************************************************
1074 Find a service by name. Otherwise works like get_service.
1075 ***************************************************************************/
1076 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1080 for (iService = iNumServices - 1; iService >= 0; iService--)
1081 if (VALID(iService) &&
1082 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1084 if (pserviceDest != NULL)
1085 copy_service(pserviceDest, pSERVICE(iService), NULL);
1094 /***************************************************************************
1095 Copy a service structure to another
1097 If pcopymapDest is NULL then copy all fields
1098 ***************************************************************************/
1099 static void copy_service(service *pserviceDest,
1100 service *pserviceSource,
1104 BOOL bcopyall = (pcopymapDest == NULL);
1106 for (i=0;parm_table[i].label;i++)
1107 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1108 (bcopyall || pcopymapDest[i]))
1110 void *def_ptr = parm_table[i].ptr;
1112 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1114 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1116 switch (parm_table[i].type)
1120 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1125 *(int *)dest_ptr = *(int *)src_ptr;
1129 *(char *)dest_ptr = *(char *)src_ptr;
1133 string_set(dest_ptr,*(char **)src_ptr);
1142 init_copymap(pserviceDest);
1143 if (pserviceSource->copymap)
1144 memcpy((void *)pserviceDest->copymap,
1145 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1149 /***************************************************************************
1150 Check a service for consistency. Return False if the service is in any way
1151 incomplete or faulty, else True.
1152 ***************************************************************************/
1153 static BOOL service_ok(int iService)
1158 if (iSERVICE(iService).szService[0] == '\0')
1160 DEBUG(0,( "The following message indicates an internal error:\n"));
1161 DEBUG(0,( "No service name in service entry.\n"));
1165 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1166 /* I can't see why you'd want a non-printable printer service... */
1167 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1168 if (!iSERVICE(iService).bPrint_ok)
1170 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1171 iSERVICE(iService).szService));
1172 iSERVICE(iService).bPrint_ok = True;
1175 if (iSERVICE(iService).szPath[0] == '\0' &&
1176 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1178 DEBUG(0,("No path in service %s - using /tmp\n",iSERVICE(iService).szService));
1179 string_set(&iSERVICE(iService).szPath,"/tmp");
1182 /* If a service is flagged unavailable, log the fact at level 0. */
1183 if (!iSERVICE(iService).bAvailable)
1184 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1185 iSERVICE(iService).szService));
1190 static struct file_lists {
1191 struct file_lists *next;
1194 } *file_lists = NULL;
1196 /*******************************************************************
1197 keep a linked list of all config files so we know when one has changed
1198 it's date and needs to be reloaded
1199 ********************************************************************/
1200 static void add_to_file_list(char *fname)
1202 struct file_lists *f=file_lists;
1205 if (f->name && !strcmp(f->name,fname)) break;
1210 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1212 f->next = file_lists;
1213 f->name = strdup(fname);
1224 standard_sub_basic(n2);
1225 f->modtime = file_modtime(n2);
1230 /*******************************************************************
1231 check if a config file has changed date
1232 ********************************************************************/
1233 BOOL lp_file_list_changed(void)
1235 struct file_lists *f = file_lists;
1239 standard_sub_basic(n2);
1240 if (f->modtime != file_modtime(n2)) return(True);
1247 /***************************************************************************
1248 handle the interpretation of the coding system parameter
1249 *************************************************************************/
1250 static BOOL handle_coding_system(char *pszParmValue,int *val)
1252 *val = interpret_coding_system(pszParmValue,*val);
1257 /***************************************************************************
1258 handle the interpretation of the character set system parameter
1259 ***************************************************************************/
1260 static BOOL handle_character_set(char *pszParmValue,int *val)
1262 string_set(&Globals.szCharacterSet,pszParmValue);
1263 *val = interpret_character_set(pszParmValue,*val);
1268 /***************************************************************************
1269 handle the interpretation of the protocol parameter
1270 ***************************************************************************/
1271 static BOOL handle_protocol(char *pszParmValue,int *val)
1273 *val = interpret_protocol(pszParmValue,*val);
1277 /***************************************************************************
1278 handle the interpretation of the security parameter
1279 ***************************************************************************/
1280 static BOOL handle_security(char *pszParmValue,int *val)
1282 *val = interpret_security(pszParmValue,*val);
1286 /***************************************************************************
1287 handle the interpretation of the default case
1288 ***************************************************************************/
1289 static BOOL handle_case(char *pszParmValue,int *val)
1291 if (strequal(pszParmValue,"LOWER"))
1293 else if (strequal(pszParmValue,"UPPER"))
1298 /***************************************************************************
1299 handle the interpretation of the printing system
1300 ***************************************************************************/
1301 static BOOL handle_printing(char *pszParmValue,int *val)
1303 if (strequal(pszParmValue,"sysv"))
1305 else if (strequal(pszParmValue,"aix"))
1307 else if (strequal(pszParmValue,"hpux"))
1309 else if (strequal(pszParmValue,"bsd"))
1311 else if (strequal(pszParmValue,"qnx"))
1313 else if (strequal(pszParmValue,"plp"))
1318 /***************************************************************************
1319 handle the valid chars lines
1320 ***************************************************************************/
1321 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1323 string_set(ptr,pszParmValue);
1325 add_char_string(pszParmValue);
1330 /***************************************************************************
1331 handle the include operation
1332 ***************************************************************************/
1333 static BOOL handle_include(char *pszParmValue,char **ptr)
1336 strcpy(fname,pszParmValue);
1338 add_to_file_list(fname);
1340 standard_sub_basic(fname);
1342 string_set(ptr,fname);
1344 if (file_exist(fname,NULL))
1345 return(pm_process(fname, do_section, do_parameter));
1347 DEBUG(2,("Can't find include file %s\n",fname));
1353 /***************************************************************************
1354 handle the interpretation of the copy parameter
1355 ***************************************************************************/
1356 static BOOL handle_copy(char *pszParmValue,char **ptr)
1360 service serviceTemp;
1362 string_set(ptr,pszParmValue);
1364 init_service(&serviceTemp);
1368 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1370 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1372 if (iTemp == iServiceIndex)
1374 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1379 copy_service(pSERVICE(iServiceIndex),
1381 iSERVICE(iServiceIndex).copymap);
1387 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1392 free_service(&serviceTemp);
1397 /***************************************************************************
1398 initialise a copymap
1399 ***************************************************************************/
1400 static void init_copymap(service *pservice)
1403 if (pservice->copymap) free(pservice->copymap);
1404 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1405 if (!pservice->copymap)
1406 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1408 for (i=0;i<NUMPARAMETERS;i++)
1409 pservice->copymap[i] = True;
1413 /***************************************************************************
1414 Process a parameter.
1415 ***************************************************************************/
1416 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1419 void *parm_ptr=NULL; /* where we are going to store the result */
1422 if (!bInGlobalSection && bGlobalOnly) return(True);
1424 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1426 parmnum = map_parameter(pszParmName);
1430 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1434 def_ptr = parm_table[parmnum].ptr;
1436 /* we might point at a service, the default service or a global */
1437 if (bInGlobalSection)
1441 if (parm_table[parmnum].class == P_GLOBAL)
1443 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1446 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1449 if (!bInGlobalSection)
1452 if (!iSERVICE(iServiceIndex).copymap)
1453 init_copymap(pSERVICE(iServiceIndex));
1455 /* this handles the aliases - set the copymap for other entries with
1456 the same data pointer */
1457 for (i=0;parm_table[i].label;i++)
1458 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1459 iSERVICE(iServiceIndex).copymap[i] = False;
1462 /* if it is a special case then go ahead */
1463 if (parm_table[parmnum].special)
1465 parm_table[parmnum].special(pszParmValue,parm_ptr);
1469 /* now switch on the type of variable it is */
1470 switch (parm_table[parmnum].type)
1473 set_boolean(parm_ptr,pszParmValue);
1477 set_boolean(parm_ptr,pszParmValue);
1478 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1482 *(int *)parm_ptr = atoi(pszParmValue);
1486 *(char *)parm_ptr = *pszParmValue;
1490 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1494 string_set(parm_ptr,pszParmValue);
1498 strcpy((char *)parm_ptr,pszParmValue);
1505 /***************************************************************************
1506 print a parameter of the specified type
1507 ***************************************************************************/
1508 static void print_parameter(parm_type type,void *ptr)
1513 printf("%s",BOOLSTR(*(BOOL *)ptr));
1517 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1521 printf("%d",*(int *)ptr);
1525 printf("%c",*(char *)ptr);
1529 printf("0%o",*(int *)ptr);
1534 printf("%s",(char *)ptr);
1539 printf("%s",*(char **)ptr);
1545 /***************************************************************************
1546 check if two parameters are equal
1547 ***************************************************************************/
1548 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1554 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1558 return(*((int *)ptr1) == *((int *)ptr2));
1561 return(*((char *)ptr1) == *((char *)ptr2));
1565 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1566 if (p1 && !*p1) p1 = NULL;
1567 if (p2 && !*p2) p2 = NULL;
1568 return(p1==p2 || strequal(p1,p2));
1572 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1573 if (p1 && !*p1) p1 = NULL;
1574 if (p2 && !*p2) p2 = NULL;
1575 return(p1==p2 || strequal(p1,p2));
1581 /***************************************************************************
1582 Process a new section (service). At this stage all sections are services.
1583 Later we'll have special sections that permit server parameters to be set.
1584 Returns True on success, False on failure.
1585 ***************************************************************************/
1586 static BOOL do_section(char *pszSectionName)
1589 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1590 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1593 /* if we were in a global section then do the local inits */
1594 if (bInGlobalSection && !isglobal)
1597 /* if we've just struck a global section, note the fact. */
1598 bInGlobalSection = isglobal;
1600 /* check for multiple global sections */
1601 if (bInGlobalSection)
1603 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1607 if (!bInGlobalSection && bGlobalOnly) return(True);
1609 /* if we have a current service, tidy it up before moving on */
1612 if (iServiceIndex >= 0)
1613 bRetval = service_ok(iServiceIndex);
1615 /* if all is still well, move to the next record in the services array */
1618 /* We put this here to avoid an odd message order if messages are */
1619 /* issued by the post-processing of a previous section. */
1620 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1622 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1624 DEBUG(0,("Failed to add a new service\n"));
1632 /***************************************************************************
1633 Display the contents of the global structure.
1634 ***************************************************************************/
1635 static void dump_globals(void)
1638 printf("Global parameters:\n");
1640 for (i=0;parm_table[i].label;i++)
1641 if (parm_table[i].class == P_GLOBAL &&
1642 parm_table[i].ptr &&
1643 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1645 printf("\t%s: ",parm_table[i].label);
1646 print_parameter(parm_table[i].type,parm_table[i].ptr);
1651 /***************************************************************************
1652 Display the contents of a single services record.
1653 ***************************************************************************/
1654 static void dump_a_service(service *pService)
1657 if (pService == &sDefault)
1658 printf("\nDefault service parameters:\n");
1660 printf("\nService parameters [%s]:\n",pService->szService);
1662 for (i=0;parm_table[i].label;i++)
1663 if (parm_table[i].class == P_LOCAL &&
1664 parm_table[i].ptr &&
1665 (*parm_table[i].label != '-') &&
1666 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1668 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1670 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1671 ((char *)pService) + pdiff,
1672 ((char *)&sDefault) + pdiff))
1674 printf("\t%s: ",parm_table[i].label);
1675 print_parameter(parm_table[i].type,
1676 ((char *)pService) + pdiff);
1683 /***************************************************************************
1684 Display the contents of a single copy structure.
1685 ***************************************************************************/
1686 static void dump_copy_map(BOOL *pcopymap)
1689 if (!pcopymap) return;
1691 printf("\n\tNon-Copied parameters:\n");
1693 for (i=0;parm_table[i].label;i++)
1694 if (parm_table[i].class == P_LOCAL &&
1695 parm_table[i].ptr && !pcopymap[i] &&
1696 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1698 printf("\t\t%s\n",parm_table[i].label);
1703 /***************************************************************************
1704 Return TRUE if the passed service number is within range.
1705 ***************************************************************************/
1706 BOOL lp_snum_ok(int iService)
1708 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1712 /***************************************************************************
1713 auto-load some homes and printer services
1714 ***************************************************************************/
1715 static void lp_add_auto_services(char *str)
1719 int homes = lp_servicenumber(HOMES_NAME);
1720 int printers = lp_servicenumber(PRINTERS_NAME);
1728 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1730 char *home = get_home_dir(p);
1732 if (lp_servicenumber(p) >= 0) continue;
1734 if (home && homes >= 0)
1736 lp_add_home(p,homes,home);
1740 if (printers >= 0 && pcap_printername_ok(p,NULL))
1741 lp_add_printer(p,printers);
1746 /***************************************************************************
1747 auto-load one printer
1748 ***************************************************************************/
1749 static void lp_add_one_printer(char *name,char *comment)
1751 int printers = lp_servicenumber(PRINTERS_NAME);
1754 if (lp_servicenumber(name) < 0)
1756 lp_add_printer(name,printers);
1757 if ((i=lp_servicenumber(name)) >= 0)
1758 string_set(&iSERVICE(i).comment,comment);
1763 /***************************************************************************
1764 auto-load printer services
1765 ***************************************************************************/
1766 static void lp_add_all_printers(void)
1768 int printers = lp_servicenumber(PRINTERS_NAME);
1770 if (printers < 0) return;
1772 pcap_printer_fn(lp_add_one_printer);
1775 /***************************************************************************
1776 have we loaded a services file yet?
1777 ***************************************************************************/
1778 BOOL lp_loaded(void)
1783 /***************************************************************************
1784 unload unused services
1785 ***************************************************************************/
1786 void lp_killunused(BOOL (*snumused)(int ))
1789 for (i=0;i<iNumServices;i++)
1790 if (VALID(i) && !snumused(i))
1792 iSERVICE(i).valid = False;
1793 free_service(pSERVICE(i));
1797 /***************************************************************************
1798 Load the services array from the services file. Return True on success,
1800 ***************************************************************************/
1801 BOOL lp_load(char *pszFname,BOOL global_only)
1806 add_to_file_list(pszFname);
1810 bInGlobalSection = True;
1811 bGlobalOnly = global_only;
1815 strcpy(n2,pszFname);
1816 standard_sub_basic(n2);
1818 /* We get sections first, so have to start 'behind' to make up */
1820 bRetval = pm_process(n2, do_section, do_parameter);
1822 /* finish up the last section */
1823 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1825 if (iServiceIndex >= 0)
1826 bRetval = service_ok(iServiceIndex);
1828 lp_add_auto_services(lp_auto_services());
1829 if (lp_load_printers())
1830 lp_add_all_printers();
1840 /***************************************************************************
1841 return the max number of services
1842 ***************************************************************************/
1843 int lp_numservices(void)
1845 return(iNumServices);
1848 /***************************************************************************
1849 Display the contents of the services array in human-readable form.
1850 ***************************************************************************/
1857 dump_a_service(&sDefault);
1859 for (iService = 0; iService < iNumServices; iService++)
1861 if (VALID(iService))
1863 if (iSERVICE(iService).szService[0] == '\0')
1865 dump_a_service(pSERVICE(iService));
1870 /***************************************************************************
1871 Return the number of the service with the given name, or -1 if it doesn't
1872 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1873 getservicebyname()! This works ONLY if all services have been loaded, and
1874 does not copy the found service.
1875 ***************************************************************************/
1876 int lp_servicenumber(char *pszServiceName)
1880 for (iService = iNumServices - 1; iService >= 0; iService--)
1881 if (VALID(iService) &&
1882 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1886 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1894 /*******************************************************************
1895 get a workgroup - but map to standalone if '*'
1896 ******************************************************************/
1897 char *my_workgroup(void)
1899 char *res = lp_workgroup();
1900 if (*res == '*') return("STANDALONE");
1904 /*******************************************************************
1905 a useful volume label function
1906 ******************************************************************/
1907 char *volume_label(int snum)
1909 char *ret = lp_volume(snum);
1910 if (!*ret) return(lp_servicename(snum));