identify.c: Stash a copy of the caller's description string.
[fwd] / fwd.h
diff --git a/fwd.h b/fwd.h
index 2da55a3..f075c53 100644 (file)
--- a/fwd.h
+++ b/fwd.h
@@ -62,6 +62,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/uio.h>
 #include <sys/wait.h>
 
@@ -87,6 +88,8 @@
 #include <mLib/fdflags.h>
 #include <mLib/fdpass.h>
 #include <mLib/ident.h>
+#include <mLib/macros.h>
+#include <mLib/mdup.h>
 #include <mLib/mdwopt.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
   extern char **environ;
 #endif
 
+/*----- Resource limit names ----------------------------------------------*/
+
+#if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
+#  define RLIMIT_NOFILE RLIMIT_OFILE
+#endif
+
+/*
+   ;;; The resource-limit name table is very boring to type and less fun to
+   ;;; maintain.  To make life less awful, put the names in this list and
+   ;;; evaluate the code to get Emacs to regenerate it.
+
+   (let ((limits '(as core cpu data fsize locks memlock msgqueue
+                  nice nofile nproc rss rtprio sigpending stack
+                  vmem)))
+     (save-excursion
+       (goto-char
+       (point-min))
+       (search-forward (concat "***" "BEGIN rlimitlist" "***"))
+       (beginning-of-line 2)
+       (delete-region (point)
+                     (progn
+                       (search-forward "***END***")
+                       (beginning-of-line)
+                       (point)))
+       (let ((avail (make-marker))
+            (list (make-marker)))
+        (set-marker avail (point))
+        (insert "#define RLIMITS(_)")
+        (set-marker list (point))
+        (dolist (limit (sort (copy-list limits) #'string<))
+          (let* ((name (symbol-name limit))
+                 (constant (concat "RLIMIT_" (upcase name)))
+                 (have (concat "HAVE_" constant "_P")))
+            (goto-char avail)
+            (insert-before-markers (format (concat "#ifdef %s\n"
+                                                   "#  define %s t\n"
+                                                   "#else\n"
+                                                   "#  define %s nil\n"
+                                                   "#endif\n")
+                                           constant have have))
+            (goto-char list)
+            (insert-before-markers
+             (format " \\\n  MAYBE_ITEM(_, %s, (%s, %s))"
+                     have name constant))))
+        (goto-char list)
+        (insert "\n"))))
+*/
+
+/***BEGIN rlimitlist***/
+#ifdef RLIMIT_AS
+#  define HAVE_RLIMIT_AS_P t
+#else
+#  define HAVE_RLIMIT_AS_P nil
+#endif
+#ifdef RLIMIT_CORE
+#  define HAVE_RLIMIT_CORE_P t
+#else
+#  define HAVE_RLIMIT_CORE_P nil
+#endif
+#ifdef RLIMIT_CPU
+#  define HAVE_RLIMIT_CPU_P t
+#else
+#  define HAVE_RLIMIT_CPU_P nil
+#endif
+#ifdef RLIMIT_DATA
+#  define HAVE_RLIMIT_DATA_P t
+#else
+#  define HAVE_RLIMIT_DATA_P nil
+#endif
+#ifdef RLIMIT_FSIZE
+#  define HAVE_RLIMIT_FSIZE_P t
+#else
+#  define HAVE_RLIMIT_FSIZE_P nil
+#endif
+#ifdef RLIMIT_LOCKS
+#  define HAVE_RLIMIT_LOCKS_P t
+#else
+#  define HAVE_RLIMIT_LOCKS_P nil
+#endif
+#ifdef RLIMIT_MEMLOCK
+#  define HAVE_RLIMIT_MEMLOCK_P t
+#else
+#  define HAVE_RLIMIT_MEMLOCK_P nil
+#endif
+#ifdef RLIMIT_MSGQUEUE
+#  define HAVE_RLIMIT_MSGQUEUE_P t
+#else
+#  define HAVE_RLIMIT_MSGQUEUE_P nil
+#endif
+#ifdef RLIMIT_NICE
+#  define HAVE_RLIMIT_NICE_P t
+#else
+#  define HAVE_RLIMIT_NICE_P nil
+#endif
+#ifdef RLIMIT_NOFILE
+#  define HAVE_RLIMIT_NOFILE_P t
+#else
+#  define HAVE_RLIMIT_NOFILE_P nil
+#endif
+#ifdef RLIMIT_NPROC
+#  define HAVE_RLIMIT_NPROC_P t
+#else
+#  define HAVE_RLIMIT_NPROC_P nil
+#endif
+#ifdef RLIMIT_RSS
+#  define HAVE_RLIMIT_RSS_P t
+#else
+#  define HAVE_RLIMIT_RSS_P nil
+#endif
+#ifdef RLIMIT_RTPRIO
+#  define HAVE_RLIMIT_RTPRIO_P t
+#else
+#  define HAVE_RLIMIT_RTPRIO_P nil
+#endif
+#ifdef RLIMIT_SIGPENDING
+#  define HAVE_RLIMIT_SIGPENDING_P t
+#else
+#  define HAVE_RLIMIT_SIGPENDING_P nil
+#endif
+#ifdef RLIMIT_STACK
+#  define HAVE_RLIMIT_STACK_P t
+#else
+#  define HAVE_RLIMIT_STACK_P nil
+#endif
+#ifdef RLIMIT_VMEM
+#  define HAVE_RLIMIT_VMEM_P t
+#else
+#  define HAVE_RLIMIT_VMEM_P nil
+#endif
+#define RLIMITS(_) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_AS_P, (as, RLIMIT_AS)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_CORE_P, (core, RLIMIT_CORE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_CPU_P, (cpu, RLIMIT_CPU)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_DATA_P, (data, RLIMIT_DATA)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_FSIZE_P, (fsize, RLIMIT_FSIZE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_LOCKS_P, (locks, RLIMIT_LOCKS)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_MEMLOCK_P, (memlock, RLIMIT_MEMLOCK)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_MSGQUEUE_P, (msgqueue, RLIMIT_MSGQUEUE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_NICE_P, (nice, RLIMIT_NICE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_NOFILE_P, (nofile, RLIMIT_NOFILE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_NPROC_P, (nproc, RLIMIT_NPROC)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_RSS_P, (rss, RLIMIT_RSS)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_RTPRIO_P, (rtprio, RLIMIT_RTPRIO)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_SIGPENDING_P, (sigpending, RLIMIT_SIGPENDING)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_STACK_P, (stack, RLIMIT_STACK)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_VMEM_P, (vmem, RLIMIT_VMEM))
+/***END***/
+
+/* --- The unpleasant conditional-output machinery --- */
+
+#define MAYBE_ITEM(_, emitp, args) GLUE(MAYBE_ITEM_, emitp)(_, args)
+#define MAYBE_ITEM_t(_, args) _ args
+#define MAYBE_ITEM_nil(_, args)
+
 /*----- Main program ------------------------------------------------------*/
 
 /* --- The global select state --- */
 
 extern sel_state *sel;
 
+/* --- Global state flags --- */
+
+extern unsigned flags;
+
+#define FW_SYSLOG 1u
+#define FW_QUIET 2u
+#define FW_SET 4u
+
 /* --- Help text --- */
 
 extern const char grammar_text[];
 extern const char option_text[];
 
+/* --- Generally useful magic constants --- */
+
+#define NOW ((time_t)-1)
+
 /* --- @fw_log@ --- *
  *
- * Arguments:  @time_t t@ = when the connection occurred or (@-1@)
+ * Arguments:  @time_t t@ = when the connection occurred or (@NOW@)
  *             @const char *fmt@ = format string to fill in
  *             @...@ = other arguments
  *
@@ -126,7 +295,8 @@ extern const char option_text[];
  * Use:                Logs a connection.
  */
 
-extern void fw_log(time_t /*t*/, const char */*fmt*/, ...);
+extern void PRINTF_LIKE(2, 3)
+  fw_log(time_t /*t*/, const char */*fmt*/, ...);
 
 /* --- @fw_inc@, @fw_dec@ --- *
  *
@@ -153,6 +323,7 @@ typedef struct chan {
   unsigned base, len;                  /* Base and length of data */
   unsigned f;                          /* Various interesting flags */
   void (*func)(void */*p*/);           /* Function to call on closure */
+  int err;                             /* What's wrong with the channel */
   void *p;                             /* Argument to pass function */
   sel_file r, w;                       /* Reader and writer selectors */
   char buf[CHAN_BUFSZ];                        /* The actual data buffer */
@@ -373,7 +544,8 @@ extern int token(scanner */*sc*/);
  * Use:                Reports an error at the current scanner location.
  */
 
-extern void error(scanner */*sc*/, const char */*msg*/, ...);
+extern void PRINTF_LIKE(2, 3) NORETURN
+  error(scanner */*sc*/, const char */*msg*/, ...);
 
 /* --- @pushback@ --- *
  *
@@ -565,6 +737,18 @@ extern int conf_prefix(scanner */*sc*/, const char */*p*/);
 
 extern void conf_name(scanner */*sc*/, char /*delim*/, dstr */*d*/);
 
+/* --- @conf_fname@ --- *
+ *
+ * Arguments:  @scanner *sc@ = pointer to scanner
+ *             @dstr *d@ = pointer to dynamic string for output
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads a file name from the input and stores it in @d@.
+ */
+
+extern void conf_fname(scanner */*sc*/, dstr */*d*/);
+
 /*----- Reference-counted file descriptors --------------------------------*/
 
 typedef struct reffd {
@@ -878,13 +1062,21 @@ extern void endpt_killall(void);
  *
  * Arguments:  @endpt *a@ = pointer to first endpoint
  *             @endpt *b@ = pointer to second endpoint
+ *             @const char *desc@ = description of connection
  *
  * Returns:    ---
  *
- * Use:                Joins two endpoints together.
+ * Use:                Joins two endpoints together.  It's OK to join endpoints
+ *             which are already joined; in fact, the the right thing to do
+ *             when your endpoint decides that it's not pending any more is
+ *             to join it to its partner again.
+ *
+ *             If the endpoints are already connected then the description
+ *             string is ignored.  The endpoint manager takes a copy of
+ *             the string, so you don't need to keep it around.
  */
 
-extern void endpt_join(endpt */*a*/, endpt */*b*/);
+extern void endpt_join(endpt */*a*/, endpt */*b*/, const char */*desc*/);
 
 /* --- @source_add@ --- *
  *