#ifndef _SYS_
#define _SYS_

/* System-wide includes, 'cuz I'm too lazy to repeat them throughout
 * the entire source tree.
 */

// C
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <netdb.h>
#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>

#ifdef INADDR_NONE
#   define HAVE_INADDR_NONE
#else
#   define INADDR_NONE 0xffffffff
#endif

// C++
#include <exception>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <queue>

/* When the system goes out of open files, we take a nap for X secs. Set
 * to 0 to suppress this. */
#define EMFILE_SLEEP 3

/* Profiling support on/off */
#ifdef PROFILER
#   define PROFILE(x) Profiler local_prof(x)
#else
#   define PROFILE(x)
#endif

/* Memory debugging on/off */
#ifdef MEMDEBUG
#   define MEM(x) x
#else
#   define MEM(x)
#endif

/* If you fear that your malloc() / realloc() may have threading problems,
 * uncomment the following. It will cause mutex locks around the calls. */
// #define MISTRUST_MALLOC_THREADSAFE

/* If you fear racing conditions in thread_create() then uncomment this.
 * BTW it would be really weird if thread_create() weren't thread-safe., so
 * defining this is very likely not necessary. */
// #define MISTRUST_THREAD_CREATE_THREADSAFE

using namespace std;

// This is for the Servertype of serversocket()
#include "servertype/servertype"


/* Generic funtions */
string inet2string(struct in_addr in);
bool ipmatch (struct in_addr addr, struct in_addr mask);
vector<string> str2parts (string const &s, char sep);
void mt_srand(unsigned long s);
unsigned long mt_rand(void);
bool check_acl(string const &ipstr, struct in_addr ipaddr);
int sysrun (string const &s);
int maxtimeout(int a, int b);
string base64_decode(string const &s);

void mutex_lock(void *obj);
void mutex_unlock(void *obj);
bool mutex_lock_cout();
void mutex_unlock_cout();
bool mutex_lock_cerr();
void mutex_unlock_cerr();

#ifndef HAVE_INET_ATON
int inet_aton (char const *name, struct in_addr *addr);
#endif

#ifndef HAVE_STRNSTR
char *strnstr (char const *s, char const *find, size_t slen);
#endif

/* Messaging. Conditionals are defined as a macro to speed things up. */
#define msg(x) \
if (config.verbose() && mutex_lock_cout()) { 	\
    if (config.prefixtimestamp()) { 		\
	Timestamp tm; 				\
	cout << tm.desc() << ' '; 		\
    } 						\
    cout << pthread_self() << " INFO: " << x; 	\
    cout.flush(); 				\
    mutex_unlock_cout();			\
}
#define debugmsg(x) 				\
if (config.debug() && mutex_lock_cout()) { 	\
    if (config.prefixtimestamp()) { 		\
	Timestamp tm; 				\
	cout << tm.desc() << ' '; 		\
    } 						\
    cout << pthread_self() << " DEBUG: " << x; 	\
    cout.flush(); 				\
    mutex_unlock_cout();			\
}
#define reportmsg(x) 				\
if (mutex_lock_cerr()) { 			\
    if (config.prefixtimestamp()) { 		\
	Timestamp tm; 				\
	cerr << tm.desc() << ' '; 		\
    } 						\
    cerr << pthread_self() << " REPORT " << x; 	\
    mutex_unlock_cerr();		       	\
}
#define warnmsg(x) 				\
if (mutex_lock_cerr()) { 			\
    if (config.prefixtimestamp()) { 		\
	Timestamp tm; 				\
	cerr << tm.desc() << ' '; 		\
    } 						\
    cerr << pthread_self() << " WARNING " << x; \
    mutex_unlock_cerr();			\
}

#endif

