Index: uspace/lib/posix/signal.c
===================================================================
--- uspace/lib/posix/signal.c	(revision 4f86fa331ccfd486b85c89e3c6fcf2950e906de7)
+++ uspace/lib/posix/signal.c	(revision d3ce33fa059aa0515a8098069a1b5db2a251912f)
@@ -37,33 +37,323 @@
 #include "signal.h"
 #include "internal/common.h"
+#include "limits.h"
+#include "stdlib.h"
+#include "string.h"
+#include "errno.h"
+
+#include "libc/fibril_synch.h"
+#include "libc/task.h"
+
+/* Used to serialize signal handling. */
+static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
+
+static posix_sigset_t _signal_mask = 0;
+
+#define DEFAULT_HANDLER { .sa_handler = SIG_DFL, \
+    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
+
+static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER
+};
+
+void __posix_default_signal_handler(int signo)
+{
+	switch (signo) {
+	case SIGABRT:
+		abort();
+	case SIGQUIT:
+		fprintf(stderr, "Quit signal raised. Exiting.");
+		exit(EXIT_FAILURE);
+	case SIGINT:
+		fprintf(stderr, "Interrupt signal caught. Exiting.");
+		exit(EXIT_FAILURE);
+	case SIGTERM:
+		fprintf(stderr, "Termination signal caught. Exiting.");
+		exit(EXIT_FAILURE);
+	case SIGSTOP:
+		fprintf(stderr, "Stop signal caught, but unsupported. Ignoring.");
+		break;
+	case SIGKILL:
+		/* This will only occur when raise or similar is called. */
+		/* Commit suicide. */
+		task_kill(task_get_id());
+		
+		/* Should not be reached. */
+		abort();
+	case SIGFPE:
+	case SIGBUS:
+	case SIGILL:
+	case SIGSEGV:
+		posix_psignal(signo, "Hardware exception raised by user code");
+		abort();
+	case SIGSYS:
+	case SIGXCPU:
+	case SIGXFSZ:
+	case SIGTRAP:
+	case SIGHUP:
+	case SIGPIPE:
+	case SIGPOLL:
+	case SIGURG:
+	case SIGTSTP:
+	case SIGTTIN:
+	case SIGTTOU:
+		posix_psignal(signo, "Unsupported signal caught");
+		abort();
+	case SIGCHLD:
+	case SIGUSR1:
+	case SIGUSR2:
+	case SIGALRM:
+	case SIGVTALRM:
+	case SIGPROF:
+	case SIGCONT:
+		/* ignored */
+		break;
+	}
+}
+
+void __posix_hold_signal_handler(int signo)
+{
+	/* Nothing */
+}
+
+void __posix_ignore_signal_handler(int signo)
+{
+	/* Nothing */
+}
+
+
+int posix_sigemptyset(posix_sigset_t *set)
+{
+	assert(set != NULL);
+
+	*set = 0;
+	return 0;
+}
+
+int posix_sigfillset(posix_sigset_t *set)
+{
+	assert(set != NULL);
+
+	*set = UINT32_MAX;
+	return 0;
+}
+
+int posix_sigaddset(posix_sigset_t *set, int signo)
+{
+	assert(set != NULL);
+
+	*set |= (1 << signo);
+	return 0;
+}
+
+int posix_sigdelset(posix_sigset_t *set, int signo)
+{
+	assert(set != NULL);
+
+	*set &= ~(1 << signo);
+	return 0;
+}
+
+int posix_sigismember(const posix_sigset_t *set, int signo)
+{
+	assert(set != NULL);
+	
+	return (*set & (1 << signo)) != 0;
+}
+
+static void _sigaction_unsafe(int sig, const struct posix_sigaction *restrict act,
+    struct posix_sigaction *restrict oact)
+{
+	if (oact != NULL) {
+		memcpy(oact, &_signal_actions[sig],
+		    sizeof(struct posix_sigaction));
+	}
+
+	if (act != NULL) {
+		memcpy(&_signal_actions[sig], act,
+		    sizeof(struct posix_sigaction));
+	}
+}
+
+int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
+    struct posix_sigaction *restrict oact)
+{
+	if (sig > _TOP_SIGNAL || (act != NULL &&
+	    (sig == SIGKILL || sig == SIGSTOP))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (sig > _TOP_CATCHABLE_SIGNAL) {
+		posix_psignal(sig,
+		    "WARNING: registering handler for a partially"
+		    " or fully unsupported signal. This handler may only be"
+		    " invoked by the raise() function, which may not be what"
+		    " the application developer intended.\nSignal name");
+	}
+
+	fibril_mutex_lock(&_signal_mutex);
+	_sigaction_unsafe(sig, act, oact);
+	fibril_mutex_unlock(&_signal_mutex);
+
+	return 0;
+}
 
 void (*posix_signal(int sig, void (*func)(int)))(int)
 {
-	// TODO
-	not_implemented();
+	struct posix_sigaction new = {
+		.sa_handler = func,
+		.sa_mask = 0,
+		.sa_flags = 0,
+		.sa_sigaction = NULL
+	};
+	struct posix_sigaction old;
+	if (posix_sigaction(sig, func == NULL ? NULL : &new, &old) == 0) {
+		return old.sa_handler;
+	} else {
+		return SIG_ERR;
+	}
+}
+
+static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
+{
+	assert(signo >= 0 && signo <= _TOP_SIGNAL);
+	assert(siginfo != NULL);
+
+	fibril_mutex_lock(&_signal_mutex);
+
+	struct posix_sigaction action = _signal_actions[signo];
+
+	if (posix_sigismember(&_signal_mask, signo) ||
+	    action.sa_handler == SIG_HOLD) {
+		// TODO: queue signal
+		fibril_mutex_unlock(&_signal_mutex);
+		return -1;
+	}
+
+	/* Modifying signal mask is unnecessary,
+	 * signal handling is serialized.
+	 */
+
+	if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
+		_signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
+	};
+
+	if (action.sa_flags & SA_SIGINFO) {
+		assert(action.sa_sigaction != NULL);
+		action.sa_sigaction(signo, siginfo, NULL);
+	} else {
+		assert(action.sa_handler != NULL);
+		action.sa_handler(signo);
+	}
+
+	fibril_mutex_unlock(&_signal_mutex);
+
+	return 0;
 }
 
 int posix_raise(int sig)
 {
-	// TODO
-	not_implemented();
-}
-
-int posix_kill(posix_pid_t pid, int sig)
-{
-	// TODO
-	not_implemented();
-}
-
-int posix_sigaddset(posix_sigset_t *set, int signo)
-{
-	// TODO
-	not_implemented();
-}
-
-int posix_sigemptyset(posix_sigset_t *set)
-{
-	// TODO
-	not_implemented();
+	if (sig >= 0 && sig <= _TOP_SIGNAL) {
+		posix_siginfo_t siginfo = {
+			.si_signo = sig,
+			.si_code = SI_USER
+		};
+		return _raise_sigaction(sig, &siginfo);
+	} else {
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+int posix_kill(posix_pid_t pid, int signo)
+{
+	if (pid < 1) {
+		// TODO
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	if (pid == task_get_id()) {
+		return posix_raise(signo);
+	}
+
+	if (pid > _TOP_SIGNAL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	switch (signo) {
+	case SIGKILL:
+		task_kill(pid);
+		break;
+	default:
+		/* Nothing else supported yet. */
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	return 0;
+}
+
+int posix_killpg(posix_pid_t pid, int sig)
+{
+	assert(pid > 1);
+	return posix_kill(-pid, sig);
+}
+
+void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
+{
+	assert(pinfo != NULL);
+	posix_psignal(pinfo->si_signo, message);
+	// TODO: print si_code
+}
+
+void posix_psignal(int signum, const char *message)
+{
+	char *sigmsg = posix_strsignal(signum);
+	if (message == NULL || *message == '\0') {
+		fprintf(stderr, "%s\n", sigmsg);
+	} else {
+		fprintf(stderr, "%s: %s\n", message, sigmsg);
+	}
+}
+
+int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
+    posix_sigset_t *restrict oset)
+{
+	fibril_mutex_lock(&_signal_mutex);
+
+	if (oset != NULL) {
+		*oset = _signal_mask;
+	}
+	if (set != NULL) {
+		switch (how) {
+		case SIG_BLOCK:
+			_signal_mask |= *set;
+			break;
+		case SIG_UNBLOCK:
+			_signal_mask &= ~*set;
+			break;
+		case SIG_SETMASK:
+			_signal_mask = *set;
+			break;
+		default:
+			fibril_mutex_unlock(&_signal_mutex);
+			return EINVAL;
+		}
+	}
+
+	// TODO: queued signal handling
+
+	fibril_mutex_unlock(&_signal_mutex);
+
+	return 0;
 }
 
@@ -71,6 +361,10 @@
     posix_sigset_t *restrict oset)
 {
-	// TODO
-	not_implemented();
+	int result = posix_thread_sigmask(how, set, oset);
+	if (result != 0) {
+		errno = result;
+		return -1;
+	}
+	return 0;
 }
 
Index: uspace/lib/posix/signal.h
===================================================================
--- uspace/lib/posix/signal.h	(revision 4f86fa331ccfd486b85c89e3c6fcf2950e906de7)
+++ uspace/lib/posix/signal.h	(revision d3ce33fa059aa0515a8098069a1b5db2a251912f)
@@ -39,24 +39,19 @@
 #include "sys/types.h"
 
-/* HelenOS doesn't have signals, so calls to functions of this header
- * are just replaced with their respective failure return value.
- *
- * Other macros and constants are here just to satisfy the symbol resolver
- * and have no practical value whatsoever, until HelenOS implements some
- * equivalent of signals. Maybe something neat based on IPC will be devised
- * in the future?
- */
+extern void __posix_default_signal_handler(int signo);
+extern void __posix_hold_signal_handler(int signo);
+extern void __posix_ignore_signal_handler(int signo);
 
 #undef SIG_DFL
-#define SIG_DFL ((void (*)(int)) 0)
+#define SIG_DFL ((void (*)(int)) __posix_default_signal_handler)
 #undef SIG_ERR
-#define SIG_ERR ((void (*)(int)) 0)
+#define SIG_ERR ((void (*)(int)) NULL)
 #undef SIG_HOLD
-#define SIG_HOLD ((void (*)(int)) 0)
+#define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler)
 #undef SIG_IGN
-#define SIG_IGN ((void (*)(int)) 0)
+#define SIG_IGN ((void (*)(int)) __posix_ignore_signal_handler)
 
 typedef int posix_sig_atomic_t;
-typedef int posix_sigset_t;
+typedef uint32_t posix_sigset_t;
 typedef struct posix_mcontext {
 	// FIXME: should not be empty to avoid compiler warnings (-pedantic)
@@ -116,85 +111,170 @@
 /* Values of posix_sigevent::sigev_notify */
 #undef SIGEV_NONE
+#undef SIGEV_SIGNAL
+#undef SIGEV_THREAD
 #define SIGEV_NONE 0
-#undef SIGEV_SIGNAL
 #define SIGEV_SIGNAL 0
-#undef SIGEV_THREAD
 #define SIGEV_THREAD 0
 
 #undef SIGRT_MIN
+#undef SIGRT_MAX
 #define SIGRT_MIN 0
-#undef SIGRT_MAX
 #define SIGRT_MAX 0
 
 #undef SIG_BLOCK
+#undef SIG_UNBLOCK
+#undef SIG_SETMASK
 #define SIG_BLOCK 0
-#undef SIG_UNBLOCK
-#define SIG_UNBLOCK 0
-#undef SIG_SETMASK
-#define SIG_SETMASK 0
+#define SIG_UNBLOCK 1
+#define SIG_SETMASK 2
 
 #undef SA_NOCLDSTOP
-#define SA_NOCLDSTOP 0
 #undef SA_ONSTACK
-#define SA_ONSTACK 0
 #undef SA_RESETHAND
-#define SA_RESETHAND 0
 #undef SA_RESTART
-#define SA_RESTART 0
 #undef SA_SIGINFO
-#define SA_SIGINFO 0
 #undef SA_NOCLDWAIT
-#define SA_NOCLDWAIT 0
 #undef SA_NODEFER
-#define SA_NODEFER 0
+#define SA_NOCLDSTOP (1 << 0)
+#define SA_ONSTACK (1 << 1)
+#define SA_RESETHAND (1 << 2)
+#define SA_RESTART (1 << 3)
+#define SA_SIGINFO (1 << 4)
+#define SA_NOCLDWAIT (1 << 5)
+#define SA_NODEFER (1 << 6)
 
 #undef SS_ONSTACK
+#undef SS_DISABLE
 #define SS_ONSTACK 0
-#undef SS_DISABLE
 #define SS_DISABLE 0
 
 #undef MINSIGSTKSZ
+#undef SIGSTKSZ
 #define MINSIGSTKSZ 0
-#undef SIGSTKSZ
 #define SIGSTKSZ 0
 
 /* full POSIX set */
 enum {
+	/* Termination Signals */
 	SIGABRT,
+	SIGQUIT,
+	SIGINT,
+	SIGTERM,
+	
+	/* Child Signal */
+	SIGCHLD,
+	
+	/* User signals */
+	SIGUSR1,
+	SIGUSR2,
+
+	/* Timer */
 	SIGALRM,
+	SIGVTALRM,
+	SIGPROF, /* obsolete */
+
+	_TOP_CATCHABLE_SIGNAL = SIGPROF,
+
+	/* Process Scheduler Interaction - not supported */
+	SIGSTOP,
+	SIGCONT,
+
+	/* Process Termination - can't be caught */
+	SIGKILL,
+
+	_TOP_SENDABLE_SIGNAL = SIGKILL,
+
+	/* Hardware Exceptions - can't be caught or sent */
+	SIGFPE,
 	SIGBUS,
-	SIGCHLD,
-	SIGCONT,
-	SIGFPE,
+	SIGILL,
+	SIGSEGV,
+
+	/* Other Exceptions - not supported */
+	SIGSYS,
+	SIGXCPU,
+	SIGXFSZ,
+
+	/* Debugging - not supported */
+	SIGTRAP,
+
+	/* Communication Signals - not supported */
 	SIGHUP,
-	SIGILL,
-	SIGINT,
-	SIGKILL,
 	SIGPIPE,
-	SIGQUIT,
-	SIGSEGV,
-	SIGSTOP,
-	SIGTERM,
+	SIGPOLL, /* obsolete */
+	SIGURG,
+
+	/* Terminal Signals - not supported */
 	SIGTSTP,
 	SIGTTIN,
 	SIGTTOU,
-	SIGUSR1,
-	SIGUSR2,
-	SIGPOLL,
-	SIGPROF,
-	SIGSYS,
-	SIGTRAP,
-	SIGURG,
-	SIGVTALRM,
-	SIGXCPU,
-	SIGXFSZ
-};
+	
+	_TOP_SIGNAL = SIGTTOU
+};
+
+/* Values for sigaction field si_code. */
+
+enum {
+	SI_USER,
+	SI_QUEUE,
+	SI_TIMER,
+	SI_ASYNCIO,
+	SI_MESGQ,
+	ILL_ILLOPC,
+	ILL_ILLOPN,
+	ILL_ILLADR,
+	ILL_ILLTRP,
+	ILL_PRVOPC,
+	ILL_PRVREG,
+	ILL_COPROC,
+	ILL_BADSTK,
+	FPE_INTDIV,
+	FPE_INTOVF,
+	FPE_FLTDIV,
+	FPE_FLTOVF,
+	FPE_FLTUND,
+	FPE_FLTRES,
+	FPE_FLTINV,
+	FPE_FLTSUB,
+	SEGV_MAPERR,
+	SEGV_ACCERR,
+	BUS_ADRALN,
+	BUS_ADRERR,
+	BUS_OBJERR,
+	TRAP_BRKPT,
+	TRAP_TRACE,
+	CLD_EXITED,
+	CLD_KILLED,
+	CLD_DUMPED,
+	CLD_TRAPPED,
+	CLD_STOPPED,
+	CLD_CONTINUED,
+	POLL_IN,
+	POLL_OUT,
+	POLL_MSG,
+	POLL_ERR,
+	POLL_PRI,
+	POLL_HUP
+};
+
+extern int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
+    struct posix_sigaction *restrict oact);
 
 extern void (*posix_signal(int sig, void (*func)(int)))(int);
 extern int posix_raise(int sig);
 extern int posix_kill(posix_pid_t pid, int sig);
-
+extern int posix_killpg(posix_pid_t pid, int sig);
+
+extern void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message);
+extern void posix_psignal(int signum, const char *message);
+
+extern int posix_sigemptyset(posix_sigset_t *set);
+extern int posix_sigfillset(posix_sigset_t *set);
 extern int posix_sigaddset(posix_sigset_t *set, int signo);
-extern int posix_sigemptyset(posix_sigset_t *set);
+extern int posix_sigdelset(posix_sigset_t *set, int signo);
+extern int posix_sigismember(const posix_sigset_t *set, int signo);
+
+extern int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
+    posix_sigset_t *restrict oset);
 extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
     posix_sigset_t *restrict oset);
@@ -214,6 +294,16 @@
 	#define raise posix_raise
 	#define kill posix_kill
+	#define killpg posix_killpg
+
+	#define psiginfo posix_psiginfo
+	#define psignal posix_psignal
+
+	#define sigemptyset posix_sigemptyset
+	#define sigfillset posix_sigfillset
 	#define sigaddset posix_sigaddset
-	#define sigemptyset posix_sigemptyset
+	#define sigdelset posix_sigdelset
+	#define sigismember posix_sigismember
+
+	#define pthread_sigmask posix_thread_sigmask
 	#define sigprocmask posix_sigprocmask
 #endif
Index: uspace/lib/posix/string.c
===================================================================
--- uspace/lib/posix/string.c	(revision 4f86fa331ccfd486b85c89e3c6fcf2950e906de7)
+++ uspace/lib/posix/string.c	(revision d3ce33fa059aa0515a8098069a1b5db2a251912f)
@@ -43,4 +43,5 @@
 #include "limits.h"
 #include "stdlib.h"
+#include "signal.h"
 
 #include "libc/str_error.h"
@@ -570,4 +571,49 @@
 }
 
+/**
+ *
+ * @param signum
+ * @return
+ */
+char *posix_strsignal(int signum)
+{
+	static const char *const sigstrings[] = {
+		[SIGABRT] = "SIGABRT (Process abort signal)",
+		[SIGALRM] = "SIGALRM (Alarm clock)",
+		[SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
+		[SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
+		[SIGCONT] = "SIGCONT (Continue executing, if stopped)",
+		[SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
+		[SIGHUP] = "SIGHUP (Hangup)",
+		[SIGILL] = "SIGILL (Illegal instruction)",
+		[SIGINT] = "SIGINT (Terminal interrupt signal)",
+		[SIGKILL] = "SIGKILL (Kill process)",
+		[SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
+		[SIGQUIT] = "SIGQUIT (Terminal quit signal)",
+		[SIGSEGV] = "SIGSEGV (Invalid memory reference)",
+		[SIGSTOP] = "SIGSTOP (Stop executing)",
+		[SIGTERM] = "SIGTERM (Termination signal)",
+		[SIGTSTP] = "SIGTSTP (Terminal stop signal)",
+		[SIGTTIN] = "SIGTTIN (Background process attempting read)",
+		[SIGTTOU] = "SIGTTOU (Background process attempting write)",
+		[SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
+		[SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
+		[SIGPOLL] = "SIGPOLL (Pollable event)",
+		[SIGPROF] = "SIGPROF (Profiling timer expired)",
+		[SIGSYS] = "SIGSYS (Bad system call)",
+		[SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
+		[SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
+		[SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
+		[SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
+		[SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
+	};
+
+	if (signum <= _TOP_SIGNAL) {
+		return (char *) sigstrings[signum];
+	}
+
+	return (char *) "ERROR, Invalid signal number";
+}
+
 /** @}
  */
Index: uspace/lib/posix/string.h
===================================================================
--- uspace/lib/posix/string.h	(revision 4f86fa331ccfd486b85c89e3c6fcf2950e906de7)
+++ uspace/lib/posix/string.h	(revision d3ce33fa059aa0515a8098069a1b5db2a251912f)
@@ -103,4 +103,7 @@
 extern size_t posix_strnlen(const char *s, size_t n);
 
+/* Signal messages */
+extern char *posix_strsignal(int signum);
+
 /* Legacy declarations */
 #ifndef POSIX_STRINGS_H_
@@ -143,4 +146,6 @@
 	#define strnlen posix_strnlen
 
+	#define strsignal posix_strsignal
+
 	#define ffs posix_ffs
 	#define strcasecmp posix_strcasecmp
