--- /dev/null
+AUTOMAKE_OPTIONS = foreign
+AM_CFLAGS = $(MYSQL_CFLAGS)
+
+BUILT_SOURCES = version.c
+version.c: checkversion
+checkversion:
+ cd src && chmod +x version.sh && ./version.sh && cd ..
+
+noinst_PROGRAMS = transirc
+
+transirc_SOURCES = src/version.c \
+ src/ConfigParser.c \
+ src/IOHandler.c \
+ src/IOEngine_select.c \
+ src/main.c \
+ src/ServerSocket.c \
+ src/tools.c \
+ src/UserClient.c
+
+transirc_LDADD = $(MYSQL_LIBS) $(SYSTEM_LIBS)
+
+install-exec-local:
+ $(INSTALL) -d -m 755 $(prefix)
+ $(INSTALL) -m 644 $(srcdir)/AUTHORS $(prefix)
+ $(INSTALL) -m 644 $(srcdir)/COPYING $(prefix)
+ $(INSTALL) -m 644 $(srcdir)/INSTALL $(prefix)
+ $(INSTALL) -m 644 $(srcdir)/VERSION $(prefix)
+ $(INSTALL) -m 744 ./transirc $(prefix)
+ @echo
+ @echo TransparentIRC-$(VERSION) has been installed to $(prefix)
+ @echo Edit the transirc.example.conf and save it as transirc.conf before you start!
+ @echo
--- /dev/null
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.67])
+AC_INIT([TransparentIRC], [0.1], [bugs@pk910.de], [transirc], [http://no.url])
+AC_PREFIX_DEFAULT([~/transirc])
+AC_CANONICAL_TARGET
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+AM_SILENT_RULES([yes])
+AC_CONFIG_HEADERS([config.h])
+
+LT_INIT([disable-static])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_AWK
+
+# Checks for libraries.
+# Get MySQL library and include locations
+AC_ARG_WITH([mysql],
+ [AS_HELP_STRING([--with-mysql=DIR],
+ [location of the MySQL headers, defaults to /usr/include/mysql])],
+ [MYSQL_CFLAGS="-I$withval"],
+ [MYSQL_CFLAGS='-I/usr/include/mysql'])
+AC_SUBST([MYSQL_CFLAGS])
+
+AC_ARG_WITH([mysql-lib],
+ [AS_HELP_STRING([--with-mysql-lib=DIR], [location of the MySQL libraries])],
+ [MYSQL_LIBS="-L$withval -lmysqlclient"],
+ [MYSQL_LIBS='-lmysqlclient'])
+AC_SUBST([MYSQL_LIBS])
+
+AC_ARG_WITH([winsock],
+ [AS_HELP_STRING([--with-winsock], [use winsock (WIN32 systems)])],
+ [SYSTEM_LIBS='-lws2_32'],
+ [SYSTEM_LIBS='-ldl'])
+AC_SUBST([SYSTEM_LIBS])
+
+do_have_ssl="no";
+AC_CHECK_LIB(ssl, SSL_read, [
+ AC_CHECK_LIB(crypto, X509_new, [
+ AC_CHECK_HEADERS(openssl/ssl.h openssl/err.h openssl/rand.h, [
+ do_have_ssl="yes";
+ ])
+ ])
+])
+
+if test x"$do_have_ssl" = xyes; then
+ LIBS="$LIBS -lssl -lcrypto"
+ AC_DEFINE([HAVE_SSL], 1, [Define if you are using SSL])
+fi
+
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug], [debug mode (compile using -O0 -Wall -Wshadow -Werror)])],
+ [CFLAGS='-g -O0 -Wall -Wshadow -Werror'],
+ [CFLAGS='-g -O2'])
+
+CFLAGS="$CFLAGS -D_GNU_SOURCE"
+
+# Checks for header files.
+AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h windows.h winsock2.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([gethostbyname memset select socket strchr strdup strstr])
+
+AC_CONFIG_FILES(Makefile)
+AC_OUTPUT
\ No newline at end of file
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
#include "ConfigParser.h"
+#include "tools.h"
#define ENTRYTYPE_BLOCK 1
#define ENTRYTYPE_STRING 2
-/* ConfigParser.h - NeonServ v5.4
+/* ConfigParser.h - TransparentIRC 0.1
* Copyright (C) 2011-2012 Philipp Kreil (pk910)
*
* This program is free software: you can redistribute it and/or modify
#ifndef _ConfigParser_h
#define _ConfigParser_h
-#include "main.h"
+#include "overall.h"
-#ifndef DND_FUNCTIONS
int loadConfig(const char *filename);
-/* MODULAR ACCESSIBLE */ int get_int_field(char *field_path);
-/* MODULAR ACCESSIBLE */ char *get_string_field(char *field_path);
+int get_int_field(char *field_path);
+char *get_string_field(char *field_path);
char **get_all_fieldnames(char *block_path);
void free_loaded_config();
#endif
-#endif
tdiff.tv_sec--;
tdiff.tv_usec += 1000000; //1 sec
}
- if(timeval_is_smaler(&tdiff, timeout)) {
+ if(timeval_is_smaler((&tdiff), timeout)) {
timeout->tv_sec = tdiff.tv_sec;
timeout->tv_usec = tdiff.tv_usec;
}
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "IOHandler.h"
+#include "IOEngine.h"
struct IODescriptor *first_descriptor = NULL;
static void iohandler_init_engine() {
//try other engines
- if(engine)
+ if(engine) {
//found an useable IO engine
- else if (engine_select.init())
+ } else if (engine_select.init())
engine = &engine_select;
else {
//STDERR: found no useable IO engine
}
}
-struct IODescriptor *iohandler_add(int sockfd, IOType type, iohandler_callback *callback) {
+struct IODescriptor *iohandler_add(int sockfd, enum IOType type, iohandler_callback *callback) {
//just add a new IODescriptor
struct IODescriptor *descriptor = calloc(1, sizeof(*descriptor));
if(!descriptor) return NULL;
descriptor->state = IO_CLOSED;
descriptor->callback = callback;
if(type != IOTYPE_TIMER) {
- descriptor->readbuf.buffer = malloc(IOREADBUFLEN + 2);
+ descriptor->readbuf.buffer = malloc(IO_READ_BUFLEN + 2);
descriptor->readbuf.bufpos = 0;
- descriptor->readbuf.buflen = IOREADBUFLEN;
- descriptor->writebuf.buffer = malloc(IOREADBUFLEN + 2);
+ descriptor->readbuf.buflen = IO_READ_BUFLEN;
+ descriptor->writebuf.buffer = malloc(IO_READ_BUFLEN + 2);
descriptor->writebuf.bufpos = 0;
- descriptor->writebuf.buflen = IOREADBUFLEN;
+ descriptor->writebuf.buflen = IO_READ_BUFLEN;
}
if(!engine) {
//add IODescriptor to the list
descriptor->prev = NULL;
descriptor->next = first_descriptor;
- first_descriptor->prev = descriptor;
+ if(first_descriptor)
+ first_descriptor->prev = descriptor;
first_descriptor = descriptor;
return descriptor;
}
}
-struct IODescriptor *iohandler_timer(timeval timeout, iohandler_callback *callback) {
+struct IODescriptor *iohandler_timer(struct timeval timeout, iohandler_callback *callback) {
struct IODescriptor *descriptor;
descriptor = iohandler_add(-1, IOTYPE_TIMER, callback);
if(!descriptor) return NULL;
return descriptor;
}
-struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, const char *bind, iohandler_callback *callback) {
+struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, const char *bindhost, iohandler_callback *callback) {
//non-blocking connect
int sockfd;
struct addrinfo hints, *res, *freeres;
ip6->sin6_port = htons(port);
struct sockaddr_in6 *ip6vhost = NULL;
- if (bind && !getaddrinfo(bind, NULL, &hints, &res)) {
+ if (bindhost && !getaddrinfo(bindhost, NULL, &hints, &res)) {
while (res) {
switch (res->ai_family) {
case AF_INET6:
ip4->sin_port = htons(port);
struct sockaddr_in *ip4vhost = NULL;
- if (bind && !getaddrinfo(bind, NULL, &hints, &res)) {
+ if (bindhost && !getaddrinfo(bindhost, NULL, &hints, &res)) {
while (res) {
switch (res->ai_family) {
case AF_INET:
/* I hope you're using the Win32 backend or something else that
* automatically marks the file descriptor non-blocking...
*/
- (void)flags;
#endif
descriptor = iohandler_add(sockfd, IOTYPE_CLIENT, callback);
if(!descriptor) {
descriptor->state = IO_CONNECTING;
descriptor->read_lines = 1;
engine->update(descriptor);
+ return descriptor;
}
struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, iohandler_callback *callback) {
/* I hope you're using the Win32 backend or something else that
* automatically marks the file descriptor non-blocking...
*/
- (void)flags;
#endif
descriptor = iohandler_add(sockfd, IOTYPE_SERVER, callback);
if(!descriptor) {
listen(sockfd, 1);
descriptor->state = IO_LISTENING;
engine->update(descriptor);
+ return descriptor;
}
void iohandler_write(struct IODescriptor *iofd, const char *line) {
return;
}
memcpy(iofd->writebuf.buffer + iofd->writebuf.bufpos, data, datalen);
+ iofd->writebuf.bufpos += datalen;
engine->update(iofd);
}
if(readable) { //could not connect
callback_event.type = IOEVENT_NOTCONNECTED;
socklen_t arglen;
- arglen = sizeof(callback_event.errno);
- if (getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &callback_event.errno, &arglen) < 0)
- callback_event.data.errno = errno;
+ arglen = sizeof(callback_event.data.errid);
+ if (getsockopt(iofd->fd, SOL_SOCKET, SO_ERROR, &callback_event.data.errid, &arglen) < 0)
+ callback_event.data.errid = errno;
iofd->state = IO_CLOSED;
} else if(writeable) {
callback_event.type = IOEVENT_CONNECTED;
if(bytes <= 0) {
if (errno != EAGAIN) {
callback_event.type = IOEVENT_CLOSED;
- callback_event.data.errno = errno;
+ callback_event.data.errid = errno;
}
} else {
- int i, used_bytes = 0, buffer_offset = 0;
+ int i, used_bytes = 0;
iofd->readbuf.bufpos += bytes;
callback_event.type = IOEVENT_RECV;
for(i = 0; i < iofd->readbuf.bufpos; i++) {
IOEVENT_READABLE, /* socket is readable - not read anything yet, could also be disconnect notification */
IOEVENT_RECV, /* client socket received something (recv_str valid) */
IOEVENT_CONNECTED, /* client socket connected successful */
- IOEVENT_NOTCONNECTED, /* client socket could not connect (errno valid) */
- IOEVENT_CLOSED, /* client socket lost connection (errno valid) */
+ IOEVENT_NOTCONNECTED, /* client socket could not connect (errid valid) */
+ IOEVENT_CLOSED, /* client socket lost connection (errid valid) */
IOEVENT_ACCEPT, /* server socket accepted new connection (accept_fd valid) */
IOEVENT_TIMEOUT /* timer timed out */
};
struct IOBuffer {
- char buffer;
+ char *buffer;
size_t bufpos, buflen;
};
struct IODescriptor {
int fd;
- IOType type;
- IOStatus state;
+ enum IOType type;
+ enum IOStatus state;
struct timeval timeout;
iohandler_callback *callback;
struct IOBuffer readbuf;
};
struct IOEvent {
- IOEventType type;
+ enum IOEventType type;
struct IODescriptor *iofd;
union {
char *recv_str;
int accept_fd;
- int errno;
+ int errid;
} data;
};
-struct IODescriptor *iohandler_add(int sockfd, IOType type, iohandler_callback *callback);
-struct IODescriptor *iohandler_timer(timeval timeout, iohandler_callback *callback);
+struct IODescriptor *iohandler_add(int sockfd, enum IOType type, iohandler_callback *callback);
+struct IODescriptor *iohandler_timer(struct timeval timeout, iohandler_callback *callback);
struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, const char *bind, iohandler_callback *callback);
struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, iohandler_callback *callback);
void iohandler_write(struct IODescriptor *iofd, const char *line);
static struct ServerSocket *serversocket_create(struct IODescriptor *iofd) {
struct ServerSocket *sock = malloc(sizeof(*sock));
sock->iofd = iofd;
+ iofd->data = sock;
sock->clientcount = 0;
//add ServerSocket to the list
sock->prev = NULL;
sock->next = serversockets;
- serversockets->prev = sock;
+ if(serversockets)
+ serversockets->prev = sock;
serversockets = sock;
+ return sock;
}
static void serversocket_delete(struct ServerSocket *server) {
struct ServerSocket *serversocket_listen(char *hostname, int port) {
struct IODescriptor *iofd = iohandler_listen(hostname, port, serversocket_callback);
- if(iofd) {
- struct ServerSocket *server = serversocket_create(iofd);
- return server;
- }
- return NULL;
+ if(!iofd) return NULL;
+ struct ServerSocket *server = serversocket_create(iofd);
+ return server;
}
void serversocket_close(struct ServerSocket *server, int keep_clients) {
}
static void serversocket_callback(struct IOEvent *event) {
+ struct ServerSocket *server = event->iofd->data;
switch(event->type) {
case IOEVENT_ACCEPT:
- struct ServerSocket *server = NULL;
- for(server = serversockets; server; server = server->next) {
- if(server->iofd == event->iofd)
- break;
- }
- if(server)
- userclient_accepted(server, event->accept_fd)
+ userclient_accepted(server, event->data.accept_fd);
+ break;
+ default:
break;
}
}
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "UserClient.c"
+#include "UserClient.h"
#include "IOHandler.h"
+#include "ServerSocket.h"
static void userclient_callback(struct IOEvent *event);
iohandler_update(iofd);
client = malloc(sizeof(*client));
client->iofd = iofd;
+ iofd->data = client;
client->server = server;
server->clientcount++;
//add UserClient to the list
- sock->prev = NULL;
- sock->next = serversockets;
- serversockets->prev = sock;
- serversockets = sock;
+ client->prev = NULL;
+ client->next = userclients;
+ if(userclients)
+ userclients->prev = client;
+ userclients = client;
//let's say hello to the client
iohandler_printf(iofd, "NOTICE AUTH :*** TransparentIRC " TRANSIRC_VERSION " (use /quote transirc for more information)");
void userclient_close_server(struct ServerSocket *server, int keep_clients) {
struct UserClient *client, *next_client;
for(client = userclients; client; client = next_client) {
+ next_client = client->next;
if(client->server == server) {
if(keep_clients)
client->server = NULL;
}
}
+static void userclient_recv(struct UserClient *client, char *line) {
+ iohandler_printf(client->iofd, "reply: %s", line);
+}
+
static void userclient_callback(struct IOEvent *event) {
+ struct UserClient *client = event->iofd->data;
switch(event->type) {
case IOEVENT_RECV:
- char *line = event->data.recv_str;
- iohandler_printf(event->iofd, "reply: %s", line);
+ userclient_recv(client, event->data.recv_str);
break;
case IOEVENT_CLOSED:
- userclient_close(event->iofd);
+ userclient_close(client);
+ break;
+ default:
break;
}
}
#include "../config.h"
#define TRANSIRC_VERSION "0.1"
+#define VERSION_PATCHLEVEL 0
#define IO_READ_BUFLEN 1024
#define IO_MAX_TIMEOUT 10
#define LINELEN 512
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <malloc.h>
+#else
+#include <features.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/wait.h>
+#include <errno.h>
+#endif
+#include <unistd.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+
+#if __GNUC__
+#define PRINTF_LIKE(M,N) __attribute__((format (printf, M, N)))
+#else
+#define PRINTF_LIKE(M,N)
+#endif
+
+#if __GNUC__ >= 2
+#define UNUSED_ARG(ARG) ARG __attribute__((unused))
+#elif defined(S_SPLINT_S)
+#define UNUSED_ARG(ARG) /*@unused@*/ ARG
+#define const /*@observer@*/ /*@temp@*/
+#else
+#define UNUSED_ARG(ARG) ARG
+#endif
+
+#define STRINGIFY_(x) #x
+#define STRINGIFY(x) STRINGIFY_(x)
+
+#if defined(__GNUC__)
+#if defined(__GNUC_PATCHLEVEL__)
+#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__)
+#else
+#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__)
+#endif
+#elif defined (__IMAGECRAFT__)
+#define COMPILER "ICCAVR"
+#else
+#define COMPILER "Unknown"
+#endif
+
#define timeval_is_bigger(x,y) ((x->tv_sec > y->tv_sec) || (x->tv_sec == y->tv_sec && x->tv_usec > y->tv_usec))
#define timeval_is_smaler(x,y) ((x->tv_sec < y->tv_sec) || (x->tv_sec == y->tv_sec && x->tv_usec < y->tv_usec))
--- /dev/null
+/* tools.c - TransparentIRC 0.1
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "tools.h"
+
+int stricmp(const char *s1, const char *s2) {
+ if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
+ if (s2 == NULL) return *s1;
+ char c1, c2;
+ while ((c1 = tolower (*s1)) == (c2 = tolower (*s2))) {
+ if (*s1 == '\0') break;
+ ++s1; ++s2;
+ }
+ return c1 - c2;
+}
+
+int stricmplen(const char *s1, const char *s2, int len) {
+ if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
+ if (s2 == NULL) return *s1;
+ char c1, c2;
+ int i = 0;
+ while ((c1 = tolower (*s1)) == (c2 = tolower (*s2))) {
+ i++;
+ if (*s1 == '\0') break;
+ ++s1; ++s2;
+ if(i == len) break;
+ }
+ return c1 - c2;
+}
\ No newline at end of file
--- /dev/null
+/* tools.h - TransparentIRC 0.1
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _tools_h
+#define _tools_h
+#include "overall.h"
+
+int stricmp(const char *s1, const char *s2);
+int stricmplen(const char *s1, const char *s2, int len);
+
+#endif
--- /dev/null
+/* version.h - TransparentIRC 0.1
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _version_h
+#define _version_h
+#include "overall.h"
+
+extern const char *compilation;
+extern const char *creation;
+extern const char *revision;
+extern const char *codelines;
+extern const int patchlevel;
+
+const char *get_compilation();
+const char *get_creation();
+const char *get_revision();
+const char *get_codelines();
+const int get_patchlevel();
+#endif
--- /dev/null
+#! /bin/sh
+echo "Extracting version.c ..."
+
+if test -r version.c
+then
+ compilation=`sed -n 's/^const char \*compilation = \"\(.*\)\";/\1/p' < version.c`
+ if test ! "$compilation" ; then compilation=0; fi
+else
+ compilation=0
+fi
+
+compilation=`expr $compilation + 1`
+
+creation=`date | \
+awk '{if (NF == 6) \
+ { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \
+else \
+ { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'`
+
+codelines=`find . -type f -regex '\./.*\.h' -or -regex '\./.*\.c' |xargs cat|wc -l`
+
+svn_revision=`svn info | grep Revision | grep -o -E '[0-9]+'`
+git_commitcount=0
+if test "x$svn_revision" = "x" ; then
+ svn_revision=`git log -n 1 --pretty="format:%h"`
+ if test "x$svn_revision" = "x" ; then
+ svn_revision="0"
+ else
+ git_commitcount=`git log --pretty=oneline --no-merges --first-parent | wc -l | sed "s/[ \t]//g"`
+ svn_revision="git-$git_commitcount-$svn_revision"
+ fi
+else
+ svn_revision="svn-$svn_revision"
+fi
+
+
+/bin/cat > version.c <<!SUB!THIS!
+/* version.c - TransparentIRC 0.1
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+//Auto generated file!
+
+#include "version.h"
+
+const char *compilation = "$compilation";
+const char *creation = "$creation";
+const char *revision = "$svn_revision";
+const char *codelines = "$codelines";
+
+const int patchlevel = ($git_commitcount ? ($git_commitcount - VERSION_PATCHLEVEL) : 0);
+
+const char *get_compilation() {
+ return compilation;
+}
+
+const char *get_creation() {
+ return creation;
+}
+
+const char *get_revision() {
+ return revision;
+}
+
+const char *get_codelines() {
+ return codelines;
+}
+
+const int get_patchlevel() {
+ return patchlevel;
+}
+
+!SUB!THIS!
+