Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / doc / developer / Libep.dbk @ master

History | View | Annotate | Download (94.7 KB)

1
<?xml version="1.0" encoding="US-ASCII"?>
2
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
3
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
4
<article class="techreport">
5
  <articleinfo>
6
    <title>Notes on "EP" Library</title>
7

    
8
    <author>
9
      <firstname>Eric</firstname>
10

    
11
      <surname>Allman</surname>
12
    </author>
13

    
14
    <copyright>
15
      <year>2008, 2014&ndash;2018 Eric P. Allman. All rights reserved.</year>
16
    </copyright>
17

    
18
    <date>2018-08-15</date>
19
  </articleinfo>
20

    
21
  <section>
22
    <title>INTRODUCTION</title>
23

    
24
    <para>This document describes the Enhanced Portability library. This is a
25
    reduced version of Eric's Portability library (designed for sendmail),
26
    removing many things that didn't work out or proved unnecessary, e.g., the
27
    entire I/O subsystem. It was originally intended to be used in sendmail,
28
    so some of the terminology is geared toward the email world; none the
29
    less, it should be generally useful.</para>
30

    
31
    <para>Programs using <symbol>libep</symbol> should be able to minimize
32
    <symbol>#ifdef</symbol> since often non-portable functionality is wrapped
33
    in portability routines; for example, BSD-derived systems and
34
    Linux-derived systems differ in how you get the name of the currently
35
    running program. These differences are hidden if the application calls
36
    <function>ep_app_getprogname</function>.</para>
37

    
38
    <section>
39
      <title>Design Goals</title>
40

    
41
      <itemizedlist>
42
        <listitem>
43
          <para>Portable, to the extent possible. Where not possible, there
44
          needs to be a clearly codified way to represent the externally
45
          visible semantic differences.</para>
46
        </listitem>
47

    
48
        <listitem>
49
          <para>Efficient.</para>
50
        </listitem>
51

    
52
        <listitem>
53
          <para>Customizable -- try to implement mechanism, not policy.</para>
54
        </listitem>
55

    
56
        <listitem>
57
          <para>TBD: It should be entirely UTF-8 internally. Any translations
58
          to other character sets should be done on input or output, and then
59
          only as strictly necessary.</para>
60
        </listitem>
61
      </itemizedlist>
62
    </section>
63

    
64
    <section>
65
      <title>Assumptions</title>
66

    
67
      <para>Use of this library requires that you have a C compiler that is
68
      compliant with ANSI C as defined by ANSI/ISO 9899-1999. Also requires an
69
      environment that is at least Posix based on Posix.1-2008.</para>
70
    </section>
71

    
72
    <section>
73
      <title>Conventions</title>
74

    
75
      <para><itemizedlist>
76
          <listitem>
77
            <para>All externally visible names (i.e., those not declared
78
            "static" in a file) shall be named ep_* (for routine names) or Ep*
79
            (for variable names). In a few cases, the names may begin with
80
            __ep or __Ep; such names would be in the global namespace, but
81
            would be intended for use internal to the library only. There are
82
            a few cases where "standard" names (such as
83
            <function>strlcpy</function>) are defined if they are not included
84
            in the standard library.</para>
85
          </listitem>
86
        </itemizedlist></para>
87
    </section>
88

    
89
    <section>
90
      <title>Terminology</title>
91

    
92
      <section>
93
        <title>Warning, Error, Severe, Abort</title>
94

    
95
        <para>These words get used fairly loosely, so they are worth defining.
96
        In the context of libep:</para>
97

    
98
        <itemizedlist>
99
          <listitem>
100
            <para>Warning means a condition that is expected in normal
101
            operations, but is not the usual case. Reading an end-of-file on a
102
            file might be a warning. Applications need to be aware of these,
103
            but are expected to either ignore them or recover easily. This can
104
            also be used for temporary errors which are likely to recover
105
            after a delay. For example, the inability to open a connection to
106
            a remote server might recover automatically if that server is
107
            re-started. However, this sort of warnings that persist should
108
            turn into permanent errors in a fashion appropriate for the
109
            application.</para>
110
          </listitem>
111

    
112
          <listitem>
113
            <para>Error means a situation that should not occur, but isn't
114
            terribly unusual. For example, an attempt to open a file that
115
            isn't accessible would be an error. Applications must be aware of
116
            such conditions and handle them gracefully.</para>
117
          </listitem>
118

    
119
          <listitem>
120
            <para>Severe means a situation that should not occur iand requires
121
            exceptional handling. Severe errors are drastic conditions, but
122
            are not so severe that the application can't take some reasonable
123
            backout action.</para>
124
          </listitem>
125

    
126
          <listitem>
127
            <para>Abort means a situation so drastic that an application
128
            cannot be expected to make any reasonable recovery. These might
129
            include assertion errors and memory allocation failures during a
130
            critical step (e.g., something where backing out a single thread
131
            won't solve the problem). About the only thing an application can
132
            reasonably do is log an abort error and exit. In particular, an
133
            abort is appropriate when an attempt for an application to recover
134
            is likely to do additional damage. These should be extremely
135
            rare.</para>
136
          </listitem>
137
        </itemizedlist>
138
      </section>
139
    </section>
140
  </section>
141

    
142
  <section>
143
    <title>GENERAL ISSUES</title>
144

    
145
    <para>All files using this library must use "<code>#include
146
    &lt;ep/ep.h&gt;</code>".</para>
147
  </section>
148

    
149
  <section>
150
    <title>STATUS CODES</title>
151

    
152
    <para>Almost all functions return an <type>EP_STAT</type> value. This is a
153
    short (integer-encoded) status value that gives you a brief idea of how
154
    severe the problem was and some idea of what it was, but not much else.
155
    Think of it as an errno equivalent. Functions returning any status other
156
    than OK are expected to provide some other way of returning detailed
157
    data.</para>
158

    
159
    <para><type>EP_STAT</type>s are also used as message identifiers for
160
    logging (below).</para>
161

    
162
    <para>Status codes are defined in
163
    <filename>&lt;ep/ep_stat.h&gt;</filename>.</para>
164

    
165
    <section>
166
      <title>Severities</title>
167

    
168
      <para>Severities are:</para>
169

    
170
      <variablelist termlength="20">
171
        <varlistentry>
172
          <term><errortype>EP_STAT_SEV_OK</errortype></term>
173

    
174
          <listitem>
175
            <para>Everything is fine. Detail may contain info. For messages,
176
            can be used for debugging.</para>
177
          </listitem>
178
        </varlistentry>
179

    
180
        <varlistentry>
181
          <term><errortype>EP_STAT_SEV_WARN</errortype></term>
182

    
183
          <listitem>
184
            <para>The function partially succeeded, but there is something
185
            that the application should be aware of, e.g., an end of file or a
186
            short data read. Alternatively, the functionfailed, but it might
187
            work again on a later try.</para>
188
          </listitem>
189
        </varlistentry>
190

    
191
        <varlistentry>
192
          <term><errortype>EP_STAT_SEV_ERROR</errortype></term>
193

    
194
          <listitem>
195
            <para>A normal error status. The call failed.</para>
196
          </listitem>
197
        </varlistentry>
198

    
199
        <varlistentry>
200
          <term><errortype>EP_STAT_SEV_SEVERE</errortype></term>
201

    
202
          <listitem>
203
            <para>A severe error status. The call failed, and the caller
204
            should try to back out.</para>
205
          </listitem>
206
        </varlistentry>
207

    
208
        <varlistentry>
209
          <term><errortype>EP_STAT_SEV_ABORT</errortype></term>
210

    
211
          <listitem>
212
            <para>A critical error occured &mdash; you should clean up and
213
            exit as soon as possible; the program cannot be expected to
214
            operate correctly.</para>
215
          </listitem>
216
        </varlistentry>
217
      </variablelist>
218

    
219
      <para>Some functions for testing values:</para>
220

    
221
      <variablelist>
222
        <varlistentry>
223
          <term><function>EP_STAT_SEV_ISOK</function>(st)</term>
224

    
225
          <listitem>
226
            <para>Returns true if this is an
227
            <errortype>EP_STAT_SEV_OK</errortype> status code.</para>
228
          </listitem>
229
        </varlistentry>
230

    
231
        <varlistentry>
232
          <term><function>EP_STAT_SEV_WARN</function>(st)</term>
233

    
234
          <listitem>
235
            <para>Returns true if this is an "warning" severity status code:
236
            <errortype>EP_STAT_SEV_WARN</errortype>.</para>
237
          </listitem>
238
        </varlistentry>
239

    
240
        <varlistentry>
241
          <term><function>EP_STAT_SEV_ISERROR</function>(st)</term>
242

    
243
          <listitem>
244
            <para>Returns true if this is an "error" severity status code:
245
            <errortype>EP_STAT_SEV_ERROR</errortype></para>
246
          </listitem>
247
        </varlistentry>
248

    
249
        <varlistentry>
250
          <term><function>EP_STAT_SEV_ISFAIL</function>(st)</term>
251

    
252
          <listitem>
253
            <para>Returns true if this message is a "failure" severity status
254
            code: <errortype>EP_STAT_SEV_ERROR</errortype> or higher.</para>
255
          </listitem>
256
        </varlistentry>
257

    
258
        <varlistentry>
259
          <term><function>EP_STAT_SEV_ISSEVERE</function>(st)</term>
260

    
261
          <listitem>
262
            <para>Returns true if this is an "severe" severity status code:
263
            <errortype>EP_STAT_SEV_SEVERE</errortype></para>
264
          </listitem>
265
        </varlistentry>
266

    
267
        <varlistentry>
268
          <term><function>EP_STAT_SEV_ISSFAIL</function>(st)</term>
269

    
270
          <listitem>
271
            <para>Returns true if this message is a "major" severity status
272
            code: <errortype>EP_STAT_SEV_SEVERE</errortype> or higher</para>
273
          </listitem>
274
        </varlistentry>
275

    
276
        <varlistentry>
277
          <term><function>EP_STAT_SEV_ISABORT</function>(st)</term>
278

    
279
          <listitem>
280
            <para>Returns true if this is an "abort" severity status code:
281
            <errortype>EP_STAT_SEV_ABORT</errortype></para>
282
          </listitem>
283
        </varlistentry>
284
      </variablelist>
285
    </section>
286

    
287
    <section>
288
      <title>Status Code Representation</title>
289

    
290
      <para>Status codes are represented as four-part values: severity,
291
      registry, module, and detail. The severities are described above.
292
      Registries are globally registered by neophilic.com and are defined in
293
      ep_registry.h. There are some registries for general use; in particular,
294
      registry numbers between 0x001 and 0x1FF are available for local
295
      (non-global) registry at the corporate or local level. Modules are
296
      defined by registries, and detail is defined by module. It is
297
      <emphasis>never</emphasis> acceptable to look at detail unless you
298
      recognize the module. (OK, you can print it out for debugging.) Severity
299
      = 3 bits, registry = 13 bits, module = 6 bits, detail = 10 bits.</para>
300

    
301
      <para>Any severity where the top bit is zero is considered "OK", and the
302
      rest of the word is available to encode a non-negative integer.</para>
303

    
304
      <para>Status codes are represented as structures to ensure type safety.
305
      Occassionally you might want to convert a status to or from a long
306
      int:</para>
307

    
308
      <programlisting>int      EP_STAT_TO_INT(EP_STAT stat)          // convert status to unsigned int
309
EP_STAT  EP_STAT_FROM_INT(unsigned int istat)  // convert unsigned integer to status</programlisting>
310

    
311
      <para>The constituent parts of the status code can also be
312
      extracted:</para>
313

    
314
      <variablelist>
315
        <varlistentry>
316
          <term><function>EP_STAT_SEV</function>(st)</term>
317

    
318
          <listitem>
319
            <para>Returns the severity part of the status code.</para>
320
          </listitem>
321
        </varlistentry>
322

    
323
        <varlistentry>
324
          <term><function>EP_STAT_REGISTRY</function>(st)</term>
325

    
326
          <listitem>
327
            <para>Returns the registry part of the status code.</para>
328
          </listitem>
329
        </varlistentry>
330

    
331
        <varlistentry>
332
          <term><function>EP_STAT_MODULE</function>(st)</term>
333

    
334
          <listitem>
335
            <para>Returns the module part of the status code.</para>
336
          </listitem>
337
        </varlistentry>
338

    
339
        <varlistentry>
340
          <term><function>EP_STAT_DETAIL</function>(st)</term>
341

    
342
          <listitem>
343
            <para>Returns the detail part of the status code.</para>
344
          </listitem>
345
        </varlistentry>
346
      </variablelist>
347

    
348
      <para>To compare two statuses for equality, use
349
      <function>EP_STAT_IS_SAME</function>(a, b).</para>
350

    
351
      <para>As a special case, if the severity is
352
      <errortype>EP_STAT_SEV_OK</errortype> the rest of the word is ignored;
353
      this can be used to pass small integers (no more than 31 bits) of
354
      information.</para>
355
    </section>
356

    
357
    <section>
358
      <title>Predefined Status Codes</title>
359

    
360
      <para>All status codes from this library are in the
361
      <constant>EP_REGISTRY_EPLIB</constant> registery. There are several
362
      predefined status codes for generic use, all using module
363
      <constant>EP_STAT_MOD_GENERIC</constant>:</para>
364

    
365
      <informaltable border="1">
366
        <col width="4*"/>
367

    
368
        <col width="6*"/>
369

    
370
        <tr>
371
          <td>EP_STAT_OK</td>
372

    
373
          <td>No error (also integer 0)</td>
374
        </tr>
375

    
376
        <tr>
377
          <td>EP_STAT_WARN</td>
378

    
379
          <td>Generic warning status</td>
380
        </tr>
381

    
382
        <tr>
383
          <td>EP_STAT_ERROR</td>
384

    
385
          <td>Generic error status</td>
386
        </tr>
387

    
388
        <tr>
389
          <td>EP_STAT_SEVERE</td>
390

    
391
          <td>Generic severe error status</td>
392
        </tr>
393

    
394
        <tr>
395
          <td>EP_STAT_ABORT</td>
396

    
397
          <td>Generic abortive status</td>
398
        </tr>
399

    
400
        <tr>
401
          <td>EP_STAT_OUT_OF_MEMORY</td>
402

    
403
          <td>Out of memory</td>
404
        </tr>
405

    
406
        <tr>
407
          <td>EP_STAT_ARG_OUT_OF_RANGE</td>
408

    
409
          <td>An argument was out of range</td>
410
        </tr>
411

    
412
        <tr>
413
          <td>EP_STAT_END_OF_FILE</td>
414

    
415
          <td>End of input</td>
416
        </tr>
417

    
418
        <tr>
419
          <td>EP_STAT_TIME_BADFORMAT</td>
420

    
421
          <td>Couldn't parse a date/time string</td>
422
        </tr>
423

    
424
        <tr>
425
          <td>EP_STAT_BUF_OVERFLOW</td>
426

    
427
          <td>Buffer overflow averted</td>
428
        </tr>
429

    
430
        <tr>
431
          <td>EP_STAT_ASSERT_ABORT</td>
432

    
433
          <td>Assertion failiure: backout now!</td>
434
        </tr>
435
      </informaltable>
436

    
437
      <para>There is also a special module
438
      <constant>EP_STAT_MOD_ERRNO</constant> that encodes Posix-style errnos
439
      (i.e., use <function>EP_STAT_DETAIL</function> on codes returned by that
440
      module to get the Posix errno code).</para>
441
    </section>
442

    
443
    <section>
444
      <title>Manipulating Status Codes</title>
445

    
446
      <para>There are several routines to print error codes or create them on
447
      the fly. Note that <function>ep_stat_tostr</function> returns the buffer
448
      itself.</para>
449

    
450
      <programlisting>// create status code from UNIX errno
451
extern EP_STAT  ep_stat_from_errno(
452
                        int uerrno);
453

    
454
// return string representation of status
455
char            *ep_stat_tostr(
456
                        EP_STAT estat,
457
                        char *buf,
458
                        size_t bsize);
459

    
460
// return string representation of severity (in natural language)
461
const char      *ep_stat_sev_tostr(
462
                        int sev);
463

    
464
// print a status code and abort (never returns)
465
void            ep_stat_abort(
466
                        EP_STAT estat);</programlisting>
467
    </section>
468

    
469
    <section>
470
      <title>Creating New Status Codes</title>
471

    
472
      <para>Libraries and applications can create their own specific error
473
      codes. There are four steps to do this:</para>
474

    
475
      <orderedlist>
476
        <listitem>
477
          <para>Determine the registry. The registry name space is divided as
478
          follows:</para>
479

    
480
          <informaltable border="1">
481
            <col width="4*"/>
482

    
483
            <col width="6*"/>
484

    
485
            <tr>
486
              <td>0x000 (<constant>EP_REGISTRY_GENERIC</constant>)</td>
487

    
488
              <td>reserved for generic status codes</td>
489
            </tr>
490

    
491
            <tr>
492
              <td>0x001 (<constant>EP_REGISTRY_USER</constant>)</td>
493

    
494
              <td>available for internal use to an application</td>
495
            </tr>
496

    
497
            <tr>
498
              <td>0x002&ndash;0x07F</td>
499

    
500
              <td>available for local, unregistered use, such as separate
501
              applications within an application suite</td>
502
            </tr>
503

    
504
            <tr>
505
              <td>0x080&ndash;0x0FF</td>
506

    
507
              <td>available for internal corporate registry, but not
508
              registered globally; conflicts may occur between organizations
509
              but not within an organization</td>
510
            </tr>
511

    
512
            <tr>
513
              <td>0x100 (<constant>EP_REGISTRY_EPLIB</constant>)</td>
514

    
515
              <td>reserved for libep</td>
516
            </tr>
517

    
518
            <tr>
519
              <td>0x101&ndash;0x6FF</td>
520

    
521
              <td>available for centrally managed global registry &mdash;
522
              contact the libep maintainers for an allocation</td>
523
            </tr>
524

    
525
            <tr>
526
              <td>0x700&ndash;0x7FF</td>
527

    
528
              <td>reserved</td>
529
            </tr>
530
          </informaltable>
531
        </listitem>
532

    
533
        <listitem>
534
          <para>Determine the module(s) in which the error code should exist.
535
          These must be unique within a registry and in the range
536
          0x00&ndash;0xFF.</para>
537
        </listitem>
538

    
539
        <listitem>
540
          <para>Define the error codes you want to use using
541
          <function>EP_STAT_NEW</function>, e.g.,</para>
542

    
543
          <programlisting>#define FOO_STAT_ELEPHANT    EP_STAT_NEW(ERROR, EP_REGISTRY_FOO, MOD_BAR, 1)
544
#define FOO_STAT_GIRAFFE     EP_STAT_NEW(SEVERE, EP_REGISTRY_FOO, MOD_BAR, 2)</programlisting>
545
        </listitem>
546

    
547
        <listitem>
548
          <para>(Optional step) Define the strings associated with the error
549
          codes when they are printed. These are done by populating a table
550
          and then calling <function>ep_stat_register_strings</function>. For
551
          example:</para>
552

    
553
          <programlisting>struct ep_stat_reg_strings  FooStatusCodes[] =
554
{
555
    FOO_STAT_ELEPHANT,    "elephant in the room",        },
556
    FOO_STAT_GIRAFFE,     "too tall",                    },
557
    EP_STAT_OK,           NULL,                          }
558
}
559

    
560
ep_stat_reg_strings(FooStatusCodes);</programlisting>
561
        </listitem>
562
      </orderedlist>
563
    </section>
564
  </section>
565

    
566
  <section>
567
    <title>INITIALIZATION</title>
568

    
569
    <para>Although libep will generally work without initialization, in some
570
    cases you may need to give it information about your usage. To do this
571
    call <function>ep_lib_init</function>:</para>
572

    
573
    <programlisting>#include &lt;ep/ep.h&gt;
574

    
575
EP_STAT
576
ep_lib_init(uint32_t flags)</programlisting>
577

    
578
    <para>Flags can be:</para>
579

    
580
    <informaltable>
581
      <tgroup cols="2">
582
        <tbody>
583
          <row>
584
            <entry>EP_LIB_USEPTHREADS</entry>
585

    
586
            <entry>Initialize the thread support</entry>
587
          </row>
588
        </tbody>
589
      </tgroup>
590
    </informaltable>
591
  </section>
592

    
593
  <section>
594
    <title>MEMORY ALLOCATION AND RESOURCE POOLS</title>
595

    
596
    <section>
597
      <title>Memory</title>
598

    
599
      <para>Memory support is much like malloc/free, but with some additional
600
      functionality. One crucial difference is that most of these routines do
601
      not return if memory is exhausted; instead they can call a cleanup
602
      routine that might (for example) eliminate some old cache entries, or
603
      pick a "victim" thread to kill and reclaim its memory. If successful
604
      they can continue, otherwise the process is aborted.</para>
605

    
606
      <programlisting>    #include &lt;ep/ep_mem.h&gt;
607

    
608
    void *
609
    ep_mem_malloc(size_t nbytes)       // allocate uninitialized memory
610

    
611
    void *
612
    ep_mem_zalloc(size_t nbytes)       // allocate zeroed memory
613

    
614
    void *
615
    ep_mem_ralloc(size_t nbytes)       // allocate randomized memory
616

    
617
    void *
618
    ep_mem_ealloc(size_t nbytes)       // allocate memory, failure OK
619

    
620
    void *
621
    ep_mem_realloc(size_t nbytes,      // reallocate (extend) memory
622
                void *curmem)
623

    
624
    void *
625
    ep_mem_falloc(size_t nbytes,       // allocate memory (see flags)
626
                uint32_t flags)
627

    
628
    void
629
    ep_mem_mfree(void *mem)            // free indicated memory
630

    
631
    struct ep_malloc_functions
632
    {
633
        void    *(*m_malloc)(size_t);
634
        void    *(*m_realloc)(void*, size_t);
635
        void    *(*m_valloc)(size_t);
636
        void    (*m_free)(void*);
637
    };
638

    
639
    void
640
    ep_mem_set_malloc_functions(       // set underlying malloc functions
641
                struct ep_malloc_functions *funcs)</programlisting>
642

    
643
      <para>The <function>ep_mem_malloc</function>,
644
      <function>ep_mem_zalloc</function>, <function>ep_mem_ralloc</function>,
645
      and <function>ep_mem_realloc</function> are all implemented in terms of
646
      <function>ep_mem_falloc</function>, which uses flags to tune the
647
      behavior (see below). The primary interface is
648
      <function>ep_mem_malloc</function>, which returns uninitialized data;
649
      <function>ep_mem_zalloc</function> returns zeroed memory, and
650
      <function>ep_mem_ralloc</function> returns memory that is initialized to
651
      random or some other nonsensical data. The last would probably be used
652
      only for debugging, and can be turned on at runtime using a debug flag
653
      <remark>XXX TBD</remark>.</para>
654

    
655
      <para>In all allocation schemes, the function returns a pointer to the
656
      allocated data &mdash; they cannot normally return
657
      <constant>NULL</constant> (but see below). If they cannot allocate the
658
      memory, they <remark>do error recovery (XXX describe)</remark>. If
659
      recovery fails, the allocation system will abort the process. However,
660
      <function>ep_mem_ealloc</function> can return <constant>NULL</constant>
661
      on memory allocation failure, as can <function>ep_mem_falloc</function>
662
      if the <constant>EP_MEM_F_FAILOK</constant> flag bit is set (see
663
      below).</para>
664

    
665
      <para>Flag bits are as follows:</para>
666

    
667
      <variablelist>
668
        <varlistentry>
669
          <term><constant>EP_MEM_F_FAILOK</constant></term>
670

    
671
          <listitem>
672
            <para>Permits the routine to return <constant>NULL</constant> on
673
            failure. This modifies the behavior described above. Note that if
674
            this is set every call to the <function>ep_*malloc</function>
675
            routines may potentially fail.</para>
676
          </listitem>
677
        </varlistentry>
678

    
679
        <varlistentry>
680
          <term><constant>EP_MEM_F_ZERO</constant></term>
681

    
682
          <listitem>
683
            <para>Zero any returned memory.</para>
684
          </listitem>
685
        </varlistentry>
686

    
687
        <varlistentry>
688
          <term><constant>EP_MEM_F_TRASH</constant></term>
689

    
690
          <listitem>
691
            <para>Randomize any returned memory.</para>
692
          </listitem>
693
        </varlistentry>
694

    
695
        <varlistentry>
696
          <term><constant>EP_MEM_F_ALIGN</constant></term>
697

    
698
          <listitem>
699
            <para>The application would prefer that the allocation is
700
            page-aligned. This is not available on all architectures, and
701
            other architectures do it automatically if the allocation is at
702
            least as large as a page.</para>
703
          </listitem>
704
        </varlistentry>
705

    
706
        <varlistentry>
707
          <term><constant>EP_MEM_F_WAIT</constant></term>
708

    
709
          <listitem>
710
            <para>If memory is unavailable, try to wait for it to become
711
            available (e.g., because another thread has released memory).
712
            <remark>This is not yet implemented.</remark></para>
713
          </listitem>
714
        </varlistentry>
715
      </variablelist>
716

    
717
      <para>Specifying <constant>EP_MEM_F_ZERO</constant> and
718
      <constant>EP_MEM_F_TRASH</constant> at the same time is
719
      undefined.</para>
720

    
721
      <para>Since <function>ep_mem_[mzr]alloc</function> are implemented as
722
      macros, they can't be used as pointers to functions (e.g., for
723
      specifying a memory allocator callback to a third party app). For this
724
      reason, there are also <function>ep_mem_[mzr]alloc_f</function> "real"
725
      functions to be used in this context.</para>
726

    
727
      <para>Generally, unthreaded code and most application code will probably
728
      be happy with the defaults. Threaded server code (which cannot be
729
      permitted to die) is expected to catch the out of memory condition, do
730
      some recovery operation such as terminating a task, and return
731
      <errorcode>EP_MEM_STAT_TRYAGAIN</errorcode> so the memory allocation can
732
      retry.</para>
733

    
734
      <para>[[[XXX Document ep_set_malloc_functions XXX]]]</para>
735
    </section>
736

    
737
    <section>
738
      <title>Resource Pools</title>
739

    
740
      <para>Resources are allocatable global entities such as memory, file
741
      descriptors, etc. Resources can be collected together into pools and
742
      then freed in one call. Memory is specially handled to allow fast
743
      allocation from a pool --- specifically, a chunk of memory can be
744
      allocated from the heap to a pool and then sub-allocated as needed.
745
      Allocating memory from resource pools is particularly fast for small
746
      allocations. Also, pool allocations that are of a size that is a
747
      multiple of the page size are guaranteed to return a page-aligned
748
      pointer. This is particularly useful to allow the I/O level to implement
749
      zero-copy I/O.</para>
750

    
751
      <para>The heap used is the one that is current when
752
      <function>ep_rpool_new</function> is invoked.</para>
753

    
754
      <programlisting>    #include &lt;ep/ep_mem.h&gt;
755

    
756
    EP_RPOOL *
757
    ep_rpool_new(const char *name,              // for debugging
758
                size_t qsize)                   // min memory allocation quantum
759

    
760
    EP_STAT
761
    ep_rpool_free(EP_RPOOL *rp)                 // free pool and all resources
762

    
763
    void *
764
    ep_rpool_malloc(EP_RPOOL *rp,               // the pool to allocate from
765
                size_t nbytes)                  // number of bytes
766

    
767
    void *
768
    ep_rpool_zalloc(EP_RPOOL *rp,               // the pool to allocate from
769
                size_t nbytes)                  // number of bytes
770

    
771
    void *
772
    ep_rpool_xalloc(EP_RPOOL *rp,               // the pool to allocate from
773
                size_t nbytes,                  // number of bytes
774
                const char *filename,           // file name (for debugging)
775
                int lineno,                     // line number (for debugging)
776
                uint32_t flags)                 // flag bits (see below)
777

    
778
    void *
779
    ep_rpool_strdup(EP_RPOOL *rp,               // the pool to allocate from
780
                char *str)                      // the string to save
781

    
782
    void *
783
    ep_rpool_realloc(EP_RPOOL *rp,              // pool to allocate from
784
                void *old mem,                  // old memory pointer
785
                size_t oldsize,                 // old allocation size
786
                size_t newsize)                 // new allocation size
787

    
788
    void
789
    ep_rpool_mfree(EP_RPOOL *rp,                // the pool to release to
790
                void *p);                       // the memory
791

    
792
    void
793
    ep_rpool_mfreeto(EP_RPOOL *rp,              // the pool to release to
794
                void *p);                       // restore up the pool to here
795

    
796
    EP_STAT
797
    ep_rpool_attach(EP_RPOOL *rp,               // the resource pool
798
                void freefunc(void *arg),       // a function to call on free
799
                void *arg)                      // argument to pass to it</programlisting>
800

    
801
      <para>The <function>ep_rpool_mfreeto</function>() routine lets you treat
802
      rpool memory like a stack; this call releases everything allocated back
803
      to (and including) the pointer given. If <computeroutput>p ==
804
      NULL</computeroutput>, the entire memory contents of the rpool are
805
      freed, but the rpool itself is still active. Deep care needs to be taken
806
      here: if a subordinate routine is called that allocates memory from the
807
      rpool, you may end up deallocating memory that is still in use.
808
      <remark>Not implemented at this time.</remark></para>
809

    
810
      <para>The <function>ep_rpool_attach</function>() routine is used to
811
      associate other resources (such as files) with a pool. The corresponding
812
      free functions will be invoked when the pool is freed.</para>
813

    
814
      <para>In most cases, passing in <parameter>rp</parameter> ==
815
      <constant>NULL</constant> treats the call like the corresponding heap
816
      allocation. In this case the caller is responsible for freeing the
817
      memory. For example,
818
      <function>ep_rpool_malloc</function>(<constant>NULL</constant>,
819
      <varname>nbytes</varname>) is equivalent to
820
      <function>ep_mem_malloc</function>(<varname>nbytes</varname>).</para>
821

    
822
      <para>The distinction between multiple heaps and resource pools are that
823
      heaps are not intended for application use other than for doing recovery
824
      for out-of-memory conditions. Pools are intended for general use. Pools
825
      are fast at allocation time (since they just grab space from the end of
826
      the pool) and fast at free time (since the entire pool can be
827
      deallocated at once); heaps are comparatively slow.</para>
828

    
829
      <para>When any memory collections (heaps or pools) are freed, all
830
      objects allocated from that collection are freed (i.e., their
831
      destructors are automatically invoked).</para>
832
    </section>
833

    
834
    <section>
835
      <title>Opening Memory as a File</title>
836

    
837
      <programlisting>    FILE *
838
    ep_fopen_smem(void *buf,          // block of memory to open
839
        size_t bsize,                 // size of that memory
840
        const char *mode)             // fopen(3) mode string</programlisting>
841
    </section>
842
  </section>
843

    
844
  <section>
845
    <title>TIME</title>
846

    
847
    <para>The ep library has a separate time abstraction. This is for two
848
    reasons: first, it guarantees that the number of seconds since January 1,
849
    1970 will be sufficiently long to last past 2038 (this varies from system
850
    to system), and it includes a "<structfield>tv_accuracy</structfield>"
851
    (type float) to indicate the approximate accuracy of the clock relative to
852
    absolute time. For example, a clock synchronized from a GPS clock might be
853
    accurate within perhaps 100nsec, whereas a standard crystal clock
854
    synchronized once a day might only have an accuracy of a few
855
    seconds.</para>
856

    
857
    <programlisting>#include &lt;ep/ep_time.h&gt;
858

    
859
typedef struct
860
{
861
        int64_t     tv_sec;          // seconds since Jan 1, 1970
862
        int32_t     tv_nsec;         // nanoseconds
863
        float       tv_accuracy;     // clock accuracy in seconds
864
} EP_TIME_SPEC;
865

    
866
#define EP_TIME_NOTIME      (-INT64_MAX)
867
#define EP_TIME_MAXTIME     (INT64_MAX)
868

    
869
EP_STAT
870
ep_time_now(                         // return current time
871
        EP_TIME_SPEC *tv);
872

    
873
EP_STAT
874
ep_time_deltanow(                    // return time in the future (or past)
875
        uint64_t delta_nanoseconds,
876
        EP_TIME_SPEC *tv);
877

    
878
void
879
ep_time_add_delta(                   // add a delta to a time (delta may be negative)
880
        EP_TIME_SPEC *delta,
881
        EP_TIME_SPEC *tv);
882

    
883
bool
884
ep_time_before(                      // determine if A occurred before B
885
        EP_TIME_SPEC *a,
886
        EP_TIME_SPEC *b);
887

    
888
void
889
ep_time_from_nsec(                   // create a time from a scalar number of nanoseconds
890
        int64_t nsec,
891
        EP_TIME_SPEC *tv);
892

    
893
void
894
ep_time_from_sec(                    // create a time from a scalar number of seconds
895
        int64_t sec,
896
        EP_TIME_SPEC *tv);
897

    
898
float
899
ep_time_accuracy(void);              // return putative clock accuracy
900

    
901
void
902
ep_time_setaccuracy(                 // set the clock accuracy (may not be available)
903
        float accuracy);
904

    
905
void
906
ep_time_format(                      // format a time string into a buffer
907
        EP_TIME_SPEC *tv,
908
        char *buf,
909
        size_t bufsize,
910
        uint32_t flags);
911

    
912
void
913
ep_time_print(                       // format a time string to a file
914
        EP_TIME_SPEC *tv,
915
        FILE *fp,
916
        uint32_t flags);
917

    
918
// values for ep_time_format and ep_time_print flags
919
#define EP_TIME_FMT_DEFAULT     0               // pseudo-flag
920
#define EP_TIME_FMT_HUMAN       0x00000001      // format for humans
921
#define EP_TIME_FMT_NOFUZZ      0x00000002      // suppress accuracy printing
922

    
923
EP_STAT
924
ep_time_parse(                       // parse a time string
925
        const char *timestr,
926
        EP_TIME_SPEC *tv,
927
        uint32_t flags);
928

    
929
// values for ep_time_parse flags
930
#define EP_TIME_USE_UTC         0x00000000      // assume UTC (default)
931
#define EP_TIME_USE_LOCALTIME   0x00000001      // assume times in local zone
932

    
933
EP_STAT
934
ep_time_nanosleep(                   // sleep for the indicated number of nanoseconds
935
        int64_t nanoseconds);
936

    
937
bool
938
EP_TIME_IS_VALID(                    // test to see if a timestamp is valid
939
        EP_TIME_SPEC *tv);
940

    
941
void
942
EP_TIME_INVALIDATE(                  // invalidate a timestamp
943
        EP_TIME_SPEC *tv);</programlisting>
944

    
945
    <para>"Human" formatted times are intended to be human readable, and may
946
    use non-ASCII characters. Otherwise the format is intended to be machine
947
    readable, e.g., using <function>ep_time_parse</function>.</para>
948
  </section>
949

    
950
  <section>
951
    <title>DATA STRUCTURES</title>
952

    
953
    <section>
954
      <title>Property Lists</title>
955

    
956
      <para><remark>Not implemented at this time.</remark> A series of
957
      key=value pairs. Used for many things, including configuration files.
958
      For example, looking in the "configuration" property list for
959
      "<varname>mailer.local.timeout.connect</varname>" would return the
960
      connect timeout for the local mailer. <remark>[[How does this deal with
961
      nested defaults &mdash; e.g., looking for timeout.connect if the full
962
      path cannot be found?]]</remark></para>
963

    
964
      <programlisting>    EP_PLIST *
965
    ep_plist_new(
966
                const char *name)              // for printing
967

    
968
    EP_STAT
969
    ep_plist_load(
970
                EP_PLIST *plp,                 // the list to read into
971
                FILE *sp,                      // the stream to load from
972
                const char *prefix)            // prefix added to all properties
973

    
974
    EP_STAT
975
    ep_plist_set(
976
                EP_PLIST *plp,                 // the plist in which to set
977
                const char *keyname,           // the name of the key to set
978
                const char *value)             // the value to set (will be copied)
979

    
980
    const char *
981
    ep_plist_get(
982
                EP_PLIST *plp,                 // the plist to search
983
                const char *keyname)           // the name of the key to get
984

    
985
    void
986
    ep_plist_dump(
987
                EP_PLIST *plp,                 // plist to print
988
                FILE *sp)                      // stream to print to
989

    
990
    void
991
    ep_plist_free(
992
                EP_PLIST *plp)                 // plist to free</programlisting>
993

    
994
      <para>A property list can be loaded from an external stream using
995
      <function>ep_plist_load</function>. The syntax of the file is a simple
996
      text file with "key=value" pairs on separate lines, with blank lines and
997
      those with # at the beginning of the line ignored. The values are
998
      strictly strings. <remark>[[Does it make sense to type
999
      them?]]</remark></para>
1000

    
1001
      <para><remark>[[Note the overlap between plists and the
1002
      <function>ep_adm</function> interface. Does this make
1003
      sense?]]</remark></para>
1004

    
1005
      <para>Property lists can be printed using
1006
      <function>ep_plist_dump</function>. The output format will be readable
1007
      by <function>ep_plist_load</function>. For the time being,
1008
      <varname>flags</varname> should always be <constant>0</constant>.</para>
1009

    
1010
      <warning>
1011
        <para>The property list is not guaranteed to be dumped in the same
1012
        order items are inserted.</para>
1013
      </warning>
1014
    </section>
1015

    
1016
    <section>
1017
      <title>Hashes</title>
1018

    
1019
      <programlisting>    #include &lt;ep/ep_hash.h&gt;
1020

    
1021
    EP_HASH *
1022
    ep_hash_new(
1023
                const char *name,               // for printing
1024
                EP_HASH_HASH_FUNCP *hfunc,      // alternate hash function
1025
                int tabsize)                    // hash table function size
1026

    
1027
    void
1028
    ep_hash_free(
1029
                EP_HASH *hp)                    // hash to free
1030

    
1031
    void *
1032
    ep_hash_search(
1033
                const EP_HASH *hp,              // hash to search
1034
                size_t keylen,                  // length of key
1035
                const void *key)                // pointer to key
1036

    
1037
    void *
1038
    ep_hash_insert(                     // returns old value for key
1039
                EP_HASH *hp,                    // hash to modify
1040
                size_t keylen,                  // length of key
1041
                const void *key,                // pointer to key
1042
                void *val)                      // value to insert
1043

    
1044
    ep_hash_forall(EP_HASH *hp,                 // hash to walk
1045
                void (func)(                    // function to call
1046
                        int keylen,                // key length
1047
                        const void *key,           // key value
1048
                        void *val,                 // value
1049
                        void *closure),            // from caller
1050
                void *closure)                  // passed to func
1051

    
1052
    ep_hash_dump(EP_TREE *tree,                 // tree to dump
1053
                FILE *sp)                       // stream to print on</programlisting>
1054

    
1055
      <para><remark>[[Should <function>ep_hash_dump</function> take the same
1056
      parameters as the usual object print routine? For that matter, should
1057
      there be a separate <function>ep_hash_dump</function> routine, or should
1058
      it just be a generic <function>ep_obj_dump</function>? Note that
1059
      <function>ep_hash_dump</function> is not implemented at this time, but
1060
      an internal (object-based) dump is.]]</remark></para>
1061
    </section>
1062

    
1063
    <section>
1064
      <title>Function Lists</title>
1065

    
1066
      <programlisting>    #include &lt;ep/ep_funclist.h&gt;
1067

    
1068
    EP_FUNCLIST *
1069
    ep_funclist_new(
1070
                const char *name)       // name for printing/debugging
1071

    
1072
    void
1073
    ep_funclist_free(EP_FUNCLIST *fp)   // list to free
1074

    
1075
    void
1076
    ep_funclist_push(EP_FUNCLIST *fp,   // list to push to
1077
                void (*func)(           // the function to invoke
1078
                        void *closure,  // from the ep_funclist_push call
1079
                        void *arg),     // from the ep_funclist_invoke call
1080
                void *closure)          // the closure arg to pass to it
1081

    
1082
    void
1083
    ep_funclist_pop(EP_FUNCLIST *fp)    // list to pop from, value discarded
1084

    
1085
    void
1086
    ep_funclist_clear(EP_FUNCLIST *fp)  // list to clear
1087

    
1088
    void
1089
    ep_funclist_invoke(EP_FUNCLIST *fp, // invoke all functions in list
1090
                void *arg)              // second func arg</programlisting>
1091
    </section>
1092
  </section>
1093

    
1094
  <section>
1095
    <title>CRYPTOGRAPHIC SUPPORT</title>
1096

    
1097
    <para>The current implementation wraps the OpenSSL library, but it could
1098
    be retargeted.</para>
1099

    
1100
    <para>Before any cryptographic functions can be used, the library must be
1101
    initialized:</para>
1102

    
1103
    <programlisting>void         ep_crypto_init(uint32_t flags)</programlisting>
1104

    
1105
    <para>At the moment flags is unused (just pass zero). There are also
1106
    several general purpose definitions, useful for declaring buffers without
1107
    memory allocation:</para>
1108

    
1109
    <informaltable border="1">
1110
      <col width="4*"/>
1111

    
1112
      <col width="6*"/>
1113

    
1114
      <tr>
1115
        <td><constant>EP_CRYPTO_MAX_PUB_KEY</constant></td>
1116

    
1117
        <td>Maximum length of a public key</td>
1118
      </tr>
1119

    
1120
      <tr>
1121
        <td><constant>EP_CRYPTO_MAX_SEC_KEY</constant></td>
1122

    
1123
        <td>Maximum length of a secret key</td>
1124
      </tr>
1125

    
1126
      <tr>
1127
        <td><constant>EP_CRYPTO_MAX_DIGEST</constant></td>
1128

    
1129
        <td>Maximum length of a message digest</td>
1130
      </tr>
1131

    
1132
      <tr>
1133
        <td><constant>EP_CRYPTO_MAX_DER</constant></td>
1134

    
1135
        <td>Maximum length of a DER-encoded key</td>
1136
      </tr>
1137
    </informaltable>
1138

    
1139
    <section>
1140
      <title>Key Management</title>
1141

    
1142
      <para>Internally all keys are represented as <type>EP_CRYPTO_KEY</type>
1143
      variables, defined in <filename>ep_crypto.h</filename>. External
1144
      representations for keys may be either PEM (Privacy Enhanced Mail,
1145
      represented as text) or DER (Distinguished Encoding Rules, represented
1146
      in binary). PEM self identifies the type of key, but DER does not, so in
1147
      some cases the key type needs to be pre-arranged.</para>
1148

    
1149
      <programlisting>// on-disk key formats
1150
# define EP_CRYPTO_KEYFORM_UNKNOWN      0       // error
1151
# define EP_CRYPTO_KEYFORM_PEM          1       // PEM (ASCII-encoded text)
1152
# define EP_CRYPTO_KEYFORM_DER          2       // DER (binary ASN.1)</programlisting>
1153

    
1154
      <para>Internally, algorithms (e.g., for keys and hash/digest functions)
1155
      are represented by a scalar value. Keys also have to be identified as
1156
      public or secret.</para>
1157

    
1158
      <remark>[[Note: DH is not supported at this time.]]</remark>
1159

    
1160
      <programlisting>// key types
1161
# define EP_CRYPTO_KEYTYPE_UNKNOWN      0       // error
1162
# define EP_CRYPTO_KEYTYPE_RSA          1       // RSA
1163
# define EP_CRYPTO_KEYTYPE_DSA          2       // DSA
1164
# define EP_CRYPTO_KEYTYPE_EC           3       // Elliptic curve
1165
# define EP_CRYPTO_KEYTYPE_DH           4       // Diffie-Hellman
1166

    
1167
// flag bits
1168
# define EP_CRYPTO_F_PUBLIC             0x0000  // public key (no flags set)
1169
# define EP_CRYPTO_F_SECRET             0x0001  // secret key</programlisting>
1170

    
1171
      <para>Keys are represented as an <type>EP_CRYPTO_KEY</type>. New keys
1172
      can be created by giving the type of the key desired, the length of the
1173
      key in bits, and two other values that are interpreted by the key type.
1174
      The first is primarily for RSA and gives the exponent, and the second is
1175
      primarily for EC and gives the curve name.</para>
1176

    
1177
      <programlisting>EP_CRYPTO_KEY           *ep_crypto_key_create(
1178
                                int keytype,
1179
                                int keylen,
1180
                                int keyexp,
1181
                                const char *curve);</programlisting>
1182

    
1183
      <para>Keys can be read from or written to named files, open files, or
1184
      memory. All the read routines create and return a new key data
1185
      structure. If the <varname>keyform</varname> is
1186
      <constant>EP_CRYPTO_KEYFORM_PEM</constant> then the
1187
      <varname>keytype</varname> need not be specified.</para>
1188

    
1189
      <programlisting>EP_CRYPTO_KEY           *ep_crypto_key_read_file(
1190
                                const char *filename,
1191
                                int keyform,
1192
                                uint32_t flags);
1193
EP_CRYPTO_KEY           *ep_crypto_key_read_fp(
1194
                                FILE *fp,
1195
                                const char *filename,
1196
                                int keyform,
1197
                                uint32_t flags);
1198
EP_CRYPTO_KEY           *ep_crypto_key_read_mem(
1199
                                const void *buf,
1200
                                size_t buflen,
1201
                                int keyform,
1202
                                uint32_t flags);
1203
EP_STAT                 ep_crypto_key_write_file(
1204
                                EP_CRYPTO_KEY *key,
1205
                                const char *filename,
1206
                                int keyform,
1207
                                int cipher,
1208
                                uint32_t flags);
1209
EP_STAT                 ep_crypto_key_write_fp(
1210
                                EP_CRYPTO_KEY *key,
1211
                                FILE *fp,
1212
                                int keyform,
1213
                                int cipher,
1214
                                uint32_t flags);
1215
EP_STAT                 ep_crypto_key_write_mem(
1216
                                EP_CRYPTO_KEY *key,
1217
                                void *buf,
1218
                                size_t bufsize,
1219
                                int keyform,
1220
                                int cipher,
1221
                                uint32_t flags);</programlisting>
1222

    
1223
      <para>When finished with a key it must be freed.</para>
1224

    
1225
      <programlisting>void                    ep_crypto_key_free(
1226
                                EP_CRYPTO_KEY *key);</programlisting>
1227

    
1228
      <para>There are also some utility routines. A public and a secret key
1229
      can be compared to see if they match each other (same algorithm,
1230
      keysize, etc.) using <function>ep_crypto_key_compat</function>. Various
1231
      conversions are also included:
1232
      <function>ep_crypto_keyform_byname</function> converts a text string
1233
      (e.g., "pem") to an internal code,
1234
      <function>ep_crypto_keytype_fromkey</function> returns the type of a
1235
      key, and <function>ep_crypto_keytype_byname</function> converts a text
1236
      string to a type.</para>
1237

    
1238
      <programlisting>EP_STAT                 ep_crypto_key_compat(
1239
                                const EP_CRYPTO_KEY *pubkey,
1240
                                const EP_CRYPTO_KEY *seckey);
1241
int                     ep_crypto_keyform_byname(
1242
                                const char *fmt);
1243
int                     ep_crypto_keytype_fromkey(
1244
                                EP_CRYPTO_KEY *key);
1245
int                     ep_crypto_keytype_byname(
1246
                                const char *alg_name);</programlisting>
1247
    </section>
1248

    
1249
    <section>
1250
      <title>Message Digests (Hashes)</title>
1251

    
1252
      <para>Several message digest (cryptographic hash) algorithms are
1253
      supported. Text can be converted to one of these values, and the
1254
      algorithm type can be extracted from the internal form.</para>
1255

    
1256
      <programlisting>// digest algorithms (no more than 4 bits)
1257
# define EP_CRYPTO_MD_NULL      0
1258
# define EP_CRYPTO_MD_SHA1      1
1259
# define EP_CRYPTO_MD_SHA224    2
1260
# define EP_CRYPTO_MD_SHA256    3
1261
# define EP_CRYPTO_MD_SHA384    4
1262
# define EP_CRYPTO_MD_SHA512    5
1263

    
1264
int                     ep_crypto_md_alg_byname(
1265
                                const char *algname);
1266
int                     ep_crypto_md_type(
1267
                                EP_CRYPTO_MD *md);</programlisting>
1268

    
1269
      <para>Digests (type <type>EP_CRYPTO_MD</type>) can be created, freed,
1270
      and cloned. Cloning lets an application compute the a fixed part of a
1271
      digest (perhaps an unchanging header) and then produce separate digests
1272
      for individual records.</para>
1273

    
1274
      <programlisting>EP_CRYPTO_MD            *ep_crypto_md_new(
1275
                                int md_alg_id);
1276
EP_CRYPTO_MD            *ep_crypto_md_clone(
1277
                                EP_CRYPTO_MD *base_md);
1278
void                    ep_crypto_md_free(
1279
                                EP_CRYPTO_MD *md);</programlisting>
1280

    
1281
      <para>The typical lifetime of a digest is to be created (as above),
1282
      updated with additional data, possibly multiple times, and then
1283
      finalized to give the output hash.</para>
1284

    
1285
      <programlisting>EP_STAT                 ep_crypto_md_update(
1286
                                EP_CRYPTO_MD *md,
1287
                                void *data,
1288
                                size_t dsize);
1289
EP_STAT                 ep_crypto_md_final(
1290
                                EP_CRYPTO_MD *md,
1291
                                void *dbuf,
1292
                                size_t *dbufsize);</programlisting>
1293
    </section>
1294

    
1295
    <section>
1296
      <title>Signing and Verification</title>
1297

    
1298
      <para>Signing and verification are quite similar. A new internal
1299
      structure is created, using the same type as a message digest, data is
1300
      added to the existing hash, possibly multiple times, the signature is
1301
      created or verified, and finally the structure is freed.</para>
1302

    
1303
      <programlisting># define EP_CRYPTO_MAX_SIG      (1024 * 8)
1304

    
1305
EP_CRYPTO_MD            *ep_crypto_sign_new(
1306
                                EP_CRYPTO_KEY *skey,
1307
                                int md_alg_id);
1308
void                    ep_crypto_sign_free(
1309
                                EP_CRYPTO_MD *md);
1310
EP_STAT                 ep_crypto_sign_update(
1311
                                EP_CRYPTO_MD *md,
1312
                                void *dbuf,
1313
                                size_t dbufsize);
1314
EP_STAT                 ep_crypto_sign_final(
1315
                                EP_CRYPTO_MD *md,
1316
                                void *sbuf,
1317
                                size_t *sbufsize);
1318

    
1319
EP_CRYPTO_MD            *ep_crypto_vrfy_new(
1320
                                EP_CRYPTO_KEY *pkey,
1321
                                int md_alg_id);
1322
void                    ep_crypto_vrfy_free(
1323
                                EP_CRYPTO_MD *md);
1324
EP_STAT                 ep_crypto_vrfy_update(
1325
                                EP_CRYPTO_MD *md,
1326
                                void *dbuf,
1327
                                size_t dbufsize);
1328
EP_STAT                 ep_crypto_vrfy_final(
1329
                                EP_CRYPTO_MD *md,
1330
                                void *obuf,
1331
                                size_t obufsize);</programlisting>
1332
    </section>
1333

    
1334
    <section>
1335
      <title>Encryption and Decryption (Asymmetric)</title>
1336

    
1337
      <para>To be supplied.</para>
1338
    </section>
1339

    
1340
    <section>
1341
      <title>Encryption and Decryption (Symmetric Ciphers)</title>
1342

    
1343
      <para>Symmetric Ciphers are driven by a Chaining Mode (how subsequent
1344
      blocks have the key modified to prevent replay and brute force attacks)
1345
      and the actual cipher itself. The chaining modes are:</para>
1346

    
1347
      <informaltable border="1">
1348
        <col width="4*"/>
1349

    
1350
        <col width="6*"/>
1351

    
1352
        <tr>
1353
          <td width=""><constant>EP_CRYPTO_MODE_CBC</constant></td>
1354

    
1355
          <td>Cipher Block Chaining</td>
1356
        </tr>
1357

    
1358
        <tr>
1359
          <td width=""><constant>EP_CRYPTO_MODE_CFB</constant></td>
1360

    
1361
          <td>Cipher Feedback mode</td>
1362
        </tr>
1363

    
1364
        <tr>
1365
          <td width=""><constant>EP_CRYPTO_MODE_OFB</constant></td>
1366

    
1367
          <td>Output Feedback mode</td>
1368
        </tr>
1369
      </informaltable>
1370

    
1371
      <para>The various cipher algorithms (which is equivalent to the key
1372
      type) are:</para>
1373

    
1374
      <informaltable border="1">
1375
        <col width="4*"/>
1376

    
1377
        <col width="6*"/>
1378

    
1379
        <tr>
1380
          <td><constant>EP_CRYPTO_SYMKEY_NONE</constant></td>
1381

    
1382
          <td>Error/unencrypted</td>
1383
        </tr>
1384

    
1385
        <tr>
1386
          <td><constant>EP_CRYPTO_SYMKEY_AES128</constant></td>
1387

    
1388
          <td>Advanced Encr Std, 128-bit key</td>
1389
        </tr>
1390

    
1391
        <tr>
1392
          <td><constant>EP_CRYPTO_SYMKEY_AES192</constant></td>
1393

    
1394
          <td>Advanced Encr Std, 192-bit key</td>
1395
        </tr>
1396

    
1397
        <tr>
1398
          <td><constant>EP_CRYPTO_SYMKEY_AES256</constant></td>
1399

    
1400
          <td>Advanced Encr Std, 256-bit key</td>
1401
        </tr>
1402

    
1403
        <tr>
1404
          <td><constant>EP_CRYPTO_SYMKEY_CAMELLIA128</constant></td>
1405

    
1406
          <td>Camellia, 128-bit key</td>
1407
        </tr>
1408

    
1409
        <tr>
1410
          <td><constant>EP_CRYPTO_SYMKEY_CAMELLIA192</constant></td>
1411

    
1412
          <td>Camellia, 192-bit key</td>
1413
        </tr>
1414

    
1415
        <tr>
1416
          <td><constant>EP_CRYPTO_SYMKEY_CAMELLIA256</constant></td>
1417

    
1418
          <td>Camellia, 256-bit key</td>
1419
        </tr>
1420

    
1421
        <tr>
1422
          <td><constant>EP_CRYPTO_SYMKEY_DES</constant></td>
1423

    
1424
          <td>Data Encryption Standard, single, 56-bit key</td>
1425
        </tr>
1426

    
1427
        <tr>
1428
          <td><constant>EP_CRYPTO_SYMKEY_3DES</constant></td>
1429

    
1430
          <td>Data Encryption Standard, triple, 128-bit key (112-bit
1431
          effective)</td>
1432
        </tr>
1433

    
1434
        <tr>
1435
          <td><constant>EP_CRYPTO_SYMKEY_IDEA</constant></td>
1436

    
1437
          <td>International Data Encryption Alg, 128-bit key</td>
1438
        </tr>
1439
      </informaltable>
1440

    
1441
      <para>One value from each table are "or"ed together to specify a full
1442
      symmetric cipher. The rest of the interface is as follows:</para>
1443

    
1444
      <programlisting>/*
1445
**      The cipher is set to encrypt or decrypt when the context
1446
**      is created.
1447
**
1448
**      ep_crypto_cipher_crypt is just shorthand for a single
1449
**      call to ep_crypto_cipher_update followed by a single
1450
**      call to ep_crypto_cipher_final.  Final pads out any
1451
**      remaining block and returns that data.
1452
*/
1453

    
1454
EP_CRYPTO_CIPHER_CTX    *ep_crypto_cipher_new(
1455
                                uint32_t ciphertype,    // mode + keytype &amp; len
1456
                                uint8_t *key,           // the key
1457
                                uint8_t *iv,            // initialization vector
1458
                                bool enc);              // true =&gt; encrypt
1459
void                    ep_crypto_cipher_free(
1460
                                EP_CRYPTO_CIPHER_CTX *cipher);
1461

    
1462
EP_STAT                 ep_crypto_cipher_crypt(
1463
                                EP_CRYPTO_CIPHER_CTX *cipher,
1464
                                void *in,               // input data
1465
                                size_t inlen,           // input length
1466
                                void *out,              // output buffer
1467
                                size_t outlen);         // output buf size
1468
EP_STAT                 ep_crypto_cipher_update(
1469
                                EP_CRYPTO_CIPHER_CTX *cipher,
1470
                                void *in,               // input data
1471
                                size_t inlen,           // input length
1472
                                void *out,              // output buffer
1473
                                size_t outlen);         // output buf size
1474
EP_STAT                 ep_crypto_cipher_final(
1475
                                EP_CRYPTO_CIPHER_CTX *cipher,
1476
                                void *out,              // output buffer
1477
                                size_t outlen);         // output buf size</programlisting>
1478
    </section>
1479

    
1480
    <section>
1481
      <title>Cryptography-specific Error Codes</title>
1482

    
1483
      <para>There are several status codes that may be returned from the
1484
      cryptography routines. These are all in module
1485
      EP_STAT_MOD_CRYPTO.</para>
1486

    
1487
      <informaltable border="1">
1488
        <col width="4*"/>
1489

    
1490
        <col width="6*"/>
1491

    
1492
        <tr>
1493
          <td><errorcode>EP_STAT_CRYPTO_DIGEST</errorcode></td>
1494

    
1495
          <td>Failed to update or finalize a digest (hash)</td>
1496
        </tr>
1497

    
1498
        <tr>
1499
          <td><errorcode>EP_STAT_CRYPTO_SIGN</errorcode></td>
1500

    
1501
          <td>Failed to update or finalize a digest for signing</td>
1502
        </tr>
1503

    
1504
        <tr>
1505
          <td><errorcode>EP_STAT_CRYPTO_VRFY</errorcode></td>
1506

    
1507
          <td>Failed to update or finalize a digest for verification</td>
1508
        </tr>
1509

    
1510
        <tr>
1511
          <td><errorcode>EP_STAT_CRYPTO_BADSIG</errorcode></td>
1512

    
1513
          <td>Signature did not match</td>
1514
        </tr>
1515

    
1516
        <tr>
1517
          <td><errorcode>EP_STAT_CRYPTO_KEYTYPE</errorcode></td>
1518

    
1519
          <td>Unknown key type</td>
1520
        </tr>
1521

    
1522
        <tr>
1523
          <td><errorcode>EP_STAT_CRYPTO_KEYFORM</errorcode></td>
1524

    
1525
          <td>Unknown key format</td>
1526
        </tr>
1527

    
1528
        <tr>
1529
          <td><errorcode>EP_STAT_CRYPTO_CONVERT</errorcode></td>
1530

    
1531
          <td>Couldn't read or write a key</td>
1532
        </tr>
1533

    
1534
        <tr>
1535
          <td><errorcode>EP_STAT_CRYPTO_KEYCREATE</errorcode></td>
1536

    
1537
          <td>Couldn't create a new key</td>
1538
        </tr>
1539

    
1540
        <tr>
1541
          <td><errorcode>EP_STAT_CRYPTO_KEYCOMPAT</errorcode></td>
1542

    
1543
          <td>Public and secret keys are incompatible</td>
1544
        </tr>
1545

    
1546
        <tr>
1547
          <td><errorcode>EP_STAT_CRYPTO_CIPHER</errorcode></td>
1548

    
1549
          <td>Symmetric cipher failure</td>
1550
        </tr>
1551
      </informaltable>
1552
    </section>
1553
  </section>
1554

    
1555
  <section>
1556
    <title>APPLICATION SUPPORT</title>
1557

    
1558
    <para>The following routines are intended to provide useful support to
1559
    applications, but are not otherwise fundamental</para>
1560

    
1561
    <section>
1562
      <title>Printing Flag Words, Etc.</title>
1563

    
1564
      <programlisting>    #include &lt;ep/ep_prflags.h&gt;
1565

    
1566
    void
1567
    ep_prflags(
1568
                u_int32 flagword,               // the flags word to print
1569
                EP_PRFLAGS_DESC *flaglist,      // descriptor of flags
1570
                FILE *out)                      // output stream
1571

    
1572
    typedef struct ep_prflags_desc
1573
    {
1574
            u_int32     bits;           // bits to compare against
1575
            u_int32     mask;           // mask against flagword
1576
            char        *name;          // printable name
1577
    } EP_PRFLAGS_DESC;</programlisting>
1578

    
1579
      <para>For example, given a descriptor of:</para>
1580

    
1581
      <programlisting>        0x0000, 0x0003, "READ",
1582
        0x0001, 0x0003, "WRITE",
1583
        0x0002, 0x0003, "READWRITE",
1584
        0x0003, 0x0003, "[INVALID MODE]",
1585
        0x0004, 0x0004, "NONBLOCK",
1586
        0x0008, 0x0008, "APPEND",
1587
        0,      0,      NULL</programlisting>
1588

    
1589
      <para>then a flagword of 0x0009 would print:</para>
1590

    
1591
      <para><computeroutput> 0009&lt;WRITE,APPEND&gt;</computeroutput></para>
1592
    </section>
1593

    
1594
    <section>
1595
      <title>Printing Helpers</title>
1596

    
1597
      <para>A few routines to make it easier to create string versions of
1598
      other type variables, e.g., for
1599
      <function>ep_stat_post</function>.</para>
1600

    
1601
      <programlisting>    #include &lt;ep/ep_pcvt.h&gt;
1602

    
1603
    char *ep_pcvt_str(size_t osize,             // output buffer size
1604
                char *obuf,                     // output buffer
1605
                const char *val)                // value to convert
1606

    
1607
    char *ep_pcvt_int(size_t osize,             // output buffer size
1608
                char *obuf,                     // output buffer
1609
                int base,                       // base of value
1610
                int val)                        // value to convert</programlisting>
1611

    
1612
      <para>All of these return their input buffer.</para>
1613

    
1614
      <para>The routine <function>ep_pcvt_str</function> truncates the value
1615
      to the indicated size. If the value won't fit, it renders
1616
      "<replaceable>beginning</replaceable>...<replaceable>end</replaceable>"
1617
      where <replaceable>end</replaceable> is the last three bytes of the
1618
      value.</para>
1619
    </section>
1620

    
1621
    <section>
1622
      <title>Application Messages</title>
1623

    
1624
      <para>Associated with status printing.</para>
1625

    
1626
      <programlisting>    #include &lt;ep/ep_app.h&gt;
1627

    
1628
    void ep_app_info(const char *fmt,           // printf-style format
1629
                ...)
1630

    
1631
    void ep_app_warn(const char *fmt,           // printf-style format
1632
                ...)
1633

    
1634
    void ep_app_error(const char *fmt,          // printf-style format
1635
                ...)
1636

    
1637
    void ep_app_fatal(const char *fmt,          // printf-style format
1638
                ...)
1639

    
1640
    void ep_app_abort(const char *fmt,          // printf-style format
1641
                ...)
1642

    
1643
    void ep_app_setflags(uint32_t flags)        // set operational tweaks</programlisting>
1644

    
1645
      <para>The first three just print messages; the second two print the
1646
      message and does not return. <function>ep_app_abort</function> generates
1647
      a core dump on termination. All five use printf formats.
1648
      <function>ep_app_setflags</function> sets flags telling when to also do
1649
      logging; the flags are <constant>EP_APP_FLAG_LOGABORTS</constant>,
1650
      <constant>EP_APP_FLAG_LOGFATALS</constant>,
1651
      <constant>EP_APP_FLAG_LOGERRORS</constant>,
1652
      <constant>EP_APP_FLAG_LOGWARNINGS</constant>, and
1653
      <constant>EP_APP_FLAG_LOGINFOS</constant>. The log severity is different
1654
      for these various functions.</para>
1655

    
1656
      <programlisting>    const char *
1657
    ep_app_getprogname(void)                    // get current program name</programlisting>
1658

    
1659
      <para>This is a portability wrapper that returns the name of the current
1660
      program (essentially, the last component of argv[0]).</para>
1661
    </section>
1662

    
1663
    <section>
1664
      <title>Printing Memory</title>
1665

    
1666
      <para>To print out a block of binary memory, use ep_hexdump.</para>
1667

    
1668
      <programlisting>    #include &lt;ep/ep_hexdump.h&gt;
1669

    
1670
    void
1671
    ep_hexdump(void *bufp,                       // block of memory to print
1672
        size_t buflen,                           // size of that block
1673
        FILE *fp,                                // output file
1674
        int format,                              // see description
1675
        size_t offset);                          // offset</programlisting>
1676

    
1677
      <para>This prints a block of memory as a hexadecimal dump, optionally
1678
      with an ASCII rendition. The offset printed starts at the
1679
      <varname>offset</varname> parameter (zero to make the printed offsets be
1680
      relative to <varname>bufp</varname>). The <varname>format</varname> may
1681
      be <constant>EP_HEXDUMP_HEX</constant> to print only the hexadecimal or
1682
      <constant>EP_HEXDUMP_ASCII</constant> to also show the bytes interpreted
1683
      as ASCII (unprintable characters are substituted).</para>
1684
    </section>
1685
  </section>
1686

    
1687
  <section>
1688
    <title>DEBUGGING, TRACING, ASSERTIONS</title>
1689

    
1690
    <para>Named flags, each settable from 0 to 127.</para>
1691

    
1692
    <para>When setting flags, wildcards can be used (only <quote>*</quote>
1693
    supported for now).</para>
1694

    
1695
    <programlisting>    #include &lt;ep/ep_dbg.h&gt;
1696

    
1697
    void
1698
    ep_dbg_init(void)                   // initialize debugging
1699

    
1700
    void
1701
    ep_dbg_set(const char *fspec)       // set debug flags (command line)
1702

    
1703
    void
1704
    ep_dbg_setto(const char *fpat,      // flag pattern
1705
                int lev)                // level
1706

    
1707
    EP_DBG  <replaceable>flag</replaceable> EP_DBG_INIT(           // opaque structure for flag
1708
                        name,           // external name of flag
1709
                        desc);          // description (internal use only)
1710

    
1711
    int
1712
    ep_dbg_level(EP_DBG *flag)          // return level of given flag
1713

    
1714
    bool
1715
    ep_dbg_test(EP_DBG *flag,
1716
                 int value)             // true if flag set to &gt;= value
1717

    
1718
    void
1719
    ep_dbg_printf(fmt, ...)             // print to EpStStddbg
1720

    
1721
    void
1722
    ep_dbg_cprintf(EP_DBG *flag,        // if flag level &gt;= value,
1723
                int value,
1724
                fmt, ...)               // print fmt etc as though printf.
1725

    
1726
    void
1727
    ep_dbg_setfile(FILE *fp)            // set debug output to indicated file
1728

    
1729
    void
1730
    ep_dbg_getfile(void)                // return current debug output file</programlisting>
1731

    
1732
    <para>Assertions are intended to catch "cannot happen" cases. They are not
1733
    necessarily fatal, depending on configuration controlled by administrative
1734
    parameters: <parameter>libep.assert.maxfailures</parameter> specifies the
1735
    number of assertion failures that will be tolerated before the process
1736
    aborts; however, every <parameter>libep.assert.resetinterval</parameter>
1737
    milliseconds the failure count is reset. For example, if
1738
    <parameter>libep.assert.maxfailures</parameter> is one, all assertion
1739
    failures are fatal; if zero, none are. It defaults to 100.
1740
    <parameter>libep.assert.resetinterval</parameter> defaults to 2000 (two
1741
    seconds).</para>
1742

    
1743
    <programlisting>    #include &lt;ep/ep_assert.h&gt;
1744

    
1745
    EP_ASSERT(condition)                // fail if condition is false; returns the condition itself
1746

    
1747
    EP_ASSERT_ELSE(condition, recovery) // print and run recovery code if condition not satisfied
1748

    
1749
    EP_ASSERT_PRINT(                    // print assertion failure message
1750
            const char *msg,               // message to print
1751
            ...)                           // arguments to message
1752
    ep_assert_print(                    // print assertion failure with extra info and message
1753
            const char *file,              // file name
1754
            int line,                      // line number
1755
            const char *msg,               // message to print
1756
            ...)                           // arguments to message
1757

    
1758
    EP_ASSERT_FAILURE(                  // abort process with message
1759
            const char *msg,               // message to print
1760
            ...)                           // arguments to message
1761
    ep_assert_failure(                  // abort process with extra info and message
1762
            const char *file,              // file name
1763
            int line,                      // line number
1764
            const char *msg,               // message to print
1765
            ...)                           // arguments to message
1766

    
1767
    void    (*EpAssertInfo)(void)       // if set, call to print additional information
1768
    void    (*EpAssertAbort)(void)      // function to call before aborting
1769
    bool    EpAssertAllAbort            // if set, all assertions are immediately fatal</programlisting>
1770

    
1771
    <para>Programs may try to recover from assertion failures by testing the
1772
    result of <function>EP_ASSERT</function>, which will be true if the
1773
    condition holds. For example, either of these return an error code if a
1774
    pointer is <constant>NULL</constant>:</para>
1775

    
1776
    <programlisting>    if (!EP_ASSERT(p != NULL))
1777
        return EP_STAT_ASSERT_ABORT;
1778

    
1779
    EP_ASSERT_ELSE(p != NULL, return EP_STAT_ASSERT_ABORT);</programlisting>
1780

    
1781
    <para>Processes can force an abort as though they got an assertion failure
1782
    by calling <function>ep_assert_failure</function>. Note that this does not
1783
    attempt any recovery; <function>ep_assert_print</function> does the same
1784
    thing but does not abort. The macros
1785
    <function>EP_ASSERT_FAILURE</function> and
1786
    <function>EP_ASSERT_PRINT</function> do the same thing, but provide the
1787
    <parameter>file</parameter> name and <parameter>line</parameter> number in
1788
    the same way as the assertion tests. If the
1789
    <varname>EpAssertInfo</varname> variable is set, that function will be
1790
    called after printing the message but before aborting. It can be used to
1791
    dump process state for debugging. If the <varname>EpAssertAbort</varname>
1792
    variable is set, that function will be called after the message is printed
1793
    and immediately before the process aborts. This might do last minute
1794
    recovery or alternative termination (e.g., terminate just the thread
1795
    rather than the entire process).</para>
1796
  </section>
1797

    
1798
  <section>
1799
    <title>THREAD SUPPORT</title>
1800

    
1801
    <para>These are mostly wrappers around the pthreads library, but they will
1802
    print errors if the <code>ep.thr</code> debug flag is set to at least
1803
    4.</para>
1804

    
1805
    <programlisting>#include &lt;ep/ep_thr.h&gt;
1806

    
1807
int
1808
ep_thr_mutex_init(EP_THR_MUTEX *mtx, int type);
1809

    
1810
int
1811
ep_thr_mutex_destroy(EP_THR_MUTEX *mtx);
1812

    
1813
int
1814
ep_thr_mutex_lock(EP_THR_MUTEX *mtx);
1815

    
1816
int
1817
ep_thr_mutex_trylock(EP_THR_MUTEX *mtx);
1818

    
1819
int
1820
ep_thr_mutex_unlock(EP_THR_MUTEX *mtx);
1821

    
1822
int
1823
ep_thr_mutex_check(EP_THR_MUTEX *mtx);
1824

    
1825
int
1826
ep_thr_cond_init(EP_THR_COND *cv);
1827

    
1828
int
1829
ep_thr_cond_destroy(EP_THR_COND *cv);
1830

    
1831
int
1832
ep_thr_cond_signal(EP_THR_COND *cv);
1833

    
1834
int
1835
ep_thr_cond_wait(EP_THR_COND *cv, EP_THR_MUTEX *mtx, EP_TIME_SPEC *timeout);
1836

    
1837
int
1838
ep_thr_cond_broadcast(EP_THR_COND *cv);
1839

    
1840
int
1841
ep_thr_rwlock_init(EP_THR_RWLOCK *rwl);
1842

    
1843
int
1844
ep_thr_rwlock_destroy(EP_THR_RWLOCK *rwl);
1845

    
1846
int
1847
ep_thr_rwlock_rdlock(EP_THR_RWLOCK *rwl);
1848

    
1849
int
1850
ep_thr_rwlock_tryrdlock(EP_THR_RWLOCK *rwl);
1851

    
1852
int
1853
ep_thr_rwlock_wrlock(EP_THR_RWLOCK *rwl);
1854

    
1855
int
1856
ep_thr_rwlock_tryrwlock(EP_THR_RWLOCK *rwl);
1857

    
1858
int
1859
ep_thr_rwlock_unlock(EP_THR_RWLOCK *rwl);</programlisting>
1860

    
1861
    <para>The ep_thr_*_check routines check the structures for consistency and
1862
    print an error; this is only for debugging. <remark>This should be
1863
    expanded to include spawning threads etc.; for the time being just use the
1864
    pthreads primitives.</remark></para>
1865

    
1866
    <para>There is also a basic thread pool implementation:</para>
1867

    
1868
    <programlisting>#include &lt;ep/ep_thr.h&gt;
1869

    
1870
void
1871
ep_thr_pool_init(
1872
        int min_threads,
1873
        int max_threads,
1874
        uint32_t flags);
1875

    
1876
void
1877
ep_thr_pool_run(
1878
        void (*func)(void *),
1879
        void *arg);</programlisting>
1880

    
1881
    <para>Thread pools are initially started with
1882
    <varname>min_threads</varname> workers (which may be zero; defaults to the
1883
    <parameter>libep.thr.pool.min_workers</parameter> administrative
1884
    parameter, or 1 if that is not set). Threads will be spawned as necessary
1885
    up to <varname>max_threads</varname> total workers (defaults to
1886
    <parameter>libep.thr.pool.max_workers</parameter>; if that is not set,
1887
    defaults to twice the number of cores available).</para>
1888

    
1889
    <para>Threads are run in essentially the same way as spawning a pthreads
1890
    thread; this is really just a convenience wrapper around that so resources
1891
    can be better controlled.</para>
1892
  </section>
1893

    
1894
  <section>
1895
    <title>LOGGING</title>
1896

    
1897
    <para>Messages may be logged together with a status code:</para>
1898

    
1899
    <programlisting>#include &lt;ep/ep_log.h&gt;
1900

    
1901
void
1902
ep_log_init(
1903
        const char *tag,
1904
        int logfac,
1905
        FILE *logfile);
1906

    
1907
void
1908
ep_log_addmethod(
1909
        void (*func)(void *ctx, EP_STAT estat, const char *fmt, va_list ap),
1910
        void *ctx,
1911
        int minsev);
1912

    
1913
void
1914
ep_log(
1915
        EP_STAT estat,
1916
        const char *fmt,
1917
        ...);
1918

    
1919
void
1920
ep_logv(
1921
        EP_STAT estat,
1922
        const char *fmt,
1923
        va_list va);</programlisting>
1924

    
1925
    <para>The <function>ep_log</function> and <function>ep_logv</function>
1926
    routines send information to various system logs. The default is to send
1927
    to <function>syslog</function>(3) and to <symbol>stderr</symbol>. You can
1928
    disable or change this by calling <function>ep_log_init</function> before
1929
    the first logging call, and extend it by passing another logging method to
1930
    <function>ep_log_addmethod</function>, which causes
1931
    <parameter>func</parameter> to be called whenever a message with severity
1932
    at least the value of the <parameter>minsev</parameter> parameter
1933
    (<constant>EP_STAT_SEV_OK</constant>,
1934
    <constant>EP_STAT_SEV_WARN</constant>,
1935
    <constant>EP_STAT_SEV_ERROR</constant>,
1936
    <constant>EP_STAT_SEV_SEVERE</constant>,
1937
    <constant>EP_STAT_SEV_ABORT</constant>).</para>
1938

    
1939
    <para>The status code is logged together with the printf-style message.
1940
    The syslog severity is determined from the severity of the status code:
1941
    <constant>OK</constant> codes log an <constant>LOG_INFO</constant>
1942
    message, <constant>WARN</constant> codes log a
1943
    <constant>LOG_WARNING</constant> message, <constant>ERROR</constant> codes
1944
    log a <constant>LOG_ERR</constant> message, <constant>SEVERE</constant>
1945
    codes log a <constant>LOG_CRIT</constant> message, and
1946
    <constant>ABORT</constant> codes log a <constant>LOG_ALERT</constant>
1947
    message.</para>
1948
  </section>
1949

    
1950
  <section>
1951
    <title>ARGUMENT CRACKING</title>
1952

    
1953
    <para><remark>Not implemented at this time</remark>. To help with parsing
1954
    command line arguments. A descriptor is declared as follows:</para>
1955

    
1956
    <programlisting>    #include &lt;ep/ep_crackargv.h&gt;
1957

    
1958
    unsigned long       NTests;
1959
    long                Seed;
1960
    static char         *FileName;
1961

    
1962
    EP_CAV_DESCR        ArgvDescriptor[] =
1963
    {
1964
        { "debug",              EP_CAV_TYPE(debug),     'D',    5,
1965
                "Debug",                "debug-flags",          NULL,
1966
                EP_CAV_FLAG_NOARGS
1967
        },
1968
        { "ntests",             EP_CAV_TYPE(ulong),     'n',    1,
1969
                "Number of tests",      NULL,                   &amp;NTests,
1970
                EP_CAV_FLAG_REQUIRED
1971
        },
1972
        { "seed",               EP_CAV_TYPE(long),      's',    1,
1973
                NULL,                   NULL,                   &amp;Seed,
1974
                EP_CAV_FLAG_NONE
1975
        }
1976
        { NULL,                 EP_CAV_TYPE(string),    '\0',   0,
1977
                NULL,                   NULL,                   &amp;FileName,
1978
                EP_CAV_FLAG_NONE
1979
        }
1980
        EP_CAV_DESCR_END
1981
    };</programlisting>
1982

    
1983
    <para>The <function>ep_crackargv</function> routine is then called with an
1984
    argument vector and a descriptor:</para>
1985

    
1986
    <programlisting>    stat = ep_crackargv(const char **argv, const EP_CAV_DESCR *descr);</programlisting>
1987

    
1988
    <para>The argument vector is then matched to the descriptor and
1989
    appropriate bindings done. Duplicate and missing flags are diagnosed and
1990
    all conversions are done.</para>
1991

    
1992
    <para>The fields in the descriptor are:</para>
1993

    
1994
    <itemizedlist>
1995
      <listitem>
1996
        <para>The long name. On Unix, this is matched against arguments
1997
        beginning "--". This is case independent.</para>
1998
      </listitem>
1999

    
2000
      <listitem>
2001
        <para>The data type. This is always
2002
        <constant>EP_CAV_TYPE</constant>(something), which calls the
2003
        conversion routine named <function>ep_cvt_txt_to_something</function>
2004
        passing it the value as a text string and a pointer to the output
2005
        location (see below).</para>
2006
      </listitem>
2007

    
2008
      <listitem>
2009
        <para>The short (single character) name. On Unix, this is matched
2010
        against arguments beginning "-". Flags without values can be combined
2011
        into one flag -- that is, if "-a -b" sets two boolean flags, "-ab"
2012
        does the same thing.</para>
2013
      </listitem>
2014

    
2015
      <listitem>
2016
        <para>The number of bytes of the long name that must match. This
2017
        allows abbreviation of names. See below.</para>
2018
      </listitem>
2019

    
2020
      <listitem>
2021
        <para>The prompt. If flags are required and a prompt is available,
2022
        <function>ep_crackargv</function> can prompt for missing parameters.
2023
        Not yet implemented.</para>
2024
      </listitem>
2025

    
2026
      <listitem>
2027
        <para>The usage message to describe this parameter. Defaults to the
2028
        long name.</para>
2029
      </listitem>
2030

    
2031
      <listitem>
2032
        <para>The value pointer. A pointer to the data area in which to store
2033
        the results. If NULL, this parameter cannot accept a value.</para>
2034
      </listitem>
2035

    
2036
      <listitem>
2037
        <para>Flag bits, as described below.</para>
2038
      </listitem>
2039
    </itemizedlist>
2040

    
2041
    <para>Long flag names can be abbreviated. All characters of the command
2042
    line must match the descriptor, but only the number indicated in the "must
2043
    match" field need be present. For example, given a name in the descriptor
2044
    of "ntests" with a "must match" field of 2 will match "--ntests",
2045
    "--ntes", "--nt", but not "--ntext", "--n", or "--nteststotry".</para>
2046

    
2047
    <para>Flag bits include:</para>
2048

    
2049
    <variablelist>
2050
      <varlistentry>
2051
        <term><constant>EP_CAV_FLAG_NONE</constant></term>
2052

    
2053
        <listitem>
2054
          <para>No special processing</para>
2055
        </listitem>
2056
      </varlistentry>
2057

    
2058
      <varlistentry>
2059
        <term><constant>EP_CAV_FLAG_NOARGS</constant></term>
2060

    
2061
        <listitem>
2062
          <para>This parameter takes no arguments (e.g., a boolean)</para>
2063
        </listitem>
2064
      </varlistentry>
2065

    
2066
      <varlistentry>
2067
        <term><constant>EP_CAV_FLAG_NOMORE</constant></term>
2068

    
2069
        <listitem>
2070
          <para>This consumes all remaining arguments (normally
2071
          EP_CAV_TYPE(Vector))</para>
2072
        </listitem>
2073
      </varlistentry>
2074

    
2075
      <varlistentry>
2076
        <term><constant>EP_CAV_FLAG_MULTVAL</constant></term>
2077

    
2078
        <listitem>
2079
          <para>There can be multiple values for this parameter (only relevant
2080
          for flags)</para>
2081
        </listitem>
2082
      </varlistentry>
2083

    
2084
      <varlistentry>
2085
        <term><constant>EP_CAV_FLAG_REQUIRED</constant></term>
2086

    
2087
        <listitem>
2088
          <para>If this parameter is missing it is an error</para>
2089
        </listitem>
2090
      </varlistentry>
2091
    </variablelist>
2092

    
2093
    <para>Predefined types and the type of the corresponding value pointer
2094
    are:</para>
2095

    
2096
    <simplelist columns="3" type="horiz">
2097
      <member>bool</member>
2098

    
2099
      <member>bool_t *</member>
2100

    
2101
      <member>Booleans. Should have
2102
      <constant>EP_CAV_FLAG_NOARGS</constant>.</member>
2103

    
2104
      <member>string</member>
2105

    
2106
      <member>const char **</member>
2107

    
2108
      <member>Strings.</member>
2109

    
2110
      <member>long</member>
2111

    
2112
      <member>long *</member>
2113

    
2114
      <member>Signed long integers.</member>
2115

    
2116
      <member>ulong</member>
2117

    
2118
      <member>unsigned long *</member>
2119

    
2120
      <member>Unsigned long integers.</member>
2121

    
2122
      <member>double</member>
2123

    
2124
      <member>double *</member>
2125

    
2126
      <member>Double point floating point.</member>
2127

    
2128
      <member>vector</member>
2129

    
2130
      <member>const char ***</member>
2131

    
2132
      <member>Vectors. Must have the EP_CAV_FLAG_MULTVAL flag set. Can only be
2133
      one, and it must be at the end.</member>
2134

    
2135
      <member>debug</member>
2136

    
2137
      <member>NULL</member>
2138

    
2139
      <member>Sets debug flags</member>
2140
    </simplelist>
2141

    
2142
    <para>To appear:</para>
2143

    
2144
    <simplelist columns="2" type="horiz">
2145
      <member>int8</member>
2146

    
2147
      <member>int8_t *</member>
2148

    
2149
      <member>uint8</member>
2150

    
2151
      <member>uint8_t *</member>
2152

    
2153
      <member>int16</member>
2154

    
2155
      <member>int16_t *</member>
2156

    
2157
      <member>uint16</member>
2158

    
2159
      <member>uint16_t *</member>
2160

    
2161
      <member>int32</member>
2162

    
2163
      <member>int32_t *</member>
2164

    
2165
      <member>uint32</member>
2166

    
2167
      <member>uint32_t *</member>
2168

    
2169
      <member>int64</member>
2170

    
2171
      <member>int64_t *</member>
2172

    
2173
      <member>uint64</member>
2174

    
2175
      <member>uint64_t *</member>
2176

    
2177
      <member>admparam</member>
2178

    
2179
      <member>const char *</member>
2180
    </simplelist>
2181

    
2182
    <para>Administrative parameters (see
2183
    <function>ep_adm_getintparam</function> and
2184
    <function>ep_adm_getstrparam</function>). The value pointer is the name of
2185
    the parameter to set.</para>
2186

    
2187
    <para>New parameter types can be trivially created by defining new
2188
    routines named
2189
    <function>ep_cvt_txt_to_</function><replaceable>type</replaceable> that
2190
    take a <type>const char *</type> as input and a
2191
    <type><replaceable>type</replaceable> *</type> output pointer. They return
2192
    <type>EP_STAT</type>. Conversion errors should fail.</para>
2193
  </section>
2194

    
2195
  <section>
2196
    <title>MISCELLANEOUS STUFF</title>
2197

    
2198
    <programlisting linenumbering="numbered">    EP_UT_BITSET(uint32 bits,           // return true if any bits...
2199
                uint32_t word)          // ... are set in word
2200

    
2201
/*
2202
    EP_UT_SETBIT(uint32_t bits,         // set these bits...
2203
                uint32_t word)          // ... in this word
2204

    
2205
    EP_UT_CLRBIT(uint32 bits,           // clear these bits...
2206
                uint32_t word)          // ... in this word
2207
*/
2208

    
2209
    EP_UT_BITMAP(               // declare bitmap
2210
        name,                           // name of bitmap to declare
2211
        nbits)                          // number of bits in map
2212

    
2213
    EP_UT_CLRBITMAP(            // clear bitmap
2214
        name)                           // bitmap to clear
2215

    
2216
    EP_UT_BITNSET(int bitn,             // true if bit number bitn is set...
2217
                bitmap)                 // ... in this map
2218

    
2219
    EP_UT_SETBITN(int bitn,             // set bit number bitn...
2220
                bitmap)                 // ... in this map
2221

    
2222
    EP_UT_CLRBITN(int bitn,             // clear bit number bitn...
2223
                bitmap)                 // ... in this map
2224

    
2225
    EP_GEN_DEADBEEF                     // a value you can use to trash memory</programlisting>
2226

    
2227
    <warning>
2228
      <para>There is no checking for the BITMAP routines
2229
      (<function>EP_UT_BITNSET</function>, <function>EP_UT_SETBITN</function>,
2230
      <function>EP_UT_CLRBITN</function>) to ensure that the bit indicated is
2231
      in range for the size of the bitmap.</para>
2232
    </warning>
2233
  </section>
2234

    
2235
  <section>
2236
    <title>INTERACTION WITH THE ENVIRONMENT</title>
2237

    
2238
    <section>
2239
      <title>Global Administrative Parameters</title>
2240

    
2241
      <para>There are a bunch of parameters that we would prefer to be
2242
      settable at run time. We'll model this on sysctl(8). Before accessing
2243
      parameters you must read them using
2244
      <function>ep_adm_readparams</function>. This routine takes a
2245
      <varname>name</varname> and then looks for a file in a search path. That
2246
      path may be set using the PARAM_PATH environment variable, and defaults
2247
      to:<programlisting>.ep_adm_params:~/.ep_adm_params:/usr/local/etc/ep_adm_params:/etc/ep_adm_params</programlisting>For
2248
      example, searching for a name such as "<userinput>defaults</userinput>"
2249
      will first try to read the file
2250
      <filename>.ep_adm_params/defaults</filename>. If that is found the
2251
      search stops, otherwise it trys
2252
      <filename>~/.ep_adm_params/defaults</filename>, and so forth. New values
2253
      replace old ones, so programs that want to search more than one file
2254
      should start with the most generic one and continue to the least generic
2255
      one.</para>
2256

    
2257
      <programlisting>    #include &lt;ep/ep_adm.h&gt;
2258

    
2259
    void
2260
    ep_adm_readparams(
2261
                const char *name)       // basename of the parameter file
2262

    
2263
    int
2264
    ep_adm_getintparam(
2265
                const char *name,       // name of the parameter
2266
                int default)            // value if parameter not set
2267

    
2268
    long
2269
    ep_adm_getlongparam(
2270
                const char *name,       // name of the parameter
2271
                long default)           // value if parameter not set
2272

    
2273
    intmax_t
2274
    ep_adm_getintmaxparam(
2275
                const char *name,       // name of the parameter
2276
                intmax_t default)       // value if the parameter is not set
2277

    
2278
    bool
2279
    ep_adm_getboolparam(
2280
                const char *name,       // name of the parameter
2281
                bool default)           // value if parameter not set
2282

    
2283
    const char *
2284
    ep_adm_getstrparam(
2285
                const char *name,       // name of the parameter
2286
                char *default)          // value if parameter not set</programlisting>
2287

    
2288
      <para>Names are structured kind of like <function>sysctl</function>
2289
      arguments or X Resource names, e.g.,
2290
      "<varname>libep.stream.hfile.bsize</varname>". You must read one or more
2291
      parameter files before getting parameters.</para>
2292

    
2293
      <para>If the <constant>EP_CONF_ADM_ENV_OVERRIDE</constant> defined
2294
      constant is set to <constant>1</constant> during compilation, parameters
2295
      can be overridden in the environment. For example,</para>
2296

    
2297
      <programlisting>env swarm.gdp.routers=foo.example.com gdplogd</programlisting>
2298

    
2299
      <para>This only works if the program is running as a non-root user
2300
      without setuid.</para>
2301
    </section>
2302

    
2303
    <section>
2304
      <title>Terminal Video Sequences and Characters</title>
2305

    
2306
      <para>Mostly for debugging use. Right now compiled in for ANSI
2307
      xterms.</para>
2308

    
2309
      <programlisting>    #include &lt;ep/ep_string.h&gt;
2310

    
2311
    struct epVidSequences
2312
    {
2313
        const char    *vidnorm;       // set video to normal
2314
        const char    *vidbold;       // set video to bold
2315
        const char    *vidfaint;      // set video to faint
2316
        const char    *vidstout;      // set viadeo to "standout"
2317
        const char    *viduline;      // set video to underline
2318
        const char    *vidblink;      // set video to blink
2319
        const char    *vidinv;        // set video to invert
2320
        const char    *vidfgblack;    // set foreground black
2321
        const char    *vidfgred;      // set foreground red
2322
        const char    *vidfggreen;    // set foreground green
2323
        const char    *vidfgyellow;   // set foreground yellow
2324
        const char    *vidfgblue;     // set foreground blue
2325
        const char    *vidfgmagenta;  // set foreground magenta
2326
        const char    *vidfgcyan;     // set foreground cyan
2327
        const char    *vidfgwhite     // set foreground white
2328
        const char    *vidbgblack;    // set background black
2329
        const char    *vidbgred;      // set background red
2330
        const char    *vidbggreen;    // set background green
2331
        const char    *vidbgyellow;   // set background yellow
2332
        const char    *vidbgblue      // set background blue
2333
        const char    *vidbgmagenta;  // set background magenta
2334
        const char    *vidbgcyan;     // set background cyan
2335
        const char    *vidbtwhite;    // set background white
2336
    } *EpVid;
2337

    
2338
    struct epCharSequences
2339
    {
2340
        const char    *lquote;        // left quote sequence
2341
        const char    *rquote;        // right quote sequence
2342
        const char    *copyright;     // copyright symbol
2343
        const char    *degree;        // degree symbol
2344
        const char    *micro;         // micro symbol
2345
        const char    *plusminus;     // +/- symbol
2346
        const char    *times;         // mathematical times symbol
2347
        const char    *divide;        // mathematical division symbol
2348
        const char    *null;          // "null" symbol
2349
        const char    *notequal;      // mathematical "not equal" symbol
2350
        const char    *unprintable;   // substitution for unprintable characters
2351
        const char    *paragraph;     // paragraph symbol
2352
        const char    *section;       // section symbol
2353
        const char    *notsign;       // logical not symbol
2354
        const char    *infinity;      // infinity symbol
2355
    } *EpChar;
2356

    
2357
    EP_STAT   ep_str_vid_set(         // set video style
2358
        const char    *type);         // NULL, "none", or "ansi"
2359

    
2360
    EP_STAT   ep_str_char_set(        // set special characters
2361
        const char    *type);         // character set (see below)</programlisting>
2362

    
2363
      <para>These structures contain character sequences used for printing
2364
      video controls and special characters respectively. The
2365
      <function>ep_str_vid_set</function> routines allows you to choose the
2366
      video escape sequences. Passing <constant>NULL</constant> causes an
2367
      educated guess at the default on the basis of the <envar>TERM</envar>
2368
      environment variable. Any <envar>TERM</envar> setting beginning with
2369
      "<constant>xterm</constant>" is the same as specifying
2370
      "<constant>ansi</constant>" as the type and anything else is the same as
2371
      specifying "<constant>none</constant>" as the type (which sets all the
2372
      video strings to null strings). Blessedly, xterm doesn't seem to render
2373
      blink, nor faint or standout. Bold and blink are both rendered in bold.
2374
      So, for best results use bold, uline, and inv (and of course
2375
      norm).</para>
2376

    
2377
      <para>The <function>ep_str_char_set</function> allows you to set special
2378
      character encodings. Its parameter may be <constant>NULL</constant>
2379
      (which guesses based on the <envar>LANG</envar> environment variable),
2380
      "<constant>ascii</constant>", "<constant>iso-8859-1</constant>",
2381
      "<constant>iso-latin-1</constant>", "<constant>utf-8</constant>", or
2382
      "<constant>utf8</constant>". The mappings are shown in the following
2383
      table:</para>
2384

    
2385
      <informaltable frame="box" rules="all">
2386
        <thead>
2387
          <tr align="center">
2388
            <th>Name</th>
2389

    
2390
            <th>ASCII</th>
2391

    
2392
            <th>Other Charset</th>
2393
          </tr>
2394
        </thead>
2395

    
2396
        <tbody>
2397
          <tr>
2398
            <td>lquote</td>
2399

    
2400
            <td align="center">`</td>
2401

    
2402
            <td align="center">&laquo;</td>
2403
          </tr>
2404

    
2405
          <tr>
2406
            <td>rquote</td>
2407

    
2408
            <td align="center">'</td>
2409

    
2410
            <td align="center">&raquo;</td>
2411
          </tr>
2412

    
2413
          <tr>
2414
            <td>copyright</td>
2415

    
2416
            <td align="center">(c)</td>
2417

    
2418
            <td align="center">&copy;</td>
2419
          </tr>
2420

    
2421
          <tr>
2422
            <td>degree</td>
2423

    
2424
            <td align="center">deg</td>
2425

    
2426
            <td align="center">&deg;</td>
2427
          </tr>
2428

    
2429
          <tr>
2430
            <td>micro</td>
2431

    
2432
            <td align="center">u</td>
2433

    
2434
            <td align="center">&micro;</td>
2435
          </tr>
2436

    
2437
          <tr>
2438
            <td>plusminus</td>
2439

    
2440
            <td align="center">+/-</td>
2441

    
2442
            <td align="center">&plusmn;</td>
2443
          </tr>
2444

    
2445
          <tr>
2446
            <td>times</td>
2447

    
2448
            <td align="center">*</td>
2449

    
2450
            <td align="center">&times;</td>
2451
          </tr>
2452

    
2453
          <tr>
2454
            <td>divide</td>
2455

    
2456
            <td align="center">/</td>
2457

    
2458
            <td align="center">&divide;</td>
2459
          </tr>
2460

    
2461
          <tr>
2462
            <td>null</td>
2463

    
2464
            <td align="center">NULL</td>
2465

    
2466
            <td align="center">&empty;</td>
2467
          </tr>
2468

    
2469
          <tr>
2470
            <td>notequal</td>
2471

    
2472
            <td align="center">!=</td>
2473

    
2474
            <td align="center">&ne;</td>
2475
          </tr>
2476

    
2477
          <tr>
2478
            <td>unprintable</td>
2479

    
2480
            <td align="center">?</td>
2481

    
2482
            <td align="center">&#8999;</td>
2483
          </tr>
2484

    
2485
          <tr>
2486
            <td>paragraph</td>
2487

    
2488
            <td align="center">pp.</td>
2489

    
2490
            <td align="center">&para;</td>
2491
          </tr>
2492

    
2493
          <tr>
2494
            <td>section</td>
2495

    
2496
            <td align="center">sec.</td>
2497

    
2498
            <td align="center">&sect;</td>
2499
          </tr>
2500

    
2501
          <tr>
2502
            <td>notsign</td>
2503

    
2504
            <td align="center">(not)</td>
2505

    
2506
            <td align="center">&not;</td>
2507
          </tr>
2508

    
2509
          <tr>
2510
            <td>infinity</td>
2511

    
2512
            <td align="center">(inf)</td>
2513

    
2514
            <td align="center">&infin;</td>
2515
          </tr>
2516
        </tbody>
2517
      </informaltable>
2518

    
2519
      <para>Other values may be added to this table as needed.</para>
2520

    
2521
      <para>Example:</para>
2522

    
2523
      <programlisting>    fprintf(ep_dbg_getfile(), "Input was %s%s%s\n",
2524
                        EpVidSeq.lquote, input, EpVidSeq.rquote);</programlisting>
2525
    </section>
2526

    
2527
    <section>
2528
      <title>Startup/Shutdown</title>
2529

    
2530
      <para>If running under <systemitem>systemd</systemitem>-based versions
2531
      of Linux, it is possible to signal status changes to the startup
2532
      environment, notably about system startup and shutdown. This is only
2533
      relevant for programs that run as system daemons.</para>
2534

    
2535
      <programlisting>#include &lt;ep/ep_sd.h&gt;
2536

    
2537
void
2538
ep_sd_notifyf(
2539
        const char *fmt,
2540
        ...);</programlisting>
2541

    
2542
      <para>The <parameter>fmt</parameter> and any arguments are printed a'la
2543
      <function>printf</function>(3) to a system buffer that is delivered to
2544
      <systemitem>systemd</systemitem>. The format of that buffer is defined
2545
      by <function>sd_notify</function>(3) and is not detailed here. Roughly,
2546
      each line of the output looks like an environment variable definition.
2547
      For example:</para>
2548

    
2549
      <programlisting>// to inform the system that this service is ready:
2550
ep_sd_notifyf(
2551
        "READY=1");
2552

    
2553
// to inform the system that this service is shutting down:
2554
ep_sd_notifyf(
2555
        "STOPPING=1\n"
2556
        "STATUS=Exiting on user signal %d\n",
2557
        sig);</programlisting>
2558

    
2559
      <para>Important values include <literal>READY=1</literal>,
2560
      <literal>RELOADING=1</literal>, <literal>WATCHDOG=1</literal>, and
2561
      <literal>STOPPING=...</literal>.</para>
2562

    
2563
      <para>If the <constant>EP_OSCF_HAS_SD_NOTIFY</constant> flag is set to
2564
      zero at compilation time, this call is a no-op. This is the case on most
2565
      systems.</para>
2566

    
2567
      <remark>This should really abstract the syntax out more, rather than
2568
      making it <systemitem>systemd</systemitem> specific, so that it can
2569
      potentially be used on other systems.</remark>
2570
    </section>
2571
  </section>
2572

    
2573
  <section>
2574
    <title>TRANSLATIONS</title>
2575

    
2576
    <para>Simple string translations for certain external formats, for example
2577
    as might be used by URLs or Quoted-Printable.</para>
2578

    
2579
    <programlisting>    #include &lt;ep/ep_xlate.h&gt;
2580

    
2581
    int
2582
    ep_xlate_in(
2583
        const void *ext,                // external (encoded) string input
2584
        uchar_t *out,                   // pointer to output buffer
2585
        size_t olen,                    // length of output buffer
2586
        char stopchar,                  // input char to stop at
2587
        uint32_t how)                   // what kind of translations to do</programlisting>
2588

    
2589
    <para>Translates an external form (with encodings) into internal form
2590
    (potentially 8-bit binary). Returns the number of output bytes. The "how"
2591
    parameter tells what translations to do -- they can be combined:</para>
2592

    
2593
    <table>
2594
      <title>EP_XLATE "how" Bits</title>
2595

    
2596
      <tgroup cols="2">
2597
        <colspec/>
2598

    
2599
        <colspec colwidth="3*"/>
2600

    
2601
        <tbody>
2602
          <row>
2603
            <entry>EP_XLATE_PERCENT</entry>
2604

    
2605
            <entry>Translate "%xx" like ESMTP</entry>
2606
          </row>
2607

    
2608
          <row>
2609
            <entry>EP_XLATE_BSLASH</entry>
2610

    
2611
            <entry>Translate backslash escapes like C</entry>
2612
          </row>
2613

    
2614
          <row>
2615
            <entry>EP_XLATE_AMPER</entry>
2616

    
2617
            <entry>Translate "&amp;name;" like HTML</entry>
2618
          </row>
2619

    
2620
          <row>
2621
            <entry>EP_XLATE_PLUS</entry>
2622

    
2623
            <entry>Translate "+xx" like DNSs</entry>
2624
          </row>
2625

    
2626
          <row>
2627
            <entry>EP_XLATE_EQUAL</entry>
2628

    
2629
            <entry>Translate "=xx" like quoted-printable</entry>
2630
          </row>
2631

    
2632
          <row>
2633
            <entry>EP_XLATE_8BIT</entry>
2634

    
2635
            <entry>Translate 8-bit characters
2636
            (<function>ep_xlate_out</function> only)</entry>
2637
          </row>
2638

    
2639
          <row>
2640
            <entry>EP_XLATE_NPRINT</entry>
2641

    
2642
            <entry>Translate non-printable characters
2643
            (<function>ep_xlate_out</function> only)</entry>
2644
          </row>
2645
        </tbody>
2646
      </tgroup>
2647
    </table>
2648

    
2649
    <programlisting>    int
2650
    ep_xlate_out(
2651
        const void *in,                 // internal (not encoded) input string
2652
        size_t ilen,                    // length of in
2653
        FILE *osp,                      // encoded output stream pointer
2654
        const char *forbid,             // list of characters to encode
2655
        uint32_t how)                   // how to do output translations</programlisting>
2656

    
2657
    <para>Unlike input, it doesn't make sense to list more than one of
2658
    <constant>EP_XLATE_PERCENT</constant>,
2659
    <constant>EP_XLATE_BSLASH</constant>, <constant>EP_XLATE_EQUAL</constant>,
2660
    and <constant>EP_XLATE_PLUS</constant>. If none are listed,
2661
    <constant>EP_XLATE_PLUS</constant> is assumed.
2662
    <constant>EP_XLATE_8BIT</constant> can be added to encode all 8-bit
2663
    characters and <constant>EP_XLATE_NPRINT</constant> translates all
2664
    unprintable characters (as determined by <function>isprint(3)</function>,
2665
    which generally does understand locales). Returns the number of bytes
2666
    output to the indicated osp.</para>
2667

    
2668
    <note>
2669
      <para>[[Arguably they should both use streams for both input and
2670
      output.]]</para>
2671
    </note>
2672

    
2673
    <para>There are also routines to encode/decode binaries in base64.</para>
2674

    
2675
    <programlisting>    #include &lt;ep/ep_b64.h&gt;
2676

    
2677
    EP_STAT
2678
    ep_b64_encode(
2679
        const void *bin,                // binary data to encode
2680
        size_t bsize,                   // size of bin to encode
2681
        char *txt,                      // text output buffer
2682
        size_t tsize,                   // size of output buffer
2683
        const char *encoding)           // type of encoding (see below)
2684

    
2685
    EP_STAT
2686
    ep_b64_decode(
2687
        const char *txt,                // text to decode
2688
        size_t tsize,                   // stop after tsize characters
2689
        void *bin,                      // binary output buffer
2690
        size_t bsize,                   // size of bin buffer
2691
        const char *encoding)           // type of encoding (see below)
2692

    
2693
    #define EP_B64_NOWRAP       0x00    // never wrap lines
2694
    #define EP_B64_WRAP64       0x01    // wrap at 64 characters
2695
    #define EP_B64_WRAP76       0x02    // wrap at 76 characters
2696
    #define EP_B64_WRAPMASK     0x03    // bit mask for wrapping
2697
    #define EP_B64_PAD          0x04    // pad with '='
2698
    #define EP_B64_IGNCRUD      0x08    // ignore unrecognized chars
2699

    
2700
    // encodings for common standards
2701
    #define EP_B64_ENC_MIME     "+/N"   // WRAP76  PAD  IGNCRUD
2702
    #define EP_B64_ENC_PEM      "+/E"   // WRAP64  PAD -IGNCRUD
2703
    #define EP_B64_ENC_URL      "-_@"   // NOWRAP -PAD -IGNCRUD</programlisting>
2704

    
2705
    <para>The encoding is a three character string. The first two characters
2706
    are used to represent the codes for positions 62 and 63 (these are the
2707
    only two that are not letters or digits). The third is used as flag bits
2708
    to indicate variations for various encodings. The three most common
2709
    strings are included as defined constants (for MIME email, Privacy
2710
    Enhanced Mail, and URLs).</para>
2711
  </section>
2712

    
2713
  <section>
2714
    <title>XXX TO BE DONE</title>
2715

    
2716
    <itemizedlist>
2717
      <listitem>
2718
        <para>Document ep_pprint.</para>
2719
      </listitem>
2720

    
2721
      <listitem>
2722
        <para>Document ep_dumpfds (shows open file descriptors (for
2723
        debugging).</para>
2724
      </listitem>
2725

    
2726
      <listitem>
2727
        <para>Document ep_fread_unlocked.</para>
2728
      </listitem>
2729
    </itemizedlist>
2730
  </section>
2731
</article>