xref: /openbsd/usr.sbin/cron/job.c (revision 73471bf0)
1 /*	$OpenBSD: job.c,v 1.15 2020/04/17 02:12:56 millert Exp $	*/
2 
3 /* Copyright 1988,1990,1993,1994 by Paul Vixie
4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 
22 #include <bitstring.h>		/* for structs.h */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <syslog.h>
26 #include <time.h>		/* for structs.h */
27 
28 #include "macros.h"
29 #include "structs.h"
30 #include "funcs.h"
31 
32 typedef	struct _job {
33 	SIMPLEQ_ENTRY(_job) entries;
34 	entry		*e;
35 	user		*u;
36 	pid_t		pid;
37 } job;
38 
39 
40 static SIMPLEQ_HEAD(job_queue, _job) jobs = SIMPLEQ_HEAD_INITIALIZER(jobs);
41 
42 void
43 job_add(entry *e, user *u)
44 {
45 	job *j;
46 
47 	/* if already on queue, keep going */
48 	SIMPLEQ_FOREACH(j, &jobs, entries) {
49 		if (j->e == e && j->u == u) {
50 			if ((j->e->flags & DONT_LOG) == 0) {
51 				syslog(LOG_INFO, "(%s) SKIPPING (%s)",
52 				    j->u->name, j->e->cmd);
53 			}
54 			return;
55 		}
56 	}
57 
58 	/* build a job queue element */
59 	if ((j = malloc(sizeof(job))) == NULL)
60 		return;
61 	j->e = e;
62 	j->u = u;
63 	j->pid = -1;
64 
65 	/* add it to the tail */
66 	SIMPLEQ_INSERT_TAIL(&jobs, j, entries);
67 }
68 
69 void
70 job_remove(entry *e, user *u)
71 {
72 	job *j, *prev = NULL;
73 
74 	SIMPLEQ_FOREACH(j, &jobs, entries) {
75 		if (j->e == e && j->u == u) {
76 			if (prev == NULL)
77 				SIMPLEQ_REMOVE_HEAD(&jobs, entries);
78 			else
79 				SIMPLEQ_REMOVE_AFTER(&jobs, prev, entries);
80 			free(j);
81 			break;
82 		}
83 		prev = j;
84 	}
85 }
86 
87 void
88 job_exit(pid_t jobpid)
89 {
90 	job *j, *prev = NULL;
91 
92 	/* If a singleton exited, remove and free it. */
93 	SIMPLEQ_FOREACH(j, &jobs, entries) {
94 		if (jobpid == j->pid) {
95 			if (prev == NULL)
96 				SIMPLEQ_REMOVE_HEAD(&jobs, entries);
97 			else
98 				SIMPLEQ_REMOVE_AFTER(&jobs, prev, entries);
99 			free(j);
100 			break;
101 		}
102 		prev = j;
103 	}
104 }
105 
106 int
107 job_runqueue(void)
108 {
109 	struct job_queue singletons = SIMPLEQ_HEAD_INITIALIZER(singletons);
110 	job *j;
111 	int run = 0;
112 
113 	while ((j = SIMPLEQ_FIRST(&jobs))) {
114 		SIMPLEQ_REMOVE_HEAD(&jobs, entries);
115 
116 		/* Only start the job if it is not a running singleton. */
117 		if (j->pid == -1) {
118 			j->pid = do_command(j->e, j->u);
119 			run++;
120 		}
121 
122 		/* Singleton jobs persist in the queue until they exit. */
123 		if (j->pid != -1)
124 			SIMPLEQ_INSERT_TAIL(&singletons, j, entries);
125 		else
126 			free(j);
127 	}
128 	SIMPLEQ_CONCAT(&jobs, &singletons);
129 	return (run);
130 }
131