+ a_warn("SERVER ignore signal SIGHUP");
+}
+
+/* --- @a_parsetime@ --- *
+ *
+ * Arguments; @const char *p@ = time string to parse
+ *
+ * Returns: Time in seconds, or @< 0@ on error.
+ */
+
+static long a_parsetime(const char *p)
+{
+ char *q;
+ long t = strtol(p, &q, 0);
+
+ switch (*q) {
+ case 'd': t *= 24;
+ case 'h': t *= 60;
+ case 'm': t *= 60;
+ case 's': if (q[1] != 0)
+ default: t = -1;
+ case 0: break;
+ }
+ return (t);
+}
+
+/*----- Backgrounded operations -------------------------------------------*/
+
+/* --- @a_bgrelease@ --- *
+ *
+ * Arguments: @admin_bgop *bg@ = backgrounded operation
+ *
+ * Returns: ---
+ *
+ * Use: Removes a backgrounded operation from the queue, since
+ * (presumably) it's done.
+ */
+
+static void a_bgrelease(admin_bgop *bg)
+{
+ admin *a = bg->a;
+
+ if (bg->tag)
+ xfree(bg->tag);
+ else
+ selbuf_enable(&a->b);
+ if (bg->next)
+ bg->next->prev = bg->prev;
+ if (bg->prev)
+ bg->prev->next = bg->next;
+ else
+ a->bg = bg->next;
+ xfree(bg);
+ if (a->f & AF_CLOSE)
+ a_destroy(a);
+}
+
+/* --- @a_bgok@, @a_bginfo@, @a_bgfail@ --- *
+ *
+ * Arguments: @admin_bgop *bg@ = backgrounded operation
+ * @const char *fmt@ = format string
+ * @...@ = other arguments
+ *
+ * Returns: ---
+ *
+ * Use: Convenience functions for @a_write@.
+ */
+
+static void a_bgok(admin_bgop *bg)
+ { a_write(bg->a, "OK", bg->tag, 0); }
+
+static void a_bginfo(admin_bgop *bg, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ a_vwrite(bg->a, "INFO", bg->tag, fmt, ap);
+ va_end(ap);
+}
+
+static void a_bgfail(admin_bgop *bg, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ a_vwrite(bg->a, "FAIL", bg->tag, fmt, ap);
+ va_end(ap);
+}
+
+/* --- @a_bgadd@ --- *
+ *
+ * Arguments: @admin *a@ = administration connection
+ * @admin_bgop *bg@ = pointer to background operation
+ * @const char *tag@ = background tag, or null for foreground
+ * @void (*cancel)(admin_bgop *)@ = cancel function
+ *
+ * Returns: ---
+ *
+ * Use: Links a background job into the list.
+ */
+
+static void a_bgadd(admin *a, admin_bgop *bg, const char *tag,
+ void (*cancel)(admin_bgop *))
+{
+ if (tag)
+ bg->tag = xstrdup(tag);
+ else {
+ bg->tag = 0;
+ selbuf_disable(&a->b);
+ }
+ bg->a = a;
+ bg->cancel = cancel;
+ bg->next = a->bg;
+ bg->prev = 0;
+ a->bg = bg;
+ if (tag) a_write(a, "DETACH", tag, 0);