emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC] syslog interface


From: Masatake YAMATO
Subject: [RFC] syslog interface
Date: Thu, 27 May 2010 14:18:47 +0900 (JST)

Hi,

 -server option added to newer emacs is very interesting.
But to write a rael server with emacs, there may be some missing
functions in emacs.

 syslog interface is one of such function. As a system administrator,
I'd like to track the event on the emacs server on which the service written 
in elisp is running via /var/log/messages.

The first question is how do you think adding syslog interface to emacs?

If it is O.k. The second question is about its implemention.  I've
found that the protocol used in syslog is still under draft stage. So
if emacs has syslog interface and the protocol is changed, we have to
modify the syslog interface code. It is not good for the maintainers.


Will Glozer wrote syslog.el(http://glozer.net/code/syslog.el).
It has both syslog daemon side code and syslog client side code.
Here my interest is the client site code. As the file name shown
it is whole written in elisp. 

I've tried Will Glozer syslog.el. The original code only supported
inet4 socket only. I've modified it to support unix socket; and 
tried to log some message. But broken message was recorded on
/var/log/messages because the syslog protcol used in syslog.el
and the protcol which syslogd was expected were not matched.
(I used rsyslog as syslogd implemention.)

At first, I should try to improve the syslog.el and take
effort it to merge emacs. But after learning the current status
of syslog protocol definition, I've changed my mind.

My idea is using syslog implemention in libc; 
it handles the protocol, and we can expect it is maintained well. If
the protocol is changed the libc maintainer will update the function.
As the result we can use/maintain syslog interfae from elisp without 
worrying about the protocol changing.

Here is sample implemention. It comes from two parts: syslog.el and a patch
for emacs. 

How to prepare

    - Apply the patch and rebuild emacs binary.
    - eval syslog.el.
    - eval (syslog 'daemon 'alert "Hello world")
    - see the tail of /var/log/messages

Regards,
Masatake YAMATO


;;; syslog.el --- syslog interface for GNU emacs

;; Copyright (C) 2010
;; Free Software Foundation, Inc.

;; Author: Masatake YAMATO <address@hidden>
;; Keywords: processes

;; This file is NOT YET part of GNU Emacs.

;; GNU Emacs 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.

;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; ...

;; TAKEN FROM sys/syslog.h of GNU Libc.
(defconst syslog-option-table
  '((pid    . #x01)
    (cons   . #x02)
    (odelay . #x04)
    (ndelay . #x08)
    (nowait . #x10)
    (perror . #x20)))

(defconst syslog-facilities-table
  (mapcar 
   (lambda (elt)
     (cons (car elt) (ash (cdr elt) 3)))
   '((kern     . 0)
     (user     . 1)
     (mail     . 2)
     (daemon   . 3)
     (auth     . 4)
     (syslog   . 5)
     (lpr      . 6)
     (news     . 7)
     (uucp     . 8)
     (cron     . 9)
     (authpriv . 10)
     (ftp      . 11)
     (local0   . 16)
     (local1   . 17)
     (local2   . 18)
     (local3   . 19)
     (local4   . 20)
     (local5   . 21)
     (local6   . 22)
     (local7   . 23))))

(defconst syslog-levels-table
  '((emerg   . 0)
    (alert   . 1)
    (crit    . 2)
    (err     . 3)
    (warning . 4)
    (notice  . 5)
    (info    . 6)
    (debug   . 7)))

(defun openlog (ident option facility)
  (let ((option (if (listp option)
                    (apply #'logior
                           (mapcar
                            (lambda (elt)
                              (cond
                               ((symbolp elt)
                                (or (cdr (assq elt syslog-option-table))
                                    (error "unknown element in OPTION: %S" 
elt)))
                               ((integerp elt) 
                                elt)
                               (t
                                (error 
                                 "element of OPTION must be a symbol enumerated 
in `syslog-facilities-table' or an integer: %S" 
                                 elt))))
                            option))
                  option))
        (facility (if (symbolp facility)
                      (cdr (assq facility syslog-facilities-table))
                    facility)))
    (when (fboundp 'openlog-internal)
      (openlog-internal ident option facility))))

(defun syslog (facility level fmt &rest args)
  (let ((priority (logior 
                   (cond
                    ((symbolp facility)
                     (or (cdr (assq facility syslog-facilities-table))
                         (error
                          "facility must be a symbol enumerated in 
`syslog-facilities-table' or an integer: %S"
                          facility)))
                    ((integerp facility) 
                     facility)
                    (t
                     (error
                      "facility must be a symbol enumerated in 
`syslog-facilities-table' or an integer: %S"
                      facility)))
                   (cond
                    ((symbolp level)
                     (or (cdr (assq level syslog-levels-table))
                         (error
                          "level must be a symbol enumerated in 
`syslog-levels-table' or an integer: %S"
                          level)))
                    ((integerp level)
                     level)
                    (t
                     (error
                      "level must be a symbol enumerated in 
`syslog-levels-table' or an integer: %S"
                      level)))
                   ))
        (msg (apply #'format fmt args)))
    (when (fboundp 'syslog-internal)
      (syslog-internal priority msg))))

(defun closelog ()
  (when (fboundp 'closelog-internal)
    (closelog-internal)))

(provide 'syslog)
;;; syslog.el ends here




=== modified file 'configure.in'
*** configure.in        2010-05-21 16:31:45 +0000
--- configure.in        2010-05-26 00:24:43 +0000
***************
*** 3030,3035 ****
--- 3030,3037 ----
       declarations.  Define as empty for no equivalent.])
  fi
  
+ AC_CHECK_HEADERS(sys/syslog.h)
+ 
  dnl Fixme: AC_SYS_POSIX_TERMIOS should probably be used, but it's not clear
  dnl how the tty code is related to POSIX and/or other versions of termios.
  dnl The following looks like a useful start.

=== modified file 'src/emacs.c'
*** src/emacs.c 2010-05-15 21:16:20 +0000
--- src/emacs.c 2010-05-26 00:28:17 +0000
***************
*** 2476,2481 ****
--- 2476,2542 ----
    return Qt;
  }
  
+ #ifdef HAVE_SYS_SYSLOG_H
+ #include <syslog.h>
+ 
+ extern Lisp_Object Qundefined;
+ 
+ DEFUN ("openlog-internal", Fopenlog_internal, Sopenlog_internal, 3, 3, 0,
+        doc: /* See openlog(3). */)
+      (ident,
+       option,
+       facility)
+      Lisp_Object ident;
+      Lisp_Object option;
+      Lisp_Object facility;
q+ {
+   unsigned char *cident;
+   int coption;
+   int cfacility;
+ 
+ 
+   CHECK_STRING(ident);
+   CHECK_NUMBER(option);
+   CHECK_NUMBER(facility);
+ 
+   cident    = SDATA(ident);
+   coption   = XINT(option);
+   cfacility = XINT(cfacility);
+   
+   openlog(cident, coption, cfacility);
+   return Qundefined;
+ }
+ 
+ DEFUN ("syslog-internal", Fsyslog_internal, Ssyslog_internal, 2, 2, 0, 
+        doc: /* See syslog(3). */)
+      (priority,
+       log)
+        Lisp_Object priority;
+        Lisp_Object log;
+ {
+   int cpriority;
+   unsigned char *clog;
+ 
+ 
+   CHECK_NUMBER(priority);
+   CHECK_STRING(log);
+ 
+   cpriority = XINT(priority);
+   clog      = SDATA (log);
+ 
+   syslog(cpriority, "%s", clog);
+   return Qundefined;
+ }
+        
+ DEFUN ("closelog-internal", Fcloselog_internal, Scloselog_internal, 0, 0, 0,
+        doc: /* See closelog(3). */)
+      ()
+ {
+   closelog();
+   return Qundefined;
+ }
+ #endif
+ 
  void
  syms_of_emacs ()
  {
***************
*** 2493,2498 ****
--- 2554,2565 ----
    defsubr (&Sdaemonp);
    defsubr (&Sdaemon_initialized);
  
+ #ifdef HAVE_SYS_SYSLOG_H
+   defsubr (&Sopenlog_internal);
+   defsubr (&Ssyslog_internal);
+   defsubr (&Scloselog_internal);
+ #endif
+ 
    DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
               doc: /* Args passed by shell to Emacs, as a list of strings.
  Many arguments are deleted from the list as they are processed.  */);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]