The branch main has been updated by otis:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7618c9e1637caea97723ff8accd60f3dc436b044

commit 7618c9e1637caea97723ff8accd60f3dc436b044
Author:     Juraj Lutter <o...@freebsd.org>
AuthorDate: 2024-04-25 13:40:00 +0000
Commit:     Juraj Lutter <o...@freebsd.org>
CommitDate: 2024-05-22 07:45:23 +0000

    daemon: Add -C (--restart-count) option
    
    Add a new option (-C, --restart-count) to specify the maximum
    number of times that the controlled process is restarted if
    restart (-r) is restarted.
    
    Reviewed by: kevans
    Differential Revision: https://reviews.freebsd.org/D44944
---
 usr.sbin/daemon/daemon.8 | 19 ++++++++++++++++---
 usr.sbin/daemon/daemon.c | 25 ++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/usr.sbin/daemon/daemon.8 b/usr.sbin/daemon/daemon.8
index 4fafb8528f18..52fbc230ac77 100644
--- a/usr.sbin/daemon/daemon.8
+++ b/usr.sbin/daemon/daemon.8
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd December 27, 2023
+.Dd April 25, 2024
 .Dt DAEMON 8
 .Os
 .Sh NAME
@@ -43,6 +43,7 @@
 .Op Fl T Ar syslog_tag
 .Op Fl l Ar syslog_facility
 .Op Fl R Ar restart_delay_seconds
+.Op Fl C Ar restart_count
 .Ar command arguments ...
 .Sh DESCRIPTION
 The
@@ -55,6 +56,17 @@ log file.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl C , Fl -restart-count Ar restart_count
+Restart the process at most
+.Ar restart_count
+times.
+When zero is specified,
+.Nm
+will exit.
+The maximum restart count is
+.Cm 128 .
+This option is used together with option
+.Fl -restart .
 .It Fl c , Fl -change-dir
 Change the current working directory to the root
 .Pq Dq Pa / .
@@ -72,8 +84,9 @@ Close
 and re-open it when signal
 .Dv SIGHUP
 is received, for interoperability with
-.Xr newsyslog 1
-and similar log rotation / archival mechanisms.  If
+.Xr newsyslog 8
+and similar log rotation / archival mechanisms.
+If
 .Fl -output-file
 is not specified, this flag is ignored.
 .It Fl l , Fl -syslog-facility Ar syslog_facility
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index 26e34d1d2e2b..7214faf8bde3 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -56,6 +56,9 @@
 /* 1 year in seconds */
 #define MAX_RESTART_DELAY 60*60*24*365
 
+/* Maximum number of restarts */
+#define MAX_RESTART_COUNT 128
+
 #define LBUF_SIZE 4096
 
 enum daemon_mode {
@@ -92,6 +95,8 @@ struct daemon_state {
        bool restart_enabled;
        bool syslog_enabled;
        bool log_reopen;
+       int restart_count;
+       int restarted_count;
 };
 
 static void restrict_process(const char *);
@@ -109,7 +114,7 @@ static void daemon_exec(struct daemon_state *);
 static bool daemon_is_child_dead(struct daemon_state *);
 static void daemon_set_child_pipe(struct daemon_state *);
 
-static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:h";
+static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:C:h";
 
 static const struct option longopts[] = {
        { "change-dir",         no_argument,            NULL,           'c' },
@@ -121,6 +126,7 @@ static const struct option longopts[] = {
        { "child-pidfile",      required_argument,      NULL,           'p' },
        { "supervisor-pidfile", required_argument,      NULL,           'P' },
        { "restart",            no_argument,            NULL,           'r' },
+       { "restart-count",      required_argument,      NULL,           'C' },
        { "restart-delay",      required_argument,      NULL,           'R' },
        { "title",              required_argument,      NULL,           't' },
        { "user",               required_argument,      NULL,           'u' },
@@ -139,6 +145,7 @@ usage(int exitcode)
            "              [-u user] [-o output_file] [-t title]\n"
            "              [-l syslog_facility] [-s syslog_priority]\n"
            "              [-T syslog_tag] [-m output_mask] [-R 
restart_delay_secs]\n"
+           "              [-C restart_count]\n"
            "command arguments ...\n");
 
        (void)fprintf(stderr,
@@ -152,6 +159,7 @@ usage(int exitcode)
            "  --child-pidfile      -p <file>  Write PID of the child process 
to file\n"
            "  --supervisor-pidfile -P <file>  Write PID of the supervisor 
process to file\n"
            "  --restart            -r         Restart child if it terminates 
(1 sec delay)\n"
+           "  --restart-count      -C <N>     Restart child at most N times, 
then exit\n"
            "  --restart-delay      -R <N>     Restart child if it terminates 
after N sec\n"
            "  --title              -t <title> Set the title of the supervisor 
process\n"
            "  --user               -u <user>  Drop privileges, run as given 
user\n"
@@ -198,6 +206,13 @@ main(int argc, char *argv[])
                case 'c':
                        state.keep_cur_workdir = 0;
                        break;
+               case 'C':
+                       state.restart_count = (int)strtonum(optarg, 0,
+                           MAX_RESTART_COUNT, &e);
+                       if (e != NULL) {
+                               errx(6, "invalid restart count: %s", e);
+                       }
+                       break;
                case 'f':
                        state.keep_fds_open = 0;
                        break;
@@ -331,6 +346,12 @@ main(int argc, char *argv[])
                state.mode = MODE_SUPERVISE;
                daemon_eventloop(&state);
                daemon_sleep(&state);
+               if (state.restart_enabled && state.restart_count > -1) {
+                       if (state.restarted_count >= state.restart_count) {
+                               state.restart_enabled = false;
+                       }
+                       state.restarted_count++;
+               }
        } while (state.restart_enabled);
 
        daemon_terminate(&state);
@@ -723,6 +744,8 @@ daemon_state_init(struct daemon_state *state)
                .keep_fds_open = 1,
                .output_fd = -1,
                .output_filename = NULL,
+               .restart_count = -1,
+               .restarted_count = 0
        };
 }
 

Reply via email to