loadparm.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; either version 3 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License along
  13. * with this program; if not, visit the http://fsf.org website.
  14. */
  15. /* This is based on loadparm.c from Samba, written by Andrew Tridgell
  16. * and Karl Auer. Some of the changes are:
  17. *
  18. * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
  19. * Copyright (C) 2003-2009 Wayne Davison <wayned@samba.org>
  20. */
  21. /* Load parameters.
  22. *
  23. * This module provides suitable callback functions for the params
  24. * module. It builds the internal table of service details which is
  25. * then used by the rest of the server.
  26. *
  27. * To add a parameter:
  28. *
  29. * 1) add it to the global or service structure definition
  30. * 2) add it to the parm_table
  31. * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
  32. * 4) If it's a global then initialise it in init_globals. If a local
  33. * (ie. service) parameter then initialise it in the sDefault structure
  34. *
  35. *
  36. * Notes:
  37. * The configuration file is processed sequentially for speed. It is NOT
  38. * accessed randomly as happens in 'real' Windows. For this reason, there
  39. * is a fair bit of sequence-dependent code here - ie., code which assumes
  40. * that certain things happen before others. In particular, the code which
  41. * happens at the boundary between sections is delicately poised, so be
  42. * careful!
  43. *
  44. */
  45. /* TODO: Parameter to set debug level on server. */
  46. #include "rsync.h"
  47. #include "ifuncs.h"
  48. #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
  49. #define strequal(a,b) (strcasecmp(a,b)==0)
  50. #define BOOLSTR(b) ((b) ? "Yes" : "No")
  51. typedef char pstring[1024];
  52. #define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
  53. #ifndef LOG_DAEMON
  54. #define LOG_DAEMON 0
  55. #endif
  56. #define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
  57. " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg"
  58. /* the following are used by loadparm for option lists */
  59. typedef enum
  60. {
  61. P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
  62. P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
  63. } parm_type;
  64. typedef enum
  65. {
  66. P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
  67. } parm_class;
  68. struct enum_list {
  69. int value;
  70. char *name;
  71. };
  72. struct parm_struct
  73. {
  74. char *label;
  75. parm_type type;
  76. parm_class class;
  77. void *ptr;
  78. struct enum_list *enum_list;
  79. unsigned flags;
  80. };
  81. #ifndef GLOBAL_NAME
  82. #define GLOBAL_NAME "global"
  83. #endif
  84. /* some helpful bits */
  85. #define pSERVICE(i) ServicePtrs[i]
  86. #define iSERVICE(i) (*pSERVICE(i))
  87. #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
  88. /*
  89. * This structure describes global (ie., server-wide) parameters.
  90. */
  91. typedef struct
  92. {
  93. char *bind_address;
  94. char *motd_file;
  95. char *pid_file;
  96. char *socket_options;
  97. int rsync_port;
  98. } global;
  99. static global Globals;
  100. /*
  101. * This structure describes a single service. Their order must match the
  102. * initializers below, which you can accomplish by keeping each sub-section
  103. * sorted. (e.g. in vim, just visually select each subsection and use !sort.)
  104. */
  105. typedef struct
  106. {
  107. char *auth_users;
  108. char *charset;
  109. char *comment;
  110. char *dont_compress;
  111. char *exclude;
  112. char *exclude_from;
  113. char *filter;
  114. char *gid;
  115. char *hosts_allow;
  116. char *hosts_deny;
  117. char *include;
  118. char *include_from;
  119. char *incoming_chmod;
  120. char *lock_file;
  121. char *log_file;
  122. char *log_format;
  123. char *name;
  124. char *outgoing_chmod;
  125. char *path;
  126. char *postxfer_exec;
  127. char *prexfer_exec;
  128. char *refuse_options;
  129. char *secrets_file;
  130. char *temp_dir;
  131. char *uid;
  132. int max_connections;
  133. int max_verbosity;
  134. int syslog_facility;
  135. int timeout;
  136. BOOL fake_super;
  137. BOOL ignore_errors;
  138. BOOL ignore_nonreadable;
  139. BOOL list;
  140. BOOL munge_symlinks;
  141. BOOL numeric_ids;
  142. BOOL read_only;
  143. BOOL strict_modes;
  144. BOOL transfer_logging;
  145. BOOL use_chroot;
  146. BOOL write_only;
  147. } service;
  148. /* This is a default service used to prime a services structure. In order
  149. * to make these easy to keep sorted in the same way as the variables
  150. * above, use the variable name in the leading comment, including a
  151. * trailing ';' (to avoid a sorting problem with trailing digits). */
  152. static service sDefault =
  153. {
  154. /* auth_users; */ NULL,
  155. /* charset; */ NULL,
  156. /* comment; */ NULL,
  157. /* dont_compress; */ DEFAULT_DONT_COMPRESS,
  158. /* exclude; */ NULL,
  159. /* exclude_from; */ NULL,
  160. /* filter; */ NULL,
  161. /* gid; */ NOBODY_GROUP,
  162. /* hosts_allow; */ NULL,
  163. /* hosts_deny; */ NULL,
  164. /* include; */ NULL,
  165. /* include_from; */ NULL,
  166. /* incoming_chmod; */ NULL,
  167. /* lock_file; */ DEFAULT_LOCK_FILE,
  168. /* log_file; */ NULL,
  169. /* log_format; */ "%o %h [%a] %m (%u) %f %l",
  170. /* name; */ NULL,
  171. /* outgoing_chmod; */ NULL,
  172. /* path; */ NULL,
  173. /* postxfer_exec; */ NULL,
  174. /* prexfer_exec; */ NULL,
  175. /* refuse_options; */ NULL,
  176. /* secrets_file; */ NULL,
  177. /* temp_dir; */ NULL,
  178. /* uid; */ NOBODY_USER,
  179. /* max_connections; */ 0,
  180. /* max_verbosity; */ 1,
  181. /* syslog_facility; */ LOG_DAEMON,
  182. /* timeout; */ 0,
  183. /* fake_super; */ False,
  184. /* ignore_errors; */ False,
  185. /* ignore_nonreadable; */ False,
  186. /* list; */ True,
  187. /* munge_symlinks; */ (BOOL)-1,
  188. /* numeric_ids; */ (BOOL)-1,
  189. /* read_only; */ True,
  190. /* strict_modes; */ True,
  191. /* transfer_logging; */ False,
  192. /* use_chroot; */ True,
  193. /* write_only; */ False,
  194. };
  195. /* local variables */
  196. static service **ServicePtrs = NULL;
  197. static int iNumServices = 0;
  198. static int iServiceIndex = 0;
  199. static BOOL bInGlobalSection = True;
  200. #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
  201. static struct enum_list enum_facilities[] = {
  202. #ifdef LOG_AUTH
  203. { LOG_AUTH, "auth" },
  204. #endif
  205. #ifdef LOG_AUTHPRIV
  206. { LOG_AUTHPRIV, "authpriv" },
  207. #endif
  208. #ifdef LOG_CRON
  209. { LOG_CRON, "cron" },
  210. #endif
  211. #ifdef LOG_DAEMON
  212. { LOG_DAEMON, "daemon" },
  213. #endif
  214. #ifdef LOG_FTP
  215. { LOG_FTP, "ftp" },
  216. #endif
  217. #ifdef LOG_KERN
  218. { LOG_KERN, "kern" },
  219. #endif
  220. #ifdef LOG_LPR
  221. { LOG_LPR, "lpr" },
  222. #endif
  223. #ifdef LOG_MAIL
  224. { LOG_MAIL, "mail" },
  225. #endif
  226. #ifdef LOG_NEWS
  227. { LOG_NEWS, "news" },
  228. #endif
  229. #ifdef LOG_AUTH
  230. { LOG_AUTH, "security" },
  231. #endif
  232. #ifdef LOG_SYSLOG
  233. { LOG_SYSLOG, "syslog" },
  234. #endif
  235. #ifdef LOG_USER
  236. { LOG_USER, "user" },
  237. #endif
  238. #ifdef LOG_UUCP
  239. { LOG_UUCP, "uucp" },
  240. #endif
  241. #ifdef LOG_LOCAL0
  242. { LOG_LOCAL0, "local0" },
  243. #endif
  244. #ifdef LOG_LOCAL1
  245. { LOG_LOCAL1, "local1" },
  246. #endif
  247. #ifdef LOG_LOCAL2
  248. { LOG_LOCAL2, "local2" },
  249. #endif
  250. #ifdef LOG_LOCAL3
  251. { LOG_LOCAL3, "local3" },
  252. #endif
  253. #ifdef LOG_LOCAL4
  254. { LOG_LOCAL4, "local4" },
  255. #endif
  256. #ifdef LOG_LOCAL5
  257. { LOG_LOCAL5, "local5" },
  258. #endif
  259. #ifdef LOG_LOCAL6
  260. { LOG_LOCAL6, "local6" },
  261. #endif
  262. #ifdef LOG_LOCAL7
  263. { LOG_LOCAL7, "local7" },
  264. #endif
  265. { -1, NULL }};
  266. /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
  267. static struct parm_struct parm_table[] =
  268. {
  269. {"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
  270. {"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
  271. {"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
  272. {"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
  273. {"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
  274. {"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
  275. {"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0},
  276. {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
  277. {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
  278. {"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
  279. {"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
  280. {"fake super", P_BOOL, P_LOCAL, &sDefault.fake_super, NULL,0},
  281. {"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
  282. {"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
  283. {"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
  284. {"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL,0},
  285. {"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors, NULL,0},
  286. {"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable,NULL,0},
  287. {"include from", P_STRING, P_LOCAL, &sDefault.include_from, NULL,0},
  288. {"include", P_STRING, P_LOCAL, &sDefault.include, NULL,0},
  289. {"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
  290. {"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
  291. {"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
  292. {"log file", P_STRING, P_LOCAL, &sDefault.log_file, NULL,0},
  293. {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
  294. {"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
  295. {"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
  296. {"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0},
  297. {"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
  298. {"numeric ids", P_BOOL, P_LOCAL, &sDefault.numeric_ids, NULL,0},
  299. {"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
  300. {"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
  301. #ifdef HAVE_PUTENV
  302. {"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec, NULL,0},
  303. {"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL,0},
  304. #endif
  305. {"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL,0},
  306. {"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
  307. {"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
  308. {"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
  309. {"syslog facility", P_ENUM, P_LOCAL, &sDefault.syslog_facility,enum_facilities,0},
  310. {"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
  311. {"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
  312. {"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
  313. {"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL,0},
  314. {"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL,0},
  315. {"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL,0},
  316. {NULL, P_BOOL, P_NONE, NULL, NULL,0}
  317. };
  318. /***************************************************************************
  319. * Initialise the global parameter structure.
  320. ***************************************************************************/
  321. static void init_globals(void)
  322. {
  323. memset(&Globals, 0, sizeof Globals);
  324. }
  325. /***************************************************************************
  326. * Initialise the sDefault parameter structure.
  327. ***************************************************************************/
  328. static void init_locals(void)
  329. {
  330. }
  331. /*
  332. In this section all the functions that are used to access the
  333. parameters from the rest of the program are defined
  334. */
  335. #define FN_GLOBAL_STRING(fn_name,ptr) \
  336. char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
  337. #define FN_GLOBAL_BOOL(fn_name,ptr) \
  338. BOOL fn_name(void) {return(*(BOOL *)(ptr));}
  339. #define FN_GLOBAL_CHAR(fn_name,ptr) \
  340. char fn_name(void) {return(*(char *)(ptr));}
  341. #define FN_GLOBAL_INTEGER(fn_name,ptr) \
  342. int fn_name(void) {return(*(int *)(ptr));}
  343. #define FN_LOCAL_STRING(fn_name,val) \
  344. char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
  345. #define FN_LOCAL_BOOL(fn_name,val) \
  346. BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
  347. #define FN_LOCAL_CHAR(fn_name,val) \
  348. char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
  349. #define FN_LOCAL_INTEGER(fn_name,val) \
  350. int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
  351. FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
  352. FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
  353. FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
  354. FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
  355. FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
  356. FN_LOCAL_STRING(lp_auth_users, auth_users)
  357. FN_LOCAL_STRING(lp_charset, charset)
  358. FN_LOCAL_STRING(lp_comment, comment)
  359. FN_LOCAL_STRING(lp_dont_compress, dont_compress)
  360. FN_LOCAL_STRING(lp_exclude, exclude)
  361. FN_LOCAL_STRING(lp_exclude_from, exclude_from)
  362. FN_LOCAL_STRING(lp_filter, filter)
  363. FN_LOCAL_STRING(lp_gid, gid)
  364. FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
  365. FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
  366. FN_LOCAL_STRING(lp_include, include)
  367. FN_LOCAL_STRING(lp_include_from, include_from)
  368. FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
  369. FN_LOCAL_STRING(lp_lock_file, lock_file)
  370. FN_LOCAL_STRING(lp_log_file, log_file)
  371. FN_LOCAL_STRING(lp_log_format, log_format)
  372. FN_LOCAL_STRING(lp_name, name)
  373. FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
  374. FN_LOCAL_STRING(lp_path, path)
  375. FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
  376. FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
  377. FN_LOCAL_STRING(lp_refuse_options, refuse_options)
  378. FN_LOCAL_STRING(lp_secrets_file, secrets_file)
  379. FN_LOCAL_STRING(lp_temp_dir, temp_dir)
  380. FN_LOCAL_STRING(lp_uid, uid)
  381. FN_LOCAL_INTEGER(lp_max_connections, max_connections)
  382. FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
  383. FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
  384. FN_LOCAL_INTEGER(lp_timeout, timeout)
  385. FN_LOCAL_BOOL(lp_fake_super, fake_super)
  386. FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
  387. FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
  388. FN_LOCAL_BOOL(lp_list, list)
  389. FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
  390. FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
  391. FN_LOCAL_BOOL(lp_read_only, read_only)
  392. FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
  393. FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
  394. FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
  395. FN_LOCAL_BOOL(lp_write_only, write_only)
  396. /* local prototypes */
  397. static int strwicmp(char *psz1, char *psz2);
  398. static int map_parameter(char *parmname);
  399. static BOOL set_boolean(BOOL *pb, char *parmvalue);
  400. static int getservicebyname(char *name, service *pserviceDest);
  401. static void copy_service(service *pserviceDest, service *pserviceSource);
  402. static BOOL do_parameter(char *parmname, char *parmvalue);
  403. static BOOL do_section(char *sectionname);
  404. /***************************************************************************
  405. * initialise a service to the defaults
  406. ***************************************************************************/
  407. static void init_service(service *pservice)
  408. {
  409. memset((char *)pservice,0,sizeof(service));
  410. copy_service(pservice,&sDefault);
  411. }
  412. /**
  413. * Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
  414. * be initialized when this is called, either to NULL or a malloc'd
  415. * string.
  416. *
  417. * @fixme There is a small leak here in that sometimes the existing
  418. * value will be dynamically allocated, and the old copy is lost.
  419. * However, we can't always deallocate the old value, because in the
  420. * case of sDefault, it points to a static string. It would be nice
  421. * to have either all-strdup'd values, or to never need to free
  422. * memory.
  423. **/
  424. static void string_set(char **s, const char *v)
  425. {
  426. if (!v) {
  427. *s = NULL;
  428. return;
  429. }
  430. *s = strdup(v);
  431. if (!*s)
  432. exit_cleanup(RERR_MALLOC);
  433. }
  434. /***************************************************************************
  435. * add a new service to the services array initialising it with the given
  436. * service
  437. ***************************************************************************/
  438. static int add_a_service(service *pservice, char *name)
  439. {
  440. int i;
  441. service tservice;
  442. int num_to_alloc = iNumServices+1;
  443. tservice = *pservice;
  444. /* it might already exist */
  445. if (name)
  446. {
  447. i = getservicebyname(name,NULL);
  448. if (i >= 0)
  449. return(i);
  450. }
  451. i = iNumServices;
  452. ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
  453. if (ServicePtrs)
  454. pSERVICE(iNumServices) = new(service);
  455. if (!ServicePtrs || !pSERVICE(iNumServices))
  456. return(-1);
  457. iNumServices++;
  458. init_service(pSERVICE(i));
  459. copy_service(pSERVICE(i),&tservice);
  460. if (name)
  461. string_set(&iSERVICE(i).name,name);
  462. return(i);
  463. }
  464. /***************************************************************************
  465. * Do a case-insensitive, whitespace-ignoring string compare.
  466. ***************************************************************************/
  467. static int strwicmp(char *psz1, char *psz2)
  468. {
  469. /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
  470. /* appropriate value. */
  471. if (psz1 == psz2)
  472. return (0);
  473. else
  474. if (psz1 == NULL)
  475. return (-1);
  476. else
  477. if (psz2 == NULL)
  478. return (1);
  479. /* sync the strings on first non-whitespace */
  480. while (1)
  481. {
  482. while (isSpace(psz1))
  483. psz1++;
  484. while (isSpace(psz2))
  485. psz2++;
  486. if (toUpper(psz1) != toUpper(psz2) || *psz1 == '\0' || *psz2 == '\0')
  487. break;
  488. psz1++;
  489. psz2++;
  490. }
  491. return (*psz1 - *psz2);
  492. }
  493. /***************************************************************************
  494. * Map a parameter's string representation to something we can use.
  495. * Returns False if the parameter string is not recognised, else TRUE.
  496. ***************************************************************************/
  497. static int map_parameter(char *parmname)
  498. {
  499. int iIndex;
  500. if (*parmname == '-')
  501. return(-1);
  502. for (iIndex = 0; parm_table[iIndex].label; iIndex++)
  503. if (strwicmp(parm_table[iIndex].label, parmname) == 0)
  504. return(iIndex);
  505. rprintf(FLOG, "Unknown Parameter encountered: \"%s\"\n", parmname);
  506. return(-1);
  507. }
  508. /***************************************************************************
  509. * Set a boolean variable from the text value stored in the passed string.
  510. * Returns True in success, False if the passed string does not correctly
  511. * represent a boolean.
  512. ***************************************************************************/
  513. static BOOL set_boolean(BOOL *pb, char *parmvalue)
  514. {
  515. BOOL bRetval;
  516. bRetval = True;
  517. if (strwicmp(parmvalue, "yes") == 0 ||
  518. strwicmp(parmvalue, "true") == 0 ||
  519. strwicmp(parmvalue, "1") == 0)
  520. *pb = True;
  521. else
  522. if (strwicmp(parmvalue, "no") == 0 ||
  523. strwicmp(parmvalue, "False") == 0 ||
  524. strwicmp(parmvalue, "0") == 0)
  525. *pb = False;
  526. else
  527. {
  528. rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n",
  529. parmvalue);
  530. bRetval = False;
  531. }
  532. return (bRetval);
  533. }
  534. /***************************************************************************
  535. * Find a service by name. Otherwise works like get_service.
  536. ***************************************************************************/
  537. static int getservicebyname(char *name, service *pserviceDest)
  538. {
  539. int iService;
  540. for (iService = iNumServices - 1; iService >= 0; iService--)
  541. if (strwicmp(iSERVICE(iService).name, name) == 0)
  542. {
  543. if (pserviceDest != NULL)
  544. copy_service(pserviceDest, pSERVICE(iService));
  545. break;
  546. }
  547. return (iService);
  548. }
  549. /***************************************************************************
  550. * Copy a service structure to another
  551. ***************************************************************************/
  552. static void copy_service(service *pserviceDest,
  553. service *pserviceSource)
  554. {
  555. int i;
  556. for (i=0;parm_table[i].label;i++)
  557. if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
  558. void *def_ptr = parm_table[i].ptr;
  559. void *src_ptr =
  560. ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
  561. void *dest_ptr =
  562. ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
  563. switch (parm_table[i].type)
  564. {
  565. case P_BOOL:
  566. case P_BOOLREV:
  567. *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
  568. break;
  569. case P_INTEGER:
  570. case P_ENUM:
  571. case P_OCTAL:
  572. *(int *)dest_ptr = *(int *)src_ptr;
  573. break;
  574. case P_CHAR:
  575. *(char *)dest_ptr = *(char *)src_ptr;
  576. break;
  577. case P_PATH:
  578. case P_STRING:
  579. string_set(dest_ptr,*(char **)src_ptr);
  580. break;
  581. default:
  582. break;
  583. }
  584. }
  585. }
  586. /***************************************************************************
  587. * Process a parameter for a particular service number. If snum < 0
  588. * then assume we are in the globals
  589. ***************************************************************************/
  590. static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
  591. {
  592. int parmnum, i;
  593. void *parm_ptr=NULL; /* where we are going to store the result */
  594. void *def_ptr=NULL;
  595. char *cp;
  596. parmnum = map_parameter(parmname);
  597. if (parmnum < 0)
  598. {
  599. rprintf(FLOG, "IGNORING unknown parameter \"%s\"\n", parmname);
  600. return(True);
  601. }
  602. def_ptr = parm_table[parmnum].ptr;
  603. /* we might point at a service, the default service or a global */
  604. if (snum < 0) {
  605. parm_ptr = def_ptr;
  606. } else {
  607. if (parm_table[parmnum].class == P_GLOBAL) {
  608. rprintf(FLOG, "Global parameter %s found in service section!\n",parmname);
  609. return(True);
  610. }
  611. parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
  612. }
  613. /* now switch on the type of variable it is */
  614. switch (parm_table[parmnum].type)
  615. {
  616. case P_BOOL:
  617. set_boolean(parm_ptr,parmvalue);
  618. break;
  619. case P_BOOLREV:
  620. set_boolean(parm_ptr,parmvalue);
  621. *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
  622. break;
  623. case P_INTEGER:
  624. *(int *)parm_ptr = atoi(parmvalue);
  625. break;
  626. case P_CHAR:
  627. *(char *)parm_ptr = *parmvalue;
  628. break;
  629. case P_OCTAL:
  630. sscanf(parmvalue,"%o",(int *)parm_ptr);
  631. break;
  632. case P_PATH:
  633. string_set(parm_ptr,parmvalue);
  634. if ((cp = *(char**)parm_ptr) != NULL) {
  635. int len = strlen(cp);
  636. while (len > 1 && cp[len-1] == '/') len--;
  637. cp[len] = '\0';
  638. }
  639. break;
  640. case P_STRING:
  641. string_set(parm_ptr,parmvalue);
  642. break;
  643. case P_GSTRING:
  644. strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring));
  645. break;
  646. case P_ENUM:
  647. for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
  648. if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
  649. *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
  650. break;
  651. }
  652. }
  653. if (!parm_table[parmnum].enum_list[i].name) {
  654. if (atoi(parmvalue) > 0)
  655. *(int *)parm_ptr = atoi(parmvalue);
  656. }
  657. break;
  658. case P_SEP:
  659. break;
  660. }
  661. return(True);
  662. }
  663. /***************************************************************************
  664. * Process a parameter.
  665. ***************************************************************************/
  666. static BOOL do_parameter(char *parmname, char *parmvalue)
  667. {
  668. return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
  669. }
  670. /***************************************************************************
  671. * Process a new section (service). At this stage all sections are services.
  672. * Later we'll have special sections that permit server parameters to be set.
  673. * Returns True on success, False on failure.
  674. ***************************************************************************/
  675. static BOOL do_section(char *sectionname)
  676. {
  677. BOOL bRetval;
  678. BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
  679. bRetval = False;
  680. /* if we were in a global section then do the local inits */
  681. if (bInGlobalSection && !isglobal)
  682. init_locals();
  683. /* if we've just struck a global section, note the fact. */
  684. bInGlobalSection = isglobal;
  685. /* check for multiple global sections */
  686. if (bInGlobalSection)
  687. {
  688. return(True);
  689. }
  690. if (strchr(sectionname, '/') != NULL) {
  691. rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
  692. return False;
  693. }
  694. /* if we have a current service, tidy it up before moving on */
  695. bRetval = True;
  696. if (iServiceIndex >= 0)
  697. bRetval = True;
  698. /* if all is still well, move to the next record in the services array */
  699. if (bRetval)
  700. {
  701. /* We put this here to avoid an odd message order if messages are */
  702. /* issued by the post-processing of a previous section. */
  703. if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
  704. {
  705. rprintf(FLOG, "Failed to add a new service\n");
  706. return(False);
  707. }
  708. }
  709. return (bRetval);
  710. }
  711. /***************************************************************************
  712. * Load the services array from the services file. Return True on success,
  713. * False on failure.
  714. ***************************************************************************/
  715. BOOL lp_load(char *pszFname, int globals_only)
  716. {
  717. pstring n2;
  718. BOOL bRetval;
  719. bRetval = False;
  720. bInGlobalSection = True;
  721. init_globals();
  722. pstrcpy(n2, pszFname);
  723. /* We get sections first, so have to start 'behind' to make up */
  724. iServiceIndex = -1;
  725. bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
  726. return (bRetval);
  727. }
  728. /***************************************************************************
  729. * return the max number of services
  730. ***************************************************************************/
  731. int lp_numservices(void)
  732. {
  733. return(iNumServices);
  734. }
  735. /***************************************************************************
  736. * Return the number of the service with the given name, or -1 if it doesn't
  737. * exist. Note that this is a DIFFERENT ANIMAL from the internal function
  738. * getservicebyname()! This works ONLY if all services have been loaded, and
  739. * does not copy the found service.
  740. ***************************************************************************/
  741. int lp_number(char *name)
  742. {
  743. int iService;
  744. for (iService = iNumServices - 1; iService >= 0; iService--)
  745. if (strcmp(lp_name(iService), name) == 0)
  746. break;
  747. return (iService);
  748. }