1 | #!/usr/bin/env python
|
---|
2 |
|
---|
3 | import string, Logs, Utils, Options, Build, os, optparse, textwrap
|
---|
4 | from samba_utils import EXPAND_VARIABLES, os_path_relpath
|
---|
5 |
|
---|
6 | class SambaIndentedHelpFormatter (optparse.IndentedHelpFormatter):
|
---|
7 | """Format help with indented section bodies.
|
---|
8 | """
|
---|
9 |
|
---|
10 | def __init__(self,
|
---|
11 | indent_increment=2,
|
---|
12 | max_help_position=12,
|
---|
13 | width=None,
|
---|
14 | short_first=1):
|
---|
15 | optparse.IndentedHelpFormatter.__init__(
|
---|
16 | self, indent_increment, max_help_position, width, short_first)
|
---|
17 |
|
---|
18 | def format_option(self, option):
|
---|
19 | # The help for each option consists of two parts:
|
---|
20 | # * the opt strings and metavars
|
---|
21 | # eg. ("-x", or "-fFILENAME, --file=FILENAME")
|
---|
22 | # * the user-supplied help string
|
---|
23 | # eg. ("turn on expert mode", "read data from FILENAME")
|
---|
24 | #
|
---|
25 | # If possible, we write both of these on the same line:
|
---|
26 | # -x turn on expert mode
|
---|
27 | #
|
---|
28 | # But if the opt string list is too long, we put the help
|
---|
29 | # string on a second line, indented to the same column it would
|
---|
30 | # start in if it fit on the first line.
|
---|
31 | # -fFILENAME, --file=FILENAME
|
---|
32 | # read data from FILENAME
|
---|
33 | result = []
|
---|
34 | opts = self.option_strings[option]
|
---|
35 | opt_width = self.help_position - self.current_indent - 2
|
---|
36 | if len(opts) > opt_width:
|
---|
37 | opts = "%*s%s\n" % (self.current_indent, "", opts)
|
---|
38 | indent_first = self.help_position
|
---|
39 | else: # start help on same line as opts
|
---|
40 | opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)
|
---|
41 | indent_first = 0
|
---|
42 | result.append(opts)
|
---|
43 | if option.help:
|
---|
44 | help_text = self.expand_default(option)
|
---|
45 | if string.find(help_text, '\n') == -1:
|
---|
46 | help_lines = textwrap.wrap(help_text, self.help_width)
|
---|
47 | else:
|
---|
48 | help_lines = help_text.splitlines()
|
---|
49 | result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
|
---|
50 | result.extend(["%*s%s\n" % (self.help_position, "", line)
|
---|
51 | for line in help_lines[1:]])
|
---|
52 | elif opts[-1] != "\n":
|
---|
53 | result.append("\n")
|
---|
54 | return "".join(result)
|
---|
55 |
|
---|
56 |
|
---|
57 | # list of directory options to offer in configure
|
---|
58 | #
|
---|
59 | # 'STD-PATH' - the default path without --enable-fhs
|
---|
60 | # 'FHS-PATH' - the default path with --enable-fhs
|
---|
61 | #
|
---|
62 | # 'OPTION' - the configure option to overwrite the default (optional)
|
---|
63 | # 'HELPTEXT' - the help text of the configure option (optional)
|
---|
64 | #
|
---|
65 | # 'OVERWRITE' - The option referrs to itself and was already from
|
---|
66 | # the basic GNU options from the gnu_dirs tool.
|
---|
67 | # We may overwrite the related path. (Default: False)
|
---|
68 | #
|
---|
69 | # 'DELAY' - The option referrs to other options in the dynconfig list.
|
---|
70 | # We delay the intialization into a later stage. This
|
---|
71 | # makes sure the recursion works. (Default: False)
|
---|
72 | #
|
---|
73 | dynconfig = {
|
---|
74 | 'BINDIR' : {
|
---|
75 | 'STD-PATH': '${BINDIR}',
|
---|
76 | 'FHS-PATH': '${BINDIR}',
|
---|
77 | 'OVERWRITE': True,
|
---|
78 | },
|
---|
79 | 'SBINDIR' : {
|
---|
80 | 'STD-PATH': '${SBINDIR}',
|
---|
81 | 'FHS-PATH': '${SBINDIR}',
|
---|
82 | 'OVERWRITE': True,
|
---|
83 | },
|
---|
84 | 'LIBDIR' : {
|
---|
85 | 'STD-PATH': '${LIBDIR}',
|
---|
86 | 'FHS-PATH': '${LIBDIR}',
|
---|
87 | 'OVERWRITE': True,
|
---|
88 | },
|
---|
89 | 'LIBEXECDIR' : {
|
---|
90 | 'STD-PATH': '${LIBEXECDIR}',
|
---|
91 | 'FHS-PATH': '${LIBEXECDIR}',
|
---|
92 | 'OVERWRITE': True,
|
---|
93 | },
|
---|
94 | 'DATADIR' : {
|
---|
95 | 'STD-PATH': '${DATADIR}',
|
---|
96 | 'FHS-PATH': '${DATADIR}',
|
---|
97 | 'OVERWRITE': True,
|
---|
98 | },
|
---|
99 | 'LOCALEDIR' : {
|
---|
100 | 'STD-PATH': '${LOCALEDIR}',
|
---|
101 | 'FHS-PATH': '${LOCALEDIR}',
|
---|
102 | 'OVERWRITE': True,
|
---|
103 | },
|
---|
104 | 'PYTHONDIR' : {
|
---|
105 | 'STD-PATH': '${PYTHONDIR}',
|
---|
106 | 'FHS-PATH': '${PYTHONDIR}',
|
---|
107 | 'OVERWRITE': True,
|
---|
108 | },
|
---|
109 | 'PYTHONARCHDIR' : {
|
---|
110 | 'STD-PATH': '${PYTHONARCHDIR}',
|
---|
111 | 'FHS-PATH': '${PYTHONARCHDIR}',
|
---|
112 | 'OVERWRITE': True,
|
---|
113 | },
|
---|
114 | 'PERL_LIB_INSTALL_DIR' : {
|
---|
115 | 'STD-PATH': '${PERL_LIB_INSTALL_DIR}',
|
---|
116 | 'FHS-PATH': '${PERL_LIB_INSTALL_DIR}',
|
---|
117 | 'OVERWRITE': True,
|
---|
118 | },
|
---|
119 | 'PERL_ARCH_INSTALL_DIR' : {
|
---|
120 | 'STD-PATH': '${PERL_ARCH_INSTALL_DIR}',
|
---|
121 | 'FHS-PATH': '${PERL_ARCH_INSTALL_DIR}',
|
---|
122 | 'OVERWRITE': True,
|
---|
123 | },
|
---|
124 | 'INCLUDEDIR' : {
|
---|
125 | 'STD-PATH': '${INCLUDEDIR}',
|
---|
126 | 'FHS-PATH': '${INCLUDEDIR}/samba-4.0',
|
---|
127 | 'OVERWRITE': True,
|
---|
128 | },
|
---|
129 | 'SCRIPTSBINDIR' : {
|
---|
130 | 'STD-PATH': '${SBINDIR}',
|
---|
131 | 'FHS-PATH': '${SBINDIR}',
|
---|
132 | },
|
---|
133 | 'SETUPDIR' : {
|
---|
134 | 'STD-PATH': '${DATADIR}/setup',
|
---|
135 | 'FHS-PATH': '${DATADIR}/samba/setup',
|
---|
136 | },
|
---|
137 | 'PKGCONFIGDIR' : {
|
---|
138 | 'STD-PATH': '${LIBDIR}/pkgconfig',
|
---|
139 | 'FHS-PATH': '${LIBDIR}/pkgconfig',
|
---|
140 | },
|
---|
141 | 'CODEPAGEDIR' : {
|
---|
142 | 'STD-PATH': '${DATADIR}/codepages',
|
---|
143 | 'FHS-PATH': '${DATADIR}/samba/codepages',
|
---|
144 | },
|
---|
145 | 'PRIVATELIBDIR' : {
|
---|
146 | 'STD-PATH': '${LIBDIR}/private',
|
---|
147 | 'FHS-PATH': '${LIBDIR}/samba',
|
---|
148 | 'OPTION': '--with-privatelibdir',
|
---|
149 | 'HELPTEXT': 'Which directory to use for private Samba libraries',
|
---|
150 | 'OVERWRITE': True,
|
---|
151 | },
|
---|
152 | 'MODULESDIR' : {
|
---|
153 | 'STD-PATH': '${LIBDIR}',
|
---|
154 | 'FHS-PATH': '${LIBDIR}/samba',
|
---|
155 | 'OPTION': '--with-modulesdir',
|
---|
156 | 'HELPTEXT': 'Which directory to use for Samba modules',
|
---|
157 | 'OVERWRITE': True,
|
---|
158 | },
|
---|
159 | 'PAMMODULESDIR' : {
|
---|
160 | 'STD-PATH': '${LIBDIR}/security',
|
---|
161 | 'FHS-PATH': '${LIBDIR}/security',
|
---|
162 | 'OPTION': '--with-pammodulesdir',
|
---|
163 | 'HELPTEXT': 'Which directory to use for PAM modules',
|
---|
164 | },
|
---|
165 | 'CONFIGDIR' : {
|
---|
166 | 'STD-PATH': '${SYSCONFDIR}',
|
---|
167 | 'FHS-PATH': '${SYSCONFDIR}/samba',
|
---|
168 | 'OPTION': '--with-configdir',
|
---|
169 | 'HELPTEXT': 'Where to put configuration files',
|
---|
170 | },
|
---|
171 | 'PRIVATE_DIR' : {
|
---|
172 | 'STD-PATH': '${PREFIX}/private',
|
---|
173 | 'FHS-PATH': '${LOCALSTATEDIR}/lib/samba/private',
|
---|
174 | 'OPTION': '--with-privatedir',
|
---|
175 | 'HELPTEXT': 'Where to put sam.ldb and other private files',
|
---|
176 | },
|
---|
177 | 'LOCKDIR' : {
|
---|
178 | 'STD-PATH': '${LOCALSTATEDIR}/lock',
|
---|
179 | 'FHS-PATH': '${LOCALSTATEDIR}/lock/samba',
|
---|
180 | 'OPTION': '--with-lockdir',
|
---|
181 | 'HELPTEXT': 'Where to put short term disposable state files',
|
---|
182 | },
|
---|
183 | 'PIDDIR' : {
|
---|
184 | 'STD-PATH': '${LOCALSTATEDIR}/run',
|
---|
185 | 'FHS-PATH': '${LOCALSTATEDIR}/run/samba',
|
---|
186 | 'OPTION': '--with-piddir',
|
---|
187 | 'HELPTEXT': 'Where to put pid files',
|
---|
188 | },
|
---|
189 | 'STATEDIR' : {
|
---|
190 | 'STD-PATH': '${LOCALSTATEDIR}/locks',
|
---|
191 | 'FHS-PATH': '${LOCALSTATEDIR}/lib/samba',
|
---|
192 | 'OPTION': '--with-statedir',
|
---|
193 | 'HELPTEXT': 'Where to put persistent state files',
|
---|
194 | },
|
---|
195 | 'CACHEDIR' : {
|
---|
196 | 'STD-PATH': '${LOCALSTATEDIR}/cache',
|
---|
197 | 'FHS-PATH': '${LOCALSTATEDIR}/cache/samba',
|
---|
198 | 'OPTION': '--with-cachedir',
|
---|
199 | 'HELPTEXT': 'Where to put temporary cache files',
|
---|
200 | },
|
---|
201 | 'LOGFILEBASE' : {
|
---|
202 | 'STD-PATH': '${LOCALSTATEDIR}',
|
---|
203 | 'FHS-PATH': '${LOCALSTATEDIR}/log/samba',
|
---|
204 | 'OPTION': '--with-logfilebase',
|
---|
205 | 'HELPTEXT': 'Where to put log files',
|
---|
206 | },
|
---|
207 | 'SOCKET_DIR' : {
|
---|
208 | 'STD-PATH': '${LOCALSTATEDIR}/run',
|
---|
209 | 'FHS-PATH': '${LOCALSTATEDIR}/run/samba',
|
---|
210 | 'OPTION': '--with-sockets-dir',
|
---|
211 | 'HELPTEXT': 'socket directory',
|
---|
212 | },
|
---|
213 | 'PRIVILEGED_SOCKET_DIR' : {
|
---|
214 | 'STD-PATH': '${LOCALSTATEDIR}/lib',
|
---|
215 | 'FHS-PATH': '${LOCALSTATEDIR}/lib/samba',
|
---|
216 | 'OPTION': '--with-privileged-socket-dir',
|
---|
217 | 'HELPTEXT': 'privileged socket directory',
|
---|
218 | },
|
---|
219 | 'WINBINDD_SOCKET_DIR' : {
|
---|
220 | 'STD-PATH': '${SOCKET_DIR}/winbindd',
|
---|
221 | 'FHS-PATH': '${SOCKET_DIR}/winbindd',
|
---|
222 | 'DELAY': True,
|
---|
223 | },
|
---|
224 | 'WINBINDD_PRIVILEGED_SOCKET_DIR' : {
|
---|
225 | 'STD-PATH': '${PRIVILEGED_SOCKET_DIR}/winbindd_privileged',
|
---|
226 | 'FHS-PATH': '${PRIVILEGED_SOCKET_DIR}/winbindd_privileged',
|
---|
227 | 'DELAY': True,
|
---|
228 | },
|
---|
229 | 'NMBDSOCKETDIR' : {
|
---|
230 | 'STD-PATH': '${SOCKET_DIR}/nmbd',
|
---|
231 | 'FHS-PATH': '${SOCKET_DIR}/nmbd',
|
---|
232 | 'DELAY': True,
|
---|
233 | },
|
---|
234 | 'NTP_SIGND_SOCKET_DIR' : {
|
---|
235 | 'STD-PATH': '${PRIVILEGED_SOCKET_DIR}/ntp_signd',
|
---|
236 | 'FHS-PATH': '${PRIVILEGED_SOCKET_DIR}/ntp_signd',
|
---|
237 | 'DELAY': True,
|
---|
238 | },
|
---|
239 | 'NCALRPCDIR' : {
|
---|
240 | 'STD-PATH': '${SOCKET_DIR}/ncalrpc',
|
---|
241 | 'FHS-PATH': '${SOCKET_DIR}/ncalrpc',
|
---|
242 | 'DELAY': True,
|
---|
243 | },
|
---|
244 | 'CONFIGFILE' : {
|
---|
245 | 'STD-PATH': '${CONFIGDIR}/smb.conf',
|
---|
246 | 'FHS-PATH': '${CONFIGDIR}/smb.conf',
|
---|
247 | 'DELAY': True,
|
---|
248 | },
|
---|
249 | 'LMHOSTSFILE' : {
|
---|
250 | 'STD-PATH': '${CONFIGDIR}/lmhosts',
|
---|
251 | 'FHS-PATH': '${CONFIGDIR}/lmhosts',
|
---|
252 | 'DELAY': True,
|
---|
253 | },
|
---|
254 | 'SMB_PASSWD_FILE' : {
|
---|
255 | 'STD-PATH': '${PRIVATE_DIR}/smbpasswd',
|
---|
256 | 'FHS-PATH': '${PRIVATE_DIR}/smbpasswd',
|
---|
257 | 'DELAY': True,
|
---|
258 | },
|
---|
259 | }
|
---|
260 |
|
---|
261 | def set_options(opt):
|
---|
262 | opt.parser.formatter = SambaIndentedHelpFormatter()
|
---|
263 | opt.parser.formatter.width=Utils.get_term_cols()
|
---|
264 |
|
---|
265 | for k in ('--with-privatelibdir', '--with-modulesdir'):
|
---|
266 | option = opt.parser.get_option(k)
|
---|
267 | if option:
|
---|
268 | opt.parser.remove_option(k)
|
---|
269 | del opt.parser.defaults['PRIVATELIBDIR']
|
---|
270 | del opt.parser.defaults['MODULESDIR']
|
---|
271 |
|
---|
272 | # get all the basic GNU options from the gnu_dirs tool
|
---|
273 |
|
---|
274 | opt_group=opt.add_option_group('Samba-specific directory layout','')
|
---|
275 |
|
---|
276 | fhs_help = "Use FHS-compliant paths (default no)\n"
|
---|
277 | fhs_help += "You should consider using this together with:\n"
|
---|
278 | fhs_help += "--prefix=/usr --sysconfdir=/etc --localstatedir=/var"
|
---|
279 | opt_group.add_option('--enable-fhs', help=fhs_help,
|
---|
280 | action="store_true", dest='ENABLE_FHS', default=False)
|
---|
281 |
|
---|
282 | for varname in dynconfig.keys():
|
---|
283 | if 'OPTION' not in dynconfig[varname]:
|
---|
284 | continue
|
---|
285 | opt = dynconfig[varname]['OPTION']
|
---|
286 | if 'HELPTEXT' in dynconfig[varname]:
|
---|
287 | txt = dynconfig[varname]['HELPTEXT']
|
---|
288 | else:
|
---|
289 | txt = "dynconfig path %s" % (varname)
|
---|
290 | def_std = dynconfig[varname]['STD-PATH']
|
---|
291 | def_fhs = dynconfig[varname]['FHS-PATH']
|
---|
292 |
|
---|
293 | help = "%s\n[STD-Default: %s]\n[FHS-Default: %s]" % (txt, def_std, def_fhs)
|
---|
294 | opt_group.add_option(opt, help=help, dest=varname, action="store")
|
---|
295 |
|
---|
296 | def configure(conf):
|
---|
297 | # get all the basic GNU options from the gnu_dirs tool
|
---|
298 |
|
---|
299 | if Options.options.ENABLE_FHS:
|
---|
300 | flavor = 'FHS-PATH'
|
---|
301 | else:
|
---|
302 | flavor = 'STD-PATH'
|
---|
303 | if conf.env.PREFIX == '/usr' or conf.env.PREFIX == '/usr/local':
|
---|
304 | Logs.error("Don't install directly under /usr or /usr/local without using the FHS option (--enable-fhs)")
|
---|
305 | raise Utils.WafError("ERROR: invalid --prefix=%s value" % (conf.env.PREFIX))
|
---|
306 |
|
---|
307 | explicit_set ={}
|
---|
308 |
|
---|
309 | dyn_vars = {}
|
---|
310 | for varname in dynconfig.keys():
|
---|
311 | dyn_vars[varname] = dynconfig[varname][flavor]
|
---|
312 | if 'OVERWRITE' in dynconfig[varname] and dynconfig[varname]['OVERWRITE']:
|
---|
313 | # we may overwrite this option
|
---|
314 | continue
|
---|
315 | conf.ASSERT(varname not in conf.env, "Variable %s already defined" % varname)
|
---|
316 |
|
---|
317 | # the explicit block
|
---|
318 | for varname in dynconfig.keys():
|
---|
319 | if 'OPTION' not in dynconfig[varname]:
|
---|
320 | continue
|
---|
321 | value = getattr(Options.options, varname, None)
|
---|
322 | if value is None:
|
---|
323 | continue
|
---|
324 | conf.ASSERT(value != '', "Empty dynconfig value for %s" % varname)
|
---|
325 | conf.env[varname] = value
|
---|
326 | # mark it as explicit from the command line
|
---|
327 | explicit_set[varname] = value
|
---|
328 |
|
---|
329 | # defaults stage 1 after the explicit block
|
---|
330 | for varname in dynconfig.keys():
|
---|
331 | if 'DELAY' in dynconfig[varname] and dynconfig[varname]['DELAY']:
|
---|
332 | # this option referrs to other options,
|
---|
333 | # so it needs to wait for stage 2.
|
---|
334 | continue
|
---|
335 | value = EXPAND_VARIABLES(conf, dyn_vars[varname])
|
---|
336 | conf.ASSERT(value != '', "Empty dynconfig value for %s" % varname)
|
---|
337 | if varname not in explicit_set:
|
---|
338 | # only overwrite if not specified explicitly on the command line
|
---|
339 | conf.env[varname] = value
|
---|
340 |
|
---|
341 | # defaults stage 2 after the explicit block
|
---|
342 | for varname in dynconfig.keys():
|
---|
343 | if 'DELAY' not in dynconfig[varname] or not dynconfig[varname]['DELAY']:
|
---|
344 | # this option was already handled in stage 1.
|
---|
345 | continue
|
---|
346 | value = EXPAND_VARIABLES(conf, dyn_vars[varname])
|
---|
347 | conf.ASSERT(value != '', "Empty dynconfig value for %s" % varname)
|
---|
348 | if varname not in explicit_set:
|
---|
349 | # only overwrite if not specified explicitly on the command line
|
---|
350 | conf.env[varname] = value
|
---|
351 |
|
---|
352 | # display the expanded pathes for the user
|
---|
353 | for varname in dynconfig.keys():
|
---|
354 | value = conf.env[varname]
|
---|
355 | conf.start_msg("Dynconfig[%s]: " % (varname))
|
---|
356 | conf.end_msg("'%s'" % (value), 'GREEN')
|
---|
357 |
|
---|
358 | def get_override(bld):
|
---|
359 | override = { 'MODULESDIR' : 'bin/modules',
|
---|
360 | 'PYTHONDIR' : 'bin/python',
|
---|
361 | 'PYTHONARCHDIR' : 'bin/python',
|
---|
362 | 'BINDIR' : 'bin',
|
---|
363 | 'SBINDIR' : 'bin',
|
---|
364 | 'CODEPAGEDIR' : 'codepages',
|
---|
365 | 'SCRIPTSBINDIR' : 'source4/scripting/bin',
|
---|
366 | 'SETUPDIR' : 'source4/setup'
|
---|
367 | }
|
---|
368 | return override
|
---|
369 |
|
---|
370 | def dynconfig_cflags(bld, list=None):
|
---|
371 | '''work out the extra CFLAGS for dynconfig.c'''
|
---|
372 | cflags = []
|
---|
373 | for varname in dynconfig.keys():
|
---|
374 | if list and not varname in list:
|
---|
375 | continue
|
---|
376 | value = bld.env[varname]
|
---|
377 | if not bld.is_install:
|
---|
378 | override = get_override(bld)
|
---|
379 | if varname in override:
|
---|
380 | value = os.path.join(bld.env.srcdir, override[varname])
|
---|
381 | cflags.append('-D%s="%s"' % (varname, value))
|
---|
382 | return cflags
|
---|
383 | Build.BuildContext.dynconfig_cflags = dynconfig_cflags
|
---|
384 |
|
---|
385 | def dynconfig_varnames(bld, list=None):
|
---|
386 | '''work out the dynconfig variables'''
|
---|
387 | varnames = []
|
---|
388 | for varname in dynconfig.keys():
|
---|
389 | if list and not varname in list:
|
---|
390 | continue
|
---|
391 | varnames.append(varname)
|
---|
392 | return varnames
|
---|
393 | Build.BuildContext.dynconfig_varnames = dynconfig_varnames
|
---|
394 |
|
---|
395 | def pathconfig_entities(bld, list=None):
|
---|
396 | '''work out the extra entities for the docs'''
|
---|
397 | entities = []
|
---|
398 | for varname in dynconfig.keys():
|
---|
399 | if list and not varname in list:
|
---|
400 | continue
|
---|
401 | value = bld.env[varname]
|
---|
402 | if not bld.is_install:
|
---|
403 | override = get_override(bld)
|
---|
404 | if varname in override:
|
---|
405 | value = os.path.join(bld.env.srcdir, override[varname])
|
---|
406 | entities.append("<!ENTITY pathconfig.%s '%s'>" % (varname, value))
|
---|
407 | return entities
|
---|
408 | Build.BuildContext.pathconfig_entities = pathconfig_entities
|
---|
409 |
|
---|
410 | def build(bld):
|
---|
411 | cflags = bld.dynconfig_cflags()
|
---|
412 | version_header = 'version.h'
|
---|
413 | bld.SAMBA_SUBSYSTEM('DYNCONFIG',
|
---|
414 | 'dynconfig.c',
|
---|
415 | deps='replace',
|
---|
416 | public_headers=os_path_relpath(os.path.join(Options.launch_dir, version_header), bld.curdir),
|
---|
417 | header_path='samba',
|
---|
418 | cflags=cflags)
|
---|
419 |
|
---|
420 | # install some extra empty directories
|
---|
421 | bld.INSTALL_DIRS("", "${CONFIGDIR} ${PRIVATE_DIR} ${LOGFILEBASE}");
|
---|
422 | bld.INSTALL_DIRS("", "${PRIVATE_DIR} ${PRIVILEGED_SOCKET_DIR}")
|
---|
423 | bld.INSTALL_DIRS("", "${STATEDIR} ${CACHEDIR}");
|
---|
424 |
|
---|
425 | # these might be on non persistent storage
|
---|
426 | bld.INSTALL_DIRS("", "${LOCKDIR} ${PIDDIR} ${SOCKET_DIR}")
|
---|