1 /* $NetBSD: job.c,v 1.3 2020/04/18 19:32:19 christos Exp $ */ 2 3 /* Copyright 1988,1990,1993,1994 by Paul Vixie 4 * All rights reserved 5 */ 6 7 /* 8 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 9 * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. 10 * 11 * Permission to use, copy, modify, and distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 #include <sys/cdefs.h> 24 25 #if !defined(lint) && !defined(LINT) 26 #if 0 27 static char rcsid[] = "Id: job.c,v 1.6 2004/01/23 18:56:43 vixie Exp"; 28 #else 29 __RCSID("$NetBSD: job.c,v 1.3 2020/04/18 19:32:19 christos Exp $"); 30 #endif 31 #endif 32 33 #include "cron.h" 34 35 typedef struct _job { 36 SIMPLEQ_ENTRY(_job) entries; 37 entry *e; 38 user *u; 39 time_t t; 40 pid_t pid; 41 } job; 42 43 static SIMPLEQ_HEAD(job_queue, _job) jobs = SIMPLEQ_HEAD_INITIALIZER(jobs); 44 45 static int okay_to_go(job *); 46 47 void 48 job_add(entry *e, user *u, time_t target_time) { 49 job *j; 50 51 /* if already on queue, keep going */ 52 SIMPLEQ_FOREACH(j, &jobs, entries) { 53 if (j->e == e && j->u == u) { 54 j->t = target_time; 55 return; 56 } 57 } 58 59 /* build a job queue element */ 60 if ((j = calloc(1, sizeof(*j))) == NULL) 61 return; 62 j->e = e; 63 j->u = u; 64 j->t = target_time; 65 j->pid = -1; 66 67 /* add it to the tail */ 68 SIMPLEQ_INSERT_TAIL(&jobs, j, entries); 69 } 70 71 void 72 job_remove(entry *e, user *u) 73 { 74 job *j, *prev = NULL; 75 76 SIMPLEQ_FOREACH(j, &jobs, entries) { 77 if (j->e == e && j->u == u) { 78 if (prev == NULL) 79 SIMPLEQ_REMOVE_HEAD(&jobs, entries); 80 else 81 SIMPLEQ_REMOVE_AFTER(&jobs, prev, entries); 82 free(j); 83 break; 84 } 85 prev = j; 86 } 87 } 88 89 void 90 job_exit(pid_t jobpid) 91 { 92 job *j, *prev = NULL; 93 94 /* If a singleton exited, remove and free it. */ 95 SIMPLEQ_FOREACH(j, &jobs, entries) { 96 if (jobpid == j->pid) { 97 if (prev == NULL) 98 SIMPLEQ_REMOVE_HEAD(&jobs, entries); 99 else 100 SIMPLEQ_REMOVE_AFTER(&jobs, prev, entries); 101 free(j); 102 break; 103 } 104 prev = j; 105 } 106 } 107 108 int 109 job_runqueue(void) { 110 struct job_queue singletons = SIMPLEQ_HEAD_INITIALIZER(singletons); 111 job *j; 112 int run = 0; 113 114 while ((j = SIMPLEQ_FIRST(&jobs))) { 115 SIMPLEQ_REMOVE_HEAD(&jobs, entries); 116 if (okay_to_go(j)) { 117 j->pid = do_command(j->e, j->u); 118 run++; 119 } else { 120 char *x = mkprints(j->e->cmd, strlen(j->e->cmd)); 121 char *usernm = env_get("LOGNAME", j->e->envp); 122 123 log_it(usernm, getpid(), "CMD (skipped)", x); 124 free(x); 125 } 126 if (j->pid != -1) 127 SIMPLEQ_INSERT_TAIL(&singletons, j, entries); 128 else 129 free(j); 130 } 131 SIMPLEQ_CONCAT(&jobs, &singletons); 132 return (run); 133 } 134 135 136 static int 137 okay_to_go(job *j) 138 { 139 char *within, *t; 140 long delta; 141 142 if (j->pid != -1) 143 return 0; 144 145 if (j->e->flags & WHEN_REBOOT) 146 return (1); 147 148 within = env_get("CRON_WITHIN", j->e->envp); 149 if (within == NULL) 150 return (1); 151 152 /* XXX handle 2m, 4h, etc? */ 153 errno = 0; 154 delta = strtol(within, &t, 10); 155 if (errno == ERANGE || *t != '\0' || delta <= 0) 156 return (1); 157 158 return ((j->t + delta) > time(NULL)); 159 } 160