#ifndef SML3__SUPPORT_H
#define SML3__SUPPORT_H

/* ++++++++++++++++++++
 * +++ Beschreibung +++
 * ++++++++++++++++++++

 Wrapper fuer nichtunterstuetzte Funktionen
+++ */


/* ++++++++++++++++++ */
/* +++ Funktionen +++ */
/* ++++++++++++++++++ */

#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <poll.h>
#include <pwd.h>


/** SML3_daemon: siehe daemon()
 * The daemon() function is for programs wishing to detach themselves from
 * the controlling terminal and run in the background as system daemons.
 *
 * Unless the argument nochdir is non-zero, daemon() changes the current
 * working directory to the root (/).
 *
 * Unless the argument noclose is non-zero, daemon() will redirect standard
 * input, standard output and standard error to /dev/null.
 *
 * 1.Arg: nochdir
 * 2.Arg: noclose
 * Rueckgabe: 0 = OK oder -1 = Fehler
 * SML3-errno-Wert: ECHILD = Fehler bei fork()
 *                  ENODEV = Fehler bei /dev/null 
 *                  ENOENT = Fehler bei dup2()
 */
extern int SML3_daemon(int, int);


/** SML3_fnmatch: siehe fnmatch(), verwendet aber SML3_FNM_*-Definitionen;
 * Match 2.Arg against the filename pattern 1.Arg
 * 1.Arg: Pattern
 * 2.Arg: String
 * 3.Arg: SML3_FNM_*-Definitionen
 * Rueckgabe: 0 = gefunden, SML3_FNM_NOMATCH = nicht gefunden
 */
#define SML3_FNM_PATHNAME    (1 << 0)  /* No wildcard can ever match '/' */
#define SML3_FNM_NOESCAPE    (1 << 1)  /* Backslashes don't quote special chars */
#define SML3_FNM_PERIOD      (1 << 2)  /* Leading '.' is matched only explicitly */
#define SML3_FNM_FILE_NAME SML3_FNM_PATHNAME  /* Preferred GNU name */
#define SML3_FNM_LEADING_DIR (1 << 3)  /* Ignore '/...' after a match */
#define SML3_FNM_CASEFOLD    (1 << 4)  /* Compare without regard to case */
#define SML3_FNM_NOMATCH     1         /* returned if STRING does not match PATTERN */
extern int SML3_fnmatch(const char *, const char *, int);


/** SML3_pselect: siehe pselect()
 * Die Signalmaske sigmask enthaelt die gesamten zu blockierenden Signale
 * Rueckgabe: >=0 = OK oder -1 = Fehler
 * SML3-errno-Wert: EIO | EINTR = Fehler bei (p)select()
 *
 * Bsp:
 *   sigset_t sig1, sig2;
 *   sigemptyset(&sig1); sigemptyset(&sig2);
 *   // SIGCHLD zu den blockierten Signalen hinzufuegen
 *   sigaddset(&sig1, SIGCHLD);
 *   sigprocmask(SIG_BLOCK, &sig1, &sig2);  // sig2 enthaelt die vorigen blockierten Signale
 *   // SIGCHLD fuer pselect() entblockieren, indem sig2 uebergeben wird
 *   SML3_pselect(n, readfds, writefds, exceptfds, timeout, sig2);
 */
extern int SML3_pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *);


/** SML3_ppoll: siehe ppoll()
 * Die Signalmaske sigmask enthaelt die gesamten zu blockierenden Signale
 * Rueckgabe: >=0 = OK oder -1 = Fehler
 * SML3-errno-Wert: EIO | EINTR = Fehler bei (p)poll()
 *
 * Bsp:
 *   sigset_t sig1, sig2;
 *   sigemptyset(&sig1); sigemptyset(&sig2);
 *   // SIGCHLD zu den blockierten Signalen hinzufuegen
 *   sigaddset(&sig1, SIGCHLD);
 *   sigprocmask(SIG_BLOCK, &sig1, &sig2);  // sig2 enthaelt die vorigen blockierten Signale
 *   // SIGCHLD fuer ppoll() entblockieren, indem sig2 uebergeben wird
 *   SML3_ppoll(fds, nfds, timeout, &sig2);
 */
extern int SML3_ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);


/** SML3_strtoint64: siehe strtol()
 * Wandelt einen String in ein SML3_int64 um.
 * 1.Arg: String
 * 2.Arg: fuer Rueckgabe auf Zeichen hinter Zahlenwert oder NULL
 * 3.Arg: Basis (0=ermitteln auf dez,hex,okt oder 2 bis 36)
 * Rueckgabe: Zahlenwert
 *            oder Wert = SMLINT64_MAX und SML3-errno-Wert = ERANGE: Overflow
 *            oder Wert = SMLINT64_MIN und SML3-errno-Wert = ERANGE: Underflow
 *            oder Wert = 0            und SML3-errno-Wert = EINVAL: Basis falsch
 */
extern SML3_int64 SML3_strtoint64(const char *, char **, int);


/** SML3_strtouint64: siehe strtoul()
 * Wandelt einen String in ein unsigned SML3_int64 um.
 * 1.Arg: String
 * 2.Arg: fuer Rueckgabe auf Zeichen hinter Zahlenwert oder NULL
 * 3.Arg: Basis (0=ermitteln auf dez,hex,okt oder 2 bis 36)
 * Rueckgabe: Zahlenwert
 *            oder Wert = SMLINT64_MAX und SML3-errno-Wert = ERANGE: Overflow
 *            oder Wert = 0            und SML3-errno-Wert = EINVAL: Basis falsch
 */
extern unsigned SML3_int64 SML3_strtouint64(const char *, char **, int);


/** SML3_strlcpy: siehe strlcpy()
 * Kopiert 2.Arg in 1.Arg mit Groesse 3.Arg.
 * Maximal 3.Arg - 1 Zeichen werden kopiert, immer mit Ende-0.
 * 1.Arg: Ziel
 * 2.Arg: Quelle
 * 3.Arg: sizeof 1.Arg
 * Rueckgabe: strlen(2.Arg),
 *            falls Rueckgabe >= 3.Arg, wurde abgeschnitten
 */
extern size_t SML3_strlcpy(char *, const char *, size_t);


/** SML3_strlcat: siehe strlcat()
 * Fuegt 2.Arg an 1.Arg mit Gesamtgroesse 3.Arg an.
 * Maximal 3.Arg - 1 Zeichen werden kopiert, immer mit Ende-0 (ausser 3.Arg <= strlen(1.Arg))
 * 1.Arg: Ziel
 * 2.Arg: Quelle
 * 3.Arg: sizeof 1.Arg
 * Rueckgabe: strlen(2.Arg) + MIN(3.Arg, strlen(Initial-1.Arg)),
 *            falls Rueckgabe >= 3.Arg, wurde abgeschnitten
 */
extern size_t SML3_strlcat(char *, const char *, size_t);


/** SML3_getpwnam: wie getpwnam(), aber threadsicher
 * 1.Arg: Name
 * 2.Arg: Puffer fuer Antwort
 * 3.+4.Arg: interner Puffer fuer Antwort mit Groessenangabe
 *           (vorgeschlagene Groesse: sysconf(_SC_GETPW_R_SIZE_MAX), i.a. 1024 Bytes)
 * Rueckgabe: Pointer auf 2.Arg
 *            oder NULL = nicht gefunden (SML3_fehlererrno() = 0) bzw. Fehler
 * SML3-errno-Wert: wie getpwnam()
 */
extern struct passwd * SML3_getpwnam(const char *, struct passwd *, char *, size_t);


/** SML3_getpwuid: wie getpwuid(), aber threadsicher
 * 1.Arg: UserID
 * 2.Arg: Puffer fuer Antwort
 * 3.+4.Arg: interner Puffer fuer Antwort mit Groessenangabe
 *           (vorgeschlagene Groesse: sysconf(_SC_GETPW_R_SIZE_MAX), i.a. 1024 Bytes)
 * Rueckgabe: Pointer auf 2.Arg
 *            oder NULL = nicht gefunden (SML3_fehlererrno() = 0) bzw. Fehler
 * SML3-errno-Wert: wie getpwuid()
 */
extern struct passwd * SML3_getpwuid(uid_t, struct passwd *, char *, size_t);

#endif /* SML3__SUPPORT_H */
