(defun errno ()
  (ffi:c-inline () () :int "errno" :one-liner t))

(defun strerror (errno)
  (ffi:c-inline (errno)
		(:int)
		:cstring
		"
{
	char errbuf[256];

	(void)strerror_r(#0, errbuf, 255);
	@(return) = errbuf;
}" :one-liner nil))

(define-condition unix-error
    ()
  ((function :initarg :function
	     :initform nil
	     :type (or null string)
	     :reader unix-error-function)
   (errno :initarg :errno
	  :initform nil
	  :type (or null fixnum)
	  :reader unix-error-errno)
   (objects :initarg :objects
	    :initform '()
	    :type list
	    :reader unix-error-objects))
  (:report (lambda (condition stream)
	     (format stream "Unix error: ~A() - [~A]: \"~A\"~%On: ~S~%"
		     (unix-error-function condition)
		     (unix-error-errno condition)
		     (strerror (unix-error-errno condition))
		     (unix-error-objects condition)))))

(defun unix-error (function errno &optional (objects '()))
  (error (make-condition 'unix-error
			 :function function
			 :errno errno
			 :objects objects)))

(defun gai-strerror (errno)
  (ffi:c-inline (errno)
		(:int)
		:cstring
		"gai_strerror(#0)" :one-liner t))

(define-condition gai-error
    (unix-error)
  ()
  (:report (lambda (condition stream)
	     (format stream "Resolve error: ~A() - [~A]: \"~A\"~%On: ~S~%"
		     (unix-error-function condition)
		     (unix-error-errno condition)
		     (gai-strerror (unix-error-errno condition))
		     (unix-error-objects condition)))))

(defun gai-error (function errno &optional (objects '()))
  (error (make-condition 'gai-error
			 :function function
			 :errno errno
			 :objects objects)))
