1 /* Copyright (C) 2018 Thomas Balzer */
3 /* This file is part of tomd. */
5 /* tomd is free software: you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation, either version 3 of the License, or */
8 /* (at your option) any later version. */
10 /* tomd is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with tomd. If not, see <http://www.gnu.org/licenses/>. */
24 #include "../include/job.h"
25 #include "../include/macros.h"
29 #include "../include/scm_interface.h"
32 #define MANIFEST_LOC "/.config/tomd/init/manifest.scm"
36 static int root_job
= -1;
39 static struct job jobs
[MAX_JOBS
] =
43 "/bin/bash", /* cmd */
54 static struct job jobs
[MAX_JOBS
] = {};
58 static struct job
load_job(SCM job_list
, int index
)
60 struct job ret
= { NULL
};
61 SCM scm_cur_job
= SCM_ARR(job_list
, index
);
63 if(scm_is_false(job_predicate(scm_cur_job
))){
64 tomd_p("job %d wasn't a real job type.", index
);
68 SCM scm_name
= get_name(scm_cur_job
);
69 SCM scm_cmd
= get_cmd(scm_cur_job
);
70 SCM scm_args
= get_args(scm_cur_job
);
72 /* TODO > Handle these. */
73 /* planned is to be able to run at different points, and at */
74 /* the request of a user. for testing we do things all at */
76 SCM scm_start_trigger
= get_start_trigger(scm_cur_job
);
77 SCM scm_end_trigger
= get_end_trigger(scm_cur_job
);
79 char *job_name
= scm_to_locale_string(scm_name
);
80 char *job_cmd
= scm_to_locale_string(scm_cmd
);
82 int jlen
= scm_to_int(scm_length(scm_args
));
87 scm_to_locale_string(SCM_ARR(scm_args
, j
));
96 ret
.args
[j
] = real_args
[j
- 1];
98 ret
.args
[jlen
+ 1] = NULL
;
99 ret
.args
[0] = ret
.cmd
;
104 static void *load_manifest(void *args
)
108 tomd_p("arg to load_manifest is NULL");
111 manifest_loc
= (char *)args
;
113 scm_c_primitive_load(args
);
116 scm_c_public_ref("tomd manifest", "job-list");
118 if(scm_is_false(scm_job_list
)){
119 tomd_p("no job-list found in manifest.scm");
123 if(scm_is_false(scm_list_p(scm_job_list
))){
124 tomd_p("job-list found, but isn't a list.");
129 int len
= SCM_LIST_LEN(scm_job_list
);
130 tomd_p("len=%d, max=%d", len
, MAX_JOBS
);
132 i
< len
&& i
< MAX_JOBS
;
134 jobs
[i
] = load_job(scm_job_list
, i
);
136 tomd_p("looked at %d jobs.", i
);
141 static char *lookup_user_folder(void)
144 uid_t user
= getuid();
145 struct passwd
*userpasswd
=
148 /* take the manifest location and sub ~ for pw_dir */
149 char *buffer
= (char *)malloc(sizeof(char) * 300);
150 strcpy(buffer
, userpasswd
->pw_dir
);
151 int len
= strlen(userpasswd
->pw_dir
);
152 strcpy(buffer
+ len
, MANIFEST_LOC
);
161 char *manifest
= lookup_user_folder();
163 tomd_p("Loading jobs from '%s'", manifest
);
166 scm_with_guile(load_manifest
,
169 tomd_p("Stubbed job loading.");
171 tomd_p("Finished loading.");
176 jobs
[i
].cmd
== NULL
) {
179 tomd_p("JOB <%d>:", i
);
180 tomd_p(" cmd:'%s'", jobs
[i
].cmd
);
184 jobs
[i
].args
[j
] == NULL
){
187 tomd_p(" arg [%d]:'%s'", j
, jobs
[i
].args
[j
]);
195 static int stdincache
;
196 static int stdoutcache
;
197 static int stderrcache
;
201 /* cache all filedes */
202 stdincache
= dup(STDIN_FILENO
);
203 stdoutcache
= dup(STDOUT_FILENO
);
204 stderrcache
= dup(STDERR_FILENO
);
206 tomd_p("going silent.");
208 /* close default filedes */
210 close(STDOUT_FILENO
);
211 close(STDERR_FILENO
);
213 tomd_p("now silent.");
216 #define LOG_DIR "/var/log/tomd/"
218 void run_job(int index
)
220 struct job
*job
= &jobs
[index
];
223 if(pid
== 0){ /* child */
225 /* redirect to a file */
227 strcpy(buf
, LOG_DIR
);
228 strcpy(buf
+ strlen(LOG_DIR
), job
->name
);
229 tomd_p("redirecting stdout to %s.", buf
);
230 if(unlink(buf
) != 0){
231 tomd_p("file couldn't be removed.");
234 int fd
= open(buf
, O_WRONLY
| O_CREAT
, 0644);
236 tomd_p("couldn't open file.");
240 dup2(fd
, STDOUT_FILENO
);
241 dup2(fd
, STDERR_FILENO
);
244 execvp(job
->cmd
, job
->args
);
245 tomd_panic("execvp for '%s' failed", job
->cmd
);
247 tomd_p("forked [%d] to run '%s'", pid
, job
->cmd
);
249 waitpid(job
->pid
, &job
->last_status
, WNOHANG
);
253 struct job
*lookup_job(char *my_job_name
)
258 if(jobs
[i
].name
== NULL
){
261 if(strcmp(jobs
[i
].name
, my_job_name
) == 0){
274 if(jobs
[i
].cmd
== NULL
){
275 tomd_p("out of jobs");
278 tomd_p("running job [%d] '%s'", i
, jobs
[i
].cmd
);
281 if(root_job
!= i
&& root_job
!= -1){
282 tomd_p("error! only one job can be root.");
291 static int delay
= 0;
293 void check_root_job(void)
296 if(delay
% 100 != 0){
302 int n_pid
= waitpid(jobs
[root_job
].pid
, &jobs
[root_job
].last_status
, WNOHANG
);
303 if(n_pid
!= jobs
[root_job
].pid
){
307 if(WIFEXITED(jobs
[root_job
].last_status
)){
308 /* we died, restart it */
309 tomd_p("restarting root job. (last pid = %d, last status = %d)",
310 jobs
[root_job
].pid
, jobs
[root_job
].last_status
);