Implement a library for C++ helpers to link against which provides
a main() function to achieve generic startup/query/shutdown debug
information and and a simpler API for processing a query line.

Some fake helpers and unlinkd_daemon are updated to be the first uses of this library
instead of having custom main() functions.


Amos

Implement a library for C++ helpers to link against which provides
a main() function to achieve generic startup/query/shutdown debug
information and and a simpler API for processing a query line.

Some fake helpers and unlinkd_daemon are updated to use this library
instead of custom main() functions.

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2017-06-13 06:46:58 +0000
+++ src/Makefile.am	2017-06-18 15:01:15 +0000
@@ -581,42 +581,44 @@
 	$(COMPAT_LIB) \
 	$(XTRA_LIBS)
 
 if ENABLE_LOADABLE_MODULES
 squid_SOURCES += $(LOADABLE_MODULES_SOURCES)
 squid_LDADD += -L$(top_builddir) $(LIBLTDL)
 squid_LDFLAGS = -export-dynamic -dlopen force
 ## when static module linking is supported and enabled:
 ## squid_LDFLAGS = -all-static -dlopen self
 ##
 ## LTDL headers require their local include path...
 AM_CPPFLAGS += $(INCLTDL)
 endif
 
 ## Kerberos libraries require their include path...
 AM_CPPFLAGS += $(KRB5INCS)
 
 
 unlinkd_SOURCES = unlinkd_daemon.cc
 unlinkd_LDADD = \
+	helper/libhelper_process.la \
 	$(COMPAT_LIB) \
 	$(XTRA_LIBS)
+unlinkd_LDFLAGS= $(AM_CPPFLAGS)
 
 recv_announce_SOURCES = recv-announce.cc
 
 ## What requires what..
 ## many things want ACLChecklist.cc
 ## ACLChecklist.cc wants AuthUserRequest.cc
 ## ACLChecklist.cc wants AuthScheme.cc
 ## ACLChecklist.cc wants ACLProxyAuth.cc directly
 ## ACLProxyAuth.cc wants ACLUserData
 ## ACLProxyAuth.cc wants ACLRegexData
 ## cache_cf.cc wants $(AUTH_LIBS)
 ## cache_cf.cc wants store/libstore.la
 ## cache_cf.cc wants AnyP::PortCfg
 ## client_side wants client_db
 ## client_db wants SNMP_SOURCE
 ## snmp_core wants ACLStringData
 ## tools.cc wants ip/libip.la
 ## client_side.cc wants ip/libip.la
 ## libbase.la wants cbdata.*
 ## libbase.la wants MemBuf.*

=== modified file 'src/auth/basic/fake/Makefile.am'
--- src/auth/basic/fake/Makefile.am	2017-01-01 00:12:22 +0000
+++ src/auth/basic/fake/Makefile.am	2017-06-18 15:01:27 +0000
@@ -1,15 +1,17 @@
 ## Copyright (C) 1996-2017 The Squid Software Foundation and contributors
 ##
 ## Squid software is distributed under GPLv2+ license and includes
 ## contributions from numerous individuals and organizations.
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
 include $(top_srcdir)/src/Common.am
 
 libexec_PROGRAMS = basic_fake_auth
 
 basic_fake_auth_SOURCES = fake.cc
-basic_fake_auth_LDADD = $(COMPAT_LIB)
+basic_fake_auth_LDADD = \
+	$(top_builddir)/src/helper/libhelper_process.la \
+	$(COMPAT_LIB)
 
 EXTRA_DIST = required.m4

=== modified file 'src/auth/basic/fake/fake.cc'
--- src/auth/basic/fake/fake.cc	2017-06-16 18:38:19 +0000
+++ src/auth/basic/fake/fake.cc	2017-06-18 15:01:27 +0000
@@ -26,84 +26,74 @@
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
 /*
  * Fake Basic Authentication program for Squid.
  *
  * This code gets the user details and returns OK.
  * It is intended for testing use and as a base for further implementation.
  */
 
 #include "squid.h"
+#include "helper/Process.h"
 #include "helper/protocol_defines.h"
 
-#include <iostream>
-#include <string>
-
 /**
  * options:
  * -d enable debugging.
  * -h interface help.
  */
-std::string program_name;
 
 static void
 usage(void)
 {
     std::cerr <<
-              "Usage: " << program_name << " [-d] [-h]" << std::endl <<
+              "Usage: " << HelperProcess::Name << " [-d] [-h]" << std::endl <<
               " -d  enable debugging." << std::endl <<
               " -h  this message" << std::endl << std::endl;
 }
 
-static void
-process_options(int argc, char *argv[])
+bool
+HelperProcess::Start()
 {
-    int opt;
+    return true; // nothing to do
+}
 
+bool
+HelperProcess::Options(int argc, char *argv[])
+{
+    int opt;
     opterr = 0;
     while (-1 != (opt = getopt(argc, argv, "hd"))) {
         switch (opt) {
         case 'd':
             debug_enabled = 1;
             break;
         case 'h':
             usage();
-            exit(EXIT_SUCCESS);
+            return false;
         default:
-            std::cerr << program_name << ": FATAL: unknown option: -" <<
+            std::cerr << HelperProcess::Name << ": FATAL: unknown option: -" <<
                       static_cast<char>(optopt) << ". Exiting" << std::endl;
             usage();
-            exit(EXIT_FAILURE);
+            return false;
         }
     }
+    return true;
 }
 
-int
-main(int argc, char *argv[])
+void
+HelperProcess::DoOneRequest(std::string &)
 {
-    program_name = argv[0];
-    process_options(argc, argv);
-
-    ndebug(program_name << ' ' << VERSION << ' ' << SQUID_BUILD_INFO <<
-           " starting up...");
-    std::string buf;
-    while (getline(std::cin,buf)) { // will return false at EOF
-        ndebug("Got " << buf.length() << " bytes '" << buf << "' from Squid");
-
-        /* send 'OK' result back to Squid */
-        SEND_OK("");
-    }
-    ndebug(program_name << ' ' << VERSION << ' ' << SQUID_BUILD_INFO <<
-           " shutting down...");
-    return EXIT_SUCCESS;
+    // fake helper always sends 'OK' result back to Squid
+    SEND_OK("");
 }
 

=== modified file 'src/auth/ntlm/fake/Makefile.am'
--- src/auth/ntlm/fake/Makefile.am	2017-01-01 00:12:22 +0000
+++ src/auth/ntlm/fake/Makefile.am	2017-06-18 15:01:30 +0000
@@ -1,27 +1,28 @@
 ## Copyright (C) 1996-2017 The Squid Software Foundation and contributors
 ##
 ## Squid software is distributed under GPLv2+ license and includes
 ## contributions from numerous individuals and organizations.
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
 include $(top_srcdir)/src/Common.am
 
 libexec_PROGRAMS= ntlm_fake_auth
 
 ntlm_fake_auth_SOURCES= ntlm_fake_auth.cc
 ntlm_fake_auth_LDADD= \
 	$(top_builddir)/lib/ntlmauth/libntlmauth.la \
 	$(top_builddir)/lib/libmiscencoding.la \
+	$(top_builddir)/src/helper/libhelper_process.la \
 	$(COMPAT_LIB) \
 	$(NETTLELIB) \
 	$(CRYPTLIB) \
 	$(XTRA_LIBS)
 
 ## Demo using perl.
 ## ntlm_fake_auth.pl: ntlm_fake_auth.pl.in
 ##	$(subst_perlshell)
 
 EXTRA_DIST= \
 	ntlm_fake_auth.pl.in \
 	required.m4

=== modified file 'src/auth/ntlm/fake/ntlm_fake_auth.cc'
--- src/auth/ntlm/fake/ntlm_fake_auth.cc	2017-06-16 18:38:19 +0000
+++ src/auth/ntlm/fake/ntlm_fake_auth.cc	2017-06-18 15:01:30 +0000
@@ -18,208 +18,195 @@
  * Jon Thackray <[email protected]>. Initial ntlm code by
  * Andrew Doran <[email protected]>.
  *
  * This code gets the username and returns it. No validation is done.
  * and by the way: it is a complete patch-up. Use the "real thing" NTLMSSP
  * if you can.
  *
  * Revised by Guido Serassio: <[email protected]>
  *
  * - Added negotiation of UNICODE char support
  * - More detailed debugging info
  *
  */
 
 /* undefine this to have strict protocol adherence. You don't really need
  * that though */
 #define IGNORANCE_IS_BLISS
 
 #include "squid.h"
 #include "base64.h"
+#include "helper/Process.h"
 #include "helper/protocol_defines.h"
 #include "ntlmauth/ntlmauth.h"
 #include "ntlmauth/support_bits.cci"
 
 #include <cctype>
 #include <cstring>
 #if HAVE_CRYPT_H
 #include <crypt.h>
 #endif
 #if HAVE_PWD_H
 #include <pwd.h>
 #endif
 #if HAVE_GETOPT_H
 #include <getopt.h>
 #endif
 
 /* A couple of harmless helper macros */
 #define SEND(X) {debug("sending '%s' to squid\n",X); printf(X "\n");}
 #ifdef __GNUC__
 #define SEND2(X,Y...) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
 #define SEND3(X,Y...) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
 #define SEND4(X,Y...) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
 #else
 /* no gcc, no debugging. varargs macros are a gcc extension */
 #define SEND2(X,Y) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
 #define SEND3(X,Y,Z) {debug("sending '" X "' to squid\n",Y,Z); printf(X "\n",Y,Z);}
 #define SEND4(X,Y,Z,W) {debug("sending '" X "' to squid\n",Y,Z,W); printf(X "\n",Y,Z,W);}
 #endif
 
 const char *authenticate_ntlm_domain = "WORKGROUP";
 int strip_domain_enabled = 0;
 int NTLM_packet_debug_enabled = 0;
 
 /*
  * options:
  * -d enable debugging.
  * -v enable verbose NTLM packet debugging.
  * -l if specified, changes behavior on failures to last-ditch.
  */
-char *my_program_name = NULL;
 
 static void
-usage(void)
+usage()
 {
-    fprintf(stderr,
-            "Usage: %s [-d] [-v] [-h]\n"
-            " -d  enable debugging.\n"
-            " -S  strip domain from username.\n"
-            " -v  enable verbose NTLM packet debugging.\n"
-            " -h  this message\n\n",
-            my_program_name);
+    std::cerr <<
+              "Usage: " << HelperProcess::Name << " [-d] [-v] [-h]" << std::endl <<
+              " -d  enable debugging." << std::endl <<
+              " -S  strip domain from username." << std::endl <<
+              " -v  enable verbose NTLM packet debugging." << std::endl <<
+              " -h  this message" << std::endl << std::endl;
 }
 
-static void
-process_options(int argc, char *argv[])
+bool
+HelperProcess::Start()
+{
+    setbuf(stdout, nullptr);
+    setbuf(stderr, nullptr);
+    return true;
+}
+
+bool
+HelperProcess::Options(int argc, char *argv[])
 {
-    int opt, had_error = 0;
+    int opt;
+    bool had_error = false;
 
     opterr = 0;
     while (-1 != (opt = getopt(argc, argv, "hdvS"))) {
         switch (opt) {
         case 'd':
             debug_enabled = 1;
             break;
         case 'v':
             debug_enabled = 1;
             NTLM_packet_debug_enabled = 1;
             break;
         case 'S':
             strip_domain_enabled = 1;
             break;
         case 'h':
             usage();
-            exit(EXIT_SUCCESS);
+            return false;
         case '?':
             opt = optopt;
         /* fall thru to default */
         default:
             fprintf(stderr, "unknown option: -%c. Exiting\n", opt);
             usage();
-            had_error = 1;
+            had_error = false;
         }
     }
-    if (had_error)
-        exit(EXIT_FAILURE);
+    return !had_error;
 }
 
-int
-main(int argc, char *argv[])
+void
+HelperProcess::DoOneRequest(std::string &line)
 {
-    char buf[HELPER_INPUT_BUFFER];
-    int buflen = 0;
-    uint8_t decodedBuf[HELPER_INPUT_BUFFER];
-    int decodedLen;
     char user[NTLM_MAX_FIELD_LENGTH], domain[NTLM_MAX_FIELD_LENGTH];
-    char *p;
-    char helper_command[3];
-    int len;
+    user[0] = '\0';     /*no user code */
+    domain[0] = '\0';       /*no domain code */
 
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
+    const char *buf = line.c_str();
+    int buflen = line.length();   /* keep this so we only scan the buffer for \0 once per loop */
 
-    my_program_name = argv[0];
-
-    process_options(argc, argv);
+    ntlmhdr *packet = nullptr;
+    struct base64_decode_ctx ctx;
+    base64_decode_init(&ctx);
+    size_t dstLen = 0;
+    uint8_t decodedBuf[HELPER_INPUT_BUFFER];
+    int decodedLen = 0;
+    if (buflen > 3 &&
+            base64_decode_update(&ctx, &dstLen, decodedBuf, buflen-3, reinterpret_cast<const uint8_t*>(buf+3)) &&
+            base64_decode_final(&ctx)) {
+        decodedLen = dstLen;
+        packet = (ntlmhdr*)decodedBuf;
+    }
 
-    debug("%s " VERSION " " SQUID_BUILD_INFO " starting up...\n", my_program_name);
-
-    while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != NULL) {
-        user[0] = '\0';     /*no user code */
-        domain[0] = '\0';       /*no domain code */
-
-        if ((p = strchr(buf, '\n')) != NULL)
-            *p = '\0';      /* strip \n */
-        buflen = strlen(buf);   /* keep this so we only scan the buffer for \0 once per loop */
-        ntlmhdr *packet;
-        struct base64_decode_ctx ctx;
-        base64_decode_init(&ctx);
-        size_t dstLen = 0;
-        if (buflen > 3 &&
-                base64_decode_update(&ctx, &dstLen, decodedBuf, buflen-3, reinterpret_cast<const uint8_t*>(buf+3)) &&
-                base64_decode_final(&ctx)) {
-            decodedLen = dstLen;
-            packet = (ntlmhdr*)decodedBuf;
+    char helper_command[3];
+    if (buflen > 3 && NTLM_packet_debug_enabled) {
+        strncpy(helper_command, buf, 2);
+        helper_command[2] = '\0';
+        debug("Got '%s' from Squid with data:\n", helper_command);
+        hex_dump((unsigned char *)decodedBuf, decodedLen);
+    } else
+        debug("Got '%s' from Squid\n", buf);
+
+    if (strncmp(buf, "YR", 2) == 0) {
+        char nonce[NTLM_NONCE_LEN];
+        ntlm_challenge chal;
+        ntlm_make_nonce(nonce);
+        if (buflen > 3 && packet) {
+            ntlm_negotiate *nego = (ntlm_negotiate *)packet;
+            ntlm_make_challenge(&chal, authenticate_ntlm_domain, NULL, nonce, NTLM_NONCE_LEN, nego->flags);
         } else {
-            packet = NULL;
-            decodedLen = 0;
+            ntlm_make_challenge(&chal, authenticate_ntlm_domain, NULL, nonce, NTLM_NONCE_LEN, NTLM_NEGOTIATE_ASCII);
         }
+        // TODO: find out what this context means, and why only the fake auth helper contains it.
+        chal.context_high = htole32(0x003a<<16);
 
-        if (buflen > 3 && NTLM_packet_debug_enabled) {
-            strncpy(helper_command, buf, 2);
-            helper_command[2] = '\0';
-            debug("Got '%s' from Squid with data:\n", helper_command);
-            hex_dump((unsigned char *)decodedBuf, decodedLen);
-        } else
-            debug("Got '%s' from Squid\n", buf);
-
-        if (strncmp(buf, "YR", 2) == 0) {
-            char nonce[NTLM_NONCE_LEN];
-            ntlm_challenge chal;
-            ntlm_make_nonce(nonce);
-            if (buflen > 3 && packet) {
-                ntlm_negotiate *nego = (ntlm_negotiate *)packet;
-                ntlm_make_challenge(&chal, authenticate_ntlm_domain, NULL, nonce, NTLM_NONCE_LEN, nego->flags);
-            } else {
-                ntlm_make_challenge(&chal, authenticate_ntlm_domain, NULL, nonce, NTLM_NONCE_LEN, NTLM_NEGOTIATE_ASCII);
-            }
-            // TODO: find out what this context means, and why only the fake auth helper contains it.
-            chal.context_high = htole32(0x003a<<16);
+        int len = sizeof(chal) - sizeof(chal.payload) + le16toh(chal.target.maxlen);
 
-            len = sizeof(chal) - sizeof(chal.payload) + le16toh(chal.target.maxlen);
+        struct base64_encode_ctx eCtx;
+        base64_encode_init(&eCtx);
+        uint8_t *data = (uint8_t*)xcalloc(base64_encode_len(len), 1);
+        size_t blen = base64_encode_update(&eCtx, data, len, reinterpret_cast<uint8_t*>(&chal));
+        blen += base64_encode_final(&eCtx, data+blen);
+        if (NTLM_packet_debug_enabled) {
+            printf("TT %.*s\n", (int)blen, data);
+            debug("sending 'TT' to squid with data:\n");
+            hex_dump((unsigned char *)&chal, len);
+        } else
+            SEND3("TT %.*s", (int)blen, data);
+        safe_free(data);
 
-            struct base64_encode_ctx eCtx;
-            base64_encode_init(&eCtx);
-            uint8_t *data = (uint8_t*)xcalloc(base64_encode_len(len), 1);
-            size_t blen = base64_encode_update(&eCtx, data, len, reinterpret_cast<uint8_t*>(&chal));
-            blen += base64_encode_final(&eCtx, data+blen);
-            if (NTLM_packet_debug_enabled) {
-                printf("TT %.*s\n", (int)blen, data);
-                debug("sending 'TT' to squid with data:\n");
-                hex_dump((unsigned char *)&chal, len);
-            } else
-                SEND3("TT %.*s", (int)blen, data);
-            safe_free(data);
-
-        } else if (strncmp(buf, "KK ", 3) == 0) {
-            if (!packet) {
-                SEND("BH received KK with no data! user=");
-            } else if (ntlm_validate_packet(packet, NTLM_AUTHENTICATE) == NTLM_ERR_NONE) {
-                if (ntlm_unpack_auth((ntlm_authenticate *)packet, user, domain, decodedLen) == NTLM_ERR_NONE) {
-                    lc(user);
-                    if (strip_domain_enabled) {
-                        SEND2("AF %s", user);
-                    } else {
-                        SEND4("AF %s%s%s", domain, (*domain?"\\":""), user);
-                    }
+    } else if (strncmp(buf, "KK ", 3) == 0) {
+        if (!packet) {
+            SEND("BH received KK with no data! user=");
+        } else if (ntlm_validate_packet(packet, NTLM_AUTHENTICATE) == NTLM_ERR_NONE) {
+            if (ntlm_unpack_auth((ntlm_authenticate *)packet, user, domain, decodedLen) == NTLM_ERR_NONE) {
+                lc(user);
+                if (strip_domain_enabled) {
+                    SEND2("AF %s", user);
                 } else {
-                    lc(user);
-                    SEND4("NA invalid credentials, user=%s%s%s", domain, (*domain?"\\":""), user);
+                    SEND4("AF %s%s%s", domain, (*domain?"\\":""), user);
                 }
             } else {
-                SEND("BH wrong packet type! user=");
+                lc(user);
+                SEND4("NA invalid credentials, user=%s%s%s", domain, (*domain?"\\":""), user);
             }
+        } else {
+            SEND("BH wrong packet type! user=");
         }
     }
-    return EXIT_SUCCESS;
 }
 

=== modified file 'src/helper/Makefile.am'
--- src/helper/Makefile.am	2017-01-01 00:12:22 +0000
+++ src/helper/Makefile.am	2017-06-18 15:01:36 +0000
@@ -1,22 +1,25 @@
 ## Copyright (C) 1996-2017 The Squid Software Foundation and contributors
 ##
 ## Squid software is distributed under GPLv2+ license and includes
 ## contributions from numerous individuals and organizations.
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
 include $(top_srcdir)/src/Common.am
 include $(top_srcdir)/src/TestHeaders.am
 
-noinst_LTLIBRARIES = libhelper.la
+noinst_LTLIBRARIES = libhelper.la libhelper_process.la
 
 libhelper_la_SOURCES = \
 	ChildConfig.cc \
 	ChildConfig.h \
 	forward.h \
 	Reply.cc \
 	Reply.h \
 	Request.h \
 	ResultCode.h
 
-EXTRA_DIST= protocol_defines.h
+libhelper_process_la_SOURCES = \
+	Process.cc \
+	Process.h \
+	protocol_defines.h

=== added file 'src/helper/Process.cc'
--- src/helper/Process.cc	1970-01-01 00:00:00 +0000
+++ src/helper/Process.cc	2017-06-18 15:01:36 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
+ * Copyright (c) 2017, Treehouse Networks Ltd. New Zealand
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "squid.h"
+#include "helper/Process.h"
+
+#include <cstdlib>
+
+std::string HelperProcess::Name;
+
+int
+main(int argc, char *argv[])
+{
+    HelperProcess::Name.append(argv[0]);
+
+    if (!HelperProcess::Start())
+        return EXIT_FAILURE;
+
+    if (!HelperProcess::Options(argc, argv))
+        return EXIT_FAILURE;
+
+    ndebug(HelperProcess::Name << "| " << VERSION << ' ' << SQUID_BUILD_INFO << " starting up...");
+
+    std::string buf;
+    while (getline(std::cin,buf)) { // will return false at EOF
+        ndebug(HelperProcess::Name << "| Got " << buf.length() << " bytes '" << buf << "' from Squid");
+        HelperProcess::DoOneRequest(buf);
+    }
+
+    ndebug(HelperProcess::Name << "| " << VERSION << ' ' << SQUID_BUILD_INFO << " shutting down...");
+    return EXIT_SUCCESS;
+}
+

=== added file 'src/helper/Process.h'
--- src/helper/Process.h	1970-01-01 00:00:00 +0000
+++ src/helper/Process.h	2017-06-18 15:20:09 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
+ * Copyright (c) 2017, Treehouse Networks Ltd. New Zealand
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SQUID__SRC_HELPER_PROCESS_H
+#define SQUID__SRC_HELPER_PROCESS_H
+
+#include <string>
+
+namespace HelperProcess {
+
+extern std::string Name;
+
+/**
+ * Startup initialization needed by the helper.
+ */
+bool Start();
+
+/**
+ * Parse the command line options for this helper.
+ *
+ * The options -d and -h are reserved for debug and help text.
+ *
+ * \return false on failure to parse any option.
+ */
+bool Options(int argc, char *argv[]);
+
+/**
+ * Perform all logic necessary to process and respond to Squid
+ * for a single query.
+ */
+void DoOneRequest(std::string &buffer);
+
+} // namespace HelperProcess
+
+#endif /* SQUID__SRC_HELPER_PROCESS_H */
+

=== modified file 'src/unlinkd_daemon.cc'
--- src/unlinkd_daemon.cc	2017-06-16 18:38:19 +0000
+++ src/unlinkd_daemon.cc	2017-06-18 15:01:50 +0000
@@ -1,70 +1,64 @@
 /*
  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section --    Unlink Daemon */
 
-#define SQUID_HELPER 1
-
 #include "squid.h"
+#include "helper/Process.h"
+#include "helper/protocol_defines.h"
 
-#include <iostream>
-#include <cstdio>
 #if HAVE_PATHS_H
 #include <paths.h>
 #endif
 
-/**
- \defgroup unlinkd unlinkd
- \ingroup ExternalPrograms
- \par
-    The unlink(2) system call can cause a process to block
-    for a significant amount of time.  Therefore we do not want
-    to make unlink() calls from Squid.  Instead we pass them
-    to this external process.
- */
+bool
+HelperProcess::Start()
+{
+    close(2);
+    if (open(_PATH_DEVNULL, O_RDWR) < 0) {
+        ; // the irony of having to close(2) earlier is that we cannot report this failure.
+    }
 
-/// \ingroup unlinkd
-#define UNLINK_BUF_LEN 1024
+    return true;
+}
+
+bool
+HelperProcess::Options(int, char*[])
+{
+    return true; // This helper provides no command line options.
+}
 
 /**
- \ingroup unlinkd
- \par This is the unlinkd external process.
+ * This is the unlinkd external process.
+ *
+ * The unlink(2) system call can cause a process to block
+ * for a significant amount of time. Therefore we do not want
+ * to make unlink() calls from Squid. Instead we pass them
+ * to this external process.
  *
- \par
- *    unlinkd receives the full path of any files to be removed
- *    from stdin, each on its own line.
+ * unlinkd receives the full path of any files to be removed
+ * from stdin, each on its own line.
  *
- \par
- *    The results for each file are printed to stdout in the order
- *    they were received
+ * The results for each file are printed to stdout in the order
+ * they were received.
  *
- \param argc Ignored.
- \param argv Ignored.
- \retval ERR An error occured removing the file.
- \retval OK  The file has been removed.
+ * Output:
+ *  ERR   An error occured removing the file.
+ *  OK    The file has been removed.
  */
-int
-main(int, char *[])
+void
+HelperProcess::DoOneRequest(std::string &buf)
 {
-    std::string sbuf;
-    close(2);
-    if (open(_PATH_DEVNULL, O_RDWR) < 0) {
-        ; // the irony of having to close(2) earlier is that we cannot report this failure.
-    }
-    while (getline(std::cin, sbuf)) {
-        // tailing newline is removed by getline
-        const int rv = remove(sbuf.c_str());
-        if (rv < 0)
-            std::cout << "ERR" << std::endl; // endl flushes
-        else
-            std::cout << "OK" << std::endl;
-    }
-
-    return EXIT_SUCCESS;
+    // tailing newline was removed by getline
+    const int rv = remove(buf.c_str());
+    if (rv < 0)
+        SEND_ERR("");
+    else
+        SEND_OK("");
 }
 

_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev

Reply via email to