Home Download News FAQ / Knowledge Base Screenshots Documentation Support Site map
philosophical imaginary
Table of Contents

Featured Projects

The Uncensored Communication Group contributes to other Opensource Projects too. Feel free to provide feedback via Uncensored! BBS

libical

LibIcal is maintained by the Citadel Staff. Its Page-Content is maintained in the Citadel.org libical page.

dokuwiki NROFF Syntax Plugin

As the Citadel Project uses the Dokuwiki, it has use in extending its functionality. To unify our Documentation needs, we've created a Dokuwiki plugin to render Manpages, the NROFF plugin.

use it like that:

curl 'http://www.citadel.org/doku.php/documentation:cmdman:webserver?do=export_nroff&sec tion=1' > webserver.1

note that 'section' controls the man-section which it should live in.

Get the plugin here: nroff.tgz

Maybe you'd like to create a template with a dummy manpage for your users.

Strace alike with Backtrace

We all like & use tools like the grand master flash valgrind or GDB but sometimes all of them just don't cut it, and you have to craft your own tool.

Now since citadel started using LibEv the possible number of simultaneusly open file descriptors grew enormously, it is like sitting down backwards onto a circular saw, and afterwards find out which tooth bite you.

You may already have heard about execinfo which enables you to fetch stack traces from within your running program to aid online debugging; certain library errormessages from citadel and webcit are able to show where they are called from this way.

So we now need to find out, whats going on with filedescriptors, who opens and closes them. strace is a nice tool for this job, however it doesn't utilize execinfo, so you only see FDs opening, closing, reading & writing, but no info from where within your program this was done.

This tiny .so can be preloaded via

LD_PRELOAD=libbacktrace.so

and will output many open / close / connect calls into a logfile so you can see what was going on. Its not all complete, but it already did its job and found my bug - so I'd like to share it with you:

/*
 * gcc  -Wall -nostartfiles -fpic -shared -olibbacktrace.so  backtrace_open.c 
This is free and unencumbered software released into the public domain.
 
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
 
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
 
For more information, please refer to <http://unlicense.org/>
 
 */
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
 
#include <dlfcn.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/socket.h>
 
#include <netinet/in.h>
#include <arpa/inet.h>
 
#include <errno.h>
#include <time.h>
 
#include <execinfo.h>
 
 
/* XXX: do parallel support for open AND open64 by #undef open etc .. */
 
 
#define RESOLVE(x)	if (!o_##x && !(o_##x = dlsym(RTLD_NEXT, #x))) { fprintf(stderr, #x"() not found!\n"); exit(-1); }
 
#define min(x,y) ( (x)<(y)?(x):(y) )
#define max(x,y) ( (x)>(y)?(x):(y) )
 
#define N_FRAMES 50
 
/* XXX: need to handle this differently .. linked list? */
#define HIGHEST_FD 256
#define FEAT_RANGE_SUPPORT 1
 
static int (*o_open64)(const char *, int, ...);
static int (*o_close)(int);
 
static FILE *(*o_fopen64)(const char *, const char *);
static FILE *(*o_fdopen)(int fd, const char *mode);
static int (*o_fclose)(FILE *);
static int (*o_socket)(int domain, int type, int protocol);
static int (*o_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
static int (*o_creat)(const char *pathname, mode_t mode);
static int (*o_dup)(int oldfd);
static int (*o_dup2)(int oldfd, int newfd);
static int (*o_dup3)(int oldfd, int newfd, int flags);
 
FILE *myfd = NULL;
 
 
void _init(void)
{
	RESOLVE(fopen64);
	RESOLVE(open64);
	RESOLVE(fdopen);
	RESOLVE(socket);
	RESOLVE(connect);
	RESOLVE(fopen64);
	RESOLVE(close);
	RESOLVE(fclose);
	RESOLVE(creat);
	RESOLVE(dup);
	RESOLVE(dup2);
	RESOLVE(dup3);
 
	/* CRASH! if you load us uninitialized, your process deserves to die! */
	myfd = o_fopen64(getenv("DEBUG_FILENAME"), "a+");
 
	fprintf(myfd, "%d: my filedescriptor.\n", fileno(myfd));
	fprintf(myfd, "%d: my pid\n", getpid());
}
 
 
void oneline_backtrace(const char* CallName, const char *str1, long nFD)
{
 
	static const long sizeofstr =
		N_FRAMES *3 + // 0x,
		sizeof(void*) * N_FRAMES * 4 + // hex number
		N_FRAMES * 64 + // function string version
		256;
	void *stack_frames[N_FRAMES];
	char addresslist[sizeofstr]; 
	size_t size, i;
	long offset = 0;
	char **strings;
 
	addresslist [0] = '\0';
//	fprintf(myfd, "\n%ld: [", nFD);
 
//	fprintf(myfd, "\n%s: [", CallName);
	offset = sprintf(addresslist, "\n%ld: [%s][", nFD, CallName);
 
	size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
///	fprintf(myfd, "\n%ld: [", size);
	strings = backtrace_symbols(stack_frames, size);
	if (size > 0)
	{
		if (N_FRAMES < size)
			size = N_FRAMES;
 
		// skip first two frames, its just us.
		for (i = 2; i < size; i++) {
//			fprintf(myfd, "\t%ld - %p\n", i, strings[i]);
			if ((strings != NULL) && (strings[i] != NULL))
			{
//				fprintf(myfd, "\t%s\n", strings[i]);
				offset += snprintf(addresslist + offset, sizeofstr - offset, "\t%s\n", strings[i]);
			}
			else
			{
//				fprintf(myfd, "%p;", stack_frames[i]);
				offset += snprintf(addresslist + offset, sizeofstr - offset, "%p;", stack_frames[i]);
			}
			if (sizeofstr < offset + 64)
				break;
		}
	}
	offset += snprintf(addresslist + offset, sizeofstr - offset, "]\n\t%s", 
			   str1);
 
	fwrite(addresslist, 1, offset, myfd);
 
}
 
 
int open64(const char *pathname, int flag, ...)
{
	int ret;
 
	ret = o_open64(pathname, flag);
	oneline_backtrace (__FUNCTION__, pathname, ret);
 
	return ret;
}
 
int creat(const char *pathname, mode_t mode)
{
	int ret;
 
	ret = o_creat(pathname, mode);
	oneline_backtrace (__FUNCTION__, pathname, ret);
 
	return ret;
}
 
int dup(int oldfd)
{
	int ret;
	char buf[32];
 
	ret = o_dup(oldfd);
	sprintf(buf, "%d", oldfd);
	oneline_backtrace (__FUNCTION__, buf, ret);
 
	return ret;
}
 
int dup2(int oldfd, int newfd)
{
	int ret;
	char buf[64];
 
	ret = o_dup2(oldfd, newfd);
	sprintf(buf, "Old: %d, new: %d, ret: %d", 
		oldfd, newfd, ret);
	oneline_backtrace (__FUNCTION__, buf, ret);
 
	return ret;
}
 
int dup3(int oldfd, int newfd, int flags)
{
	int ret;
	char buf[64];
 
	ret = o_dup3(oldfd, newfd, flags);
	sprintf(buf, "Old: %d, new: %d, ret: %d", 
		oldfd, newfd, ret);
	oneline_backtrace (__FUNCTION__, buf, ret);
 
	return ret;
}
 
FILE *fopen64(const char *pathname, const char *mode)
{
	FILE *Ret;
	Ret = o_fopen64(pathname, mode);
 
	oneline_backtrace (__FUNCTION__, pathname, fileno(Ret));
 
	return Ret;
}
 
 
FILE *fdopen(int fd, const char *mode)
{
	FILE *Ret;
	Ret = o_fdopen(fd, mode);
 
	oneline_backtrace (__FUNCTION__, mode, fd);
 
	return Ret;
}
 
int socket(int domain, int type, int protocol)
{
	int ret;
	char buf[128];
 
	ret = o_socket(domain, type, protocol);
	snprintf(buf, sizeof(buf), "t: %d p:%d %s", 
		 type, protocol, strerror(errno));
 
	oneline_backtrace (__FUNCTION__, buf, ret);
	return ret;
}
 
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	char what[64];
	char netbuf[64];
	int ret;
 
	if (addrlen == sizeof(struct sockaddr_in6))
	{
		inet_ntop(AF_INET6,
			  addr,
			  netbuf,
			  sizeof(netbuf));
 
		sprintf(what, "ipv6[%s]", netbuf);
	}
	else if (addrlen == sizeof(struct sockaddr_in))
	{
 
		inet_ntop(AF_INET,
			  addr,
			  netbuf,
			  sizeof(netbuf));
		sprintf(what, "ipv4[%s]", netbuf);
	}
	else
	{
		sprintf(what, " WTF? neither ipv4 nor 6? ");
 
	}
 
	ret = o_connect(sockfd, addr, addrlen);
 
	oneline_backtrace (__FUNCTION__, what, sockfd);
 
	return ret;
}
 
 
int close(int fd)
{
	oneline_backtrace (__FUNCTION__, "", fd);
 
	return o_close(fd);
}
 
int fclose(FILE *stream)
{
	int fd;
	int ret;
 
	fd = fileno(stream);
	ret = o_fclose(stream);
 
	oneline_backtrace (__FUNCTION__, strerror(errno), fd);
 
	return ret;
}
Copyright © 1987-2014 Uncensored Communications Group. All rights reserved.     Login (site admin)