summaryrefslogtreecommitdiffstats
path: root/doc/format-specifiers.txt
blob: 86548de4db66cc0671072c9d71edd7d70ef3d565 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
== Function Specifiers ==

Both the NIS Server and Schema Compatibility plugins use format
specifiers given in their respective configurations to control how they
massage the contents of entries which are already in the directory
server into entries in either NIS maps or the compatibility area of the
directory.

=== Basics ===

Format specifiers can reference values of attributes in the entry which
is currently being examined like so:
  %{attribute}

The values of multiple attributes can be mixed together like so:
  %{one_attribute}:%{another_attribute}

Like shell variables, a reference to an attribute can specify a default
value to be used in cases where the entry has no value for the specified
attribute:
  %{gecos:-%{cn:-}}

Again, like shell variables, a reference can also specify an alternate
value to be provided when the entry has a value (though this is not
expected to be used as frequently) which should be overridden:
  %{cn:+%{cn},,,}%{cn:-%{gecos}}

Or to use a more concrete (but still simplified) example:
  %{uid}:*:%{uidNumber}:%{gidNumber}:%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-/bin/sh}

Additional operators include "#", "##", "%", "%%", "/", "//", which
operate in ways similar to their shell counterparts (with one notable
exception: patterns for the "/" operator can not currently be anchored
to the beginning or end of the string).

Strictly speaking, references to attributes return ''lists'' of values,
or produce an evaluation error if no values are found.  This helps
prevent invalid entries from showing up in NIS maps and in the
directory.

=== Functions ===

Additionally, several built-in "function"s are available.  These can be
used to modify data that's been read from the current entry before it's
incorporated into the result, or for importing values from other entries
and combining them with data from the current entry.  Generally,
function invocations look like this:

  %function(ARG[,...])

A function invocation uses a comma-separated list of double-quoted
arguments.  Any arguments which themselves contain a double-quote need
to escape the double-quote using a '\' character.  Naturally, the '\'
character itself also needs to be escaped whenever it appears.  Some
functions can take expressions as arguments, allowing functions to
operate on data after it has been acted on by other functions.

== Implemented Functions ==

=== first ===

  first(''EXPRESSION''[,''DEFAULT''])

Evaluates ''EXPRESSION'', and if one or more values is produced,
provides only the first value.  (Here, ''first'' refers to the first
value in the list of values after they've been sorted.)  If no values
result, then ''DEFAULT'' is evaluated as an expression and its result is
provided.  Nothing is done to ensure that ''DEFAULT'' provides only one
value, however.

=== match ===

  match(''EXPRESSION'',''PATTERN''[,''DEFAULT''])

Selects the single value of ''EXPRESSION'' which matches the globbing
pattern ''PATTERN''.  If no value matches, and a ''DEFAULT'' was
specified, then ''DEFAULT'' is evaluated as an expression and its value
is provided.

Here's an example entry:

  dn: cn=group
  member: bob
  member: dave

And here's how it evaluates out:

  %match("%{member}","b*")        -> bob
  %match("%{member}","d*")        -> dave
  %match("%{member}","e*")        no value
  %match("%{member}","*e*")       -> dave
  %match("%{member}","e*","jim")  -> jim
  %match("%{member}","*","%{cn}") -> group

=== regmatch ===

  regmatch(''EXPRESSION'',''PATTERN''[,''DEFAULT''])

Selects the value of ''EXPRESSION'' which matches the extended regular
expression ''PATTERN''.  If no values match, and a ''DEFAULT'' was
specified, then ''DEFAULT'' is evaluated as an expression and its value
is produced.

Here's an example entry:

  dn: cn=group
  member: bob
  member: dave

And here's how it evaluates out:

  %regmatch("%{member}","^b.*")       -> bob
  %regmatch("%{member}","^d.*")       -> dave
  %regmatch("%{member}","e")          -> dave
  %regmatch("%{member}","^e")         no value
  %regmatch("%{member}","^e.*","jim") -> jim
  %regmatch("%{member}",".*","%{cn}") -> group

=== regsub ===

  regsub(''EXPRESSION'',''PATTERN'',''TEMPLATE''[,''DEFAULT''])

Selects the value of ''EXPRESSION'' which matches the extended regular
expression ''PATTERN'' and uses ''TEMPLATE'' to build the result.  If no
values match, and a ''DEFAULT'' was specified, then ''DEFAULT'' is
evaluated as an expression and its value is produced, otherwise an error
occurs.

The template is treated as a literal value, but is allowed to
incorporate the n'th substring (one of the first nine) from the matched
value by including the sequence "%n" in the template.

Here's an example entry:

  dn: cn=group
  member: bob
  member: dave

And here's how it evaluates out:

  %regsub("%{member}","o","%0")          -> bob
  %regsub("%{member}","o","%1")          -> 
  %regsub("%{member}","^o","%0")         no value
  %regsub("%{member}","^d(.).*","%1")    -> a
  %regsub("%{member}","^(.*)e","t%1y")   -> tdavy
  %regsub("%{member}","^o","%0","jim")   -> jim
  %regsub("%{member}","^o","%0","%{cn}") -> group

=== deref ===

  deref(''THISATTRIBUTE'',''THATATTRIBUTE'')

Returns a list of the values of ''THATATTRIBUTE'' for directory entries
named by this entry's ''THISATTRIBUTE''.  Its function is similar in
principle to the indirect CoS functionality provided by the directory
server.

Here are some example entries:

  dn: cn=group
  member: uid=bob
  member: uid=pete

  dn: uid=bob
  uid: bob

  dn: uid=pete
  uid: pete

And here's how various expressions evaluate for ''cn=group'':

  %deref("member","foo") -> no values
  %deref("member","uid") -> (bob,pete)

Because the plugin attempts to track updates, the ''THISATTRIBUTE''
attribute should be indexed.

=== deref_r ===

  deref_r(''ATTRIBUTE''[,''OTHERATTRIBUTE''[...]],''VALUEATTRIBUTE'')

Looks for entries named by this entry's ''ATTRIBUTE'', and then by those
entries' ''ATTRIBUTE'', repeating the search until there are no more
entries to find named by ''ATTRIBUTE'' in the set of entries seen.

Taking that set as a new starting point, searches for entries named by
that set's ''OTHERATTRIBUTE'' values, similarly repeating until a new
complete set of entries is determined.  The process continues to be
repeated for each listed attribute except the last.

When the final set of entries is determined, their ''VALUEATTRIBUTE''
values will be used to construct the result list.

Here are some example entries:

  dn: cn=group
  member: cn=othergroup
  member: uid=bob
  includedgroup: clan=macleod

  dn: cn=othergroup
  member: uid=pete
  uid: bogus

  dn: uid=bob
  uid: bob

  dn: uid=pete
  uid: pete

  dn: clan=macleod
  includedgroup: cn=foundlings

  dn: cn=foundlings
  member: uid=cmacleod
  member: uid=dmacleod

  dn: uid=cmacleod
  uid: cmacleod

  dn: uid=dmacleod
  uid: dmacleod

And here's how various expressions evaluate for ''cn=group'':

  %deref_r("member","foo") -> no values
  %deref_r("member","uid") -> (bogus,bob,pete)

When evaluating the first attribute, the ''member'' attribute of
''cn=group'' produces this set of entries:

    * cn=group (the original entry)
    * cn=othergroup (added because it was named by ''cn=group'')
    * uid=bob (added because it was named by ''cn=group'')
    * uid=pete (added because it was named by ''cn=othergroup'')

The result list is pulled from this set of entries.

Here's another example:

  %deref_r("includedgroup","member","uid") -> (bogus,bob,cmacleod,dmacleod,pete)

When evaluating the first attribute, the ''includedgroup'' attribute
of ''cn=group'' leads to this set of entries:

    * cn=group (the original entry)
    * clan=macleod (named by cn=group)
    * cn=foundlings (named by clan=macleod)

When evaluating the second attribute, the ''member'' attribute values
for the previous set of entries produces this set of entries:

    * cn=othergroup (named by cn=group)
    * uid=bob (named by cn=group)
    * uid=cmacleod (named by cn=foundlings)
    * uid=dmacleod (named by cn=foundlings)
    * uid=pete (named by cn=othergroup)

The result list is pulled from this set of entries.

Because the plugin attempts to track updates, every attribute used here
(except for ''VALUEATTRIBUTE'') should be indexed.

=== referred ===

  referred(''SET'',''THATATTRIBUTE'',''THATOTHERATTRIBUTE'')

Creates a separated list of the values of ''THATOTHERATTRIBUTE'' stored
in directory entries which have entries in the current group in the
named ''SET'' and which also have this entry's name as a value for
''THATATTRIBUTE''.

Here are some example entries:

  dn: cn=group

  dn: uid=bob
  memberof: cn=group
  uid: bob

  dn: uid=pete
  memberof: cn=group
  uid: pete

And here's how various expressions evaluate for ''cn=group'', if
''uid=bob'' and ''uid=pete'' are both part of a set of entries named
''SET'':

  %referred("SET","memberof","foo") -> no values
  %referred("SET","memberof","uid") -> (bob,pete)

Because the plugin performs searches internally, ''THATATTRIBUTE''
should be indexed.

=== referred_r ===

  referred_r(''SET'',''ATTRIBUTE''[,''OTHERSET'',''OTHERATTRIBUTE''[,...],''VALUEATTRIBUTE'')

Searches for entries in the current group in both the current set and
''SET'' which refer to this entry using ''ATTRIBUTE'', then searches for
entries which refer to any of the just-found entries, repeating the
process until a complete set of referring entries is formed.

Then, searches for entries in ''SET'' and ''OTHERSET'' which refer to
entries in the just-found set, repeating the process until a new
complete set is formed.

The value of ''VALUEATTRIBUTE'' for every entry encountered along the
way will be returned.

Here are some example entries:

  dn: cn=group

  dn: cn=othergroup
  memberOf: cn=group

  dn: uid=bob
  uid: bob
  memberOf: cn=group

  dn: uid=pete
  uid: pete
  memberOf: cn=othergroup

And here's how various expressions evaluate for ''cn=group'', if all of
the entries with ''uid'' values are in a set named ''people'':

  %referred("people","memberof","foo") -> no values
  %referred("people","memberof","uid") -> (bob,pete)

Because the plugin performs searches internally, every attribute used
here (except for ''VALUEATTRIBUTE'') should be indexed.

=== merge ===

  merge(''SEPARATOR'',''EXPRESSION''[,...])

Evaluates and then creates a single value using multiple expressions
which may evaluate to either single values or lists.  Any expressions
which cannot be evaluated are ignored.

Here are some example entries:

  dn: cn=group
  membername: jim
  member: uid=bob
  member: uid=pete

  dn: uid=bob
  uid: bob

  dn: uid=pete
  uid: pete

And here's how an example expression evaluates for ''cn=group'':

  %merge(":","%{membername}","%deref(\"member\",\"uid\")") -> jim:bob:pete
  %merge(":","%{madeup}") -> (empty string)

=== collect ===

  collect(''EXPRESSION''[,...])

Evaluates each ''EXPRESSION'' in turn, creating one large list by
appending to it all of the values which are produced by evaluating every
expression.  Any expressions which cannot be evaluated are ignored.

Here's an example entry:

  dn: cn=group
  cn: group
  membername: jim
  member: uid=bob
  member: uid=pete

And here's how some example expressions evaluate for ''cn=group'':

  %collect("%{bogus}","%{member}","%{membername}") -> (uid=bob,uid=pete,jim)

=== link ===

  link(''EXPRESSION'',''PAD''[,''SEPARATOR'',''EXPRESSION2'',''PAD2''[,...])

Evaluates each ''EXPRESSION'' in turn to produce a list of values.  If
the lists produced by each of the expressions are not of the same
length, then each ''EXPRESSION'''s corresponding ''PAD'' value is
appended to each list, padding them out until they are all of equal
length (i.e., the length of the longest list).

Then, one list of values is produced by using the first value from each
list (separated by the corresponding SEPARATOR), then using the second
values from each list, continuing until all lists have been exhausted.

Here's an example entry:

  dn: cn=group
  cn: group
  membername: jim
  member: uid=bob
  member: uid=pete

And here's how an example expression evaluates for ''cn=group'':

  %link("%{member}","?","/","%{membername}","?") -> (uid=bob/jim,uid=pete/?)

=== ifeq ===

  ifeq(''ATTRIBUTE'',''EXPRESSION'',''MATCH-EXPRESSION'',''NONMATCH-EXPRESSION'')

Evaluates ''EXPRESSION'', and if the entry's ''ATTRIBUTE'' attribute
matches the value provided by the expression (as determined by the
server's matching rules for the attribute), evaluates and returns
''MATCH-EXPRESSION'', otherwise ''NONMATCH-EXPRESSION'' will be
evaluated and returned.

Here's an example entry:

  dn: cn=group
  cn: group
  membername: jim
  member: uid=bob
  member: uid=pete

And here's how an example expression evaluates for ''cn=group'':

  %ifeq("member","jim","","%{membername}") -> (jim)