1 #include "uogetopt.h"
2 #include "scheduled.h"
3 #include "open.h"
4 #include "attributes.h"
5 #include "stralloc.h"
6 #include "bailout.h"
7 #include "buffer.h"
8 #include "env.h"
9 #include "str.h"
10 #include "scan.h"
11 #include "error.h"
12 #include <unistd.h> /* read, write, fsync, chdir */
13 #include <sys/stat.h> /* fchmod */
14
15 static const char *o_id;
16 static const char *o_dir;
17 static int o_dot_as_home;
18 static int o_env=0;
19
20 static uogetopt2 myopts[]={
21 {'.',"dot-as-home",uogo_flag,UOGO_NOARG,&o_dot_as_home, 1 ,
22 "Use current directory instead of $HOME.",0,0},
23 {'d',"dir",uogo_string,0,&o_dir, 0 ,
24 "Jobdirectory.",
25 "Jobs will be read from this directory.","DIR"},
26 {'e',"copy-environment",uogo_flag,UOGO_NOARG,&o_env, 1 ,
27 "Clone current environment for job.",
28 "The default is to start new jobs in the daemons environment. This option "
29 "causes the current environment to be copied for the new process.",0},
30 {'i',"id",uogo_string,0,&o_id, 0 ,
31 "Unique ID for the new job.",
32 "An identifier must not be re-used and must not contain colons, slashes and "
33 "dots. If this option is not used then a unique ID will be given.", "ID"},
34 {0,0,0,0,0,0,0,0,0}
35 };
36 static void die_write(void) attribute_noreturn;
37 static void die_write_temp(void) attribute_noreturn;
38 static void die_fsync(void) attribute_noreturn;
39 static void die_fchmod(void) attribute_noreturn;
40
die_write(void)41 static void die_write(void) {xbailout(111,errno,"failed to write",0,0,0);}
die_write_temp(void)42 static void die_write_temp(void)
43 { xbailout(111,errno,"failed to write temporary file",0,0,0); }
die_fsync(void)44 static void die_fsync(void)
45 { xbailout(111,errno,"failed to fsync temporary file",0,0,0); }
die_fchmod(void)46 static void die_fchmod(void)
47 { xbailout(111,errno,"failed to fchmod temporary file",0,0,0); }
48
49 extern char **environ;
50 #define W(b,s,l) do { \
51 if (-1==buffer_put(b,s,l)) die_write_temp(); \
52 } while (0)
53
54 static void
copy_env(buffer * o)55 copy_env(buffer *o)
56 {
57 unsigned int i;
58 if (-1==buffer_puts(o,"env - \\\n")) die_write_temp();
59 for (i=0;environ[i];i++) {
60 char *e=environ[i];
61 unsigned int j;
62 j=str_chr(e,'=');
63 if (!e[j])
64 continue;
65 W(o,e,j+1);
66 W(o,"'",1);
67 j++;
68 while (e[j]) {
69 if (e[j]=='\'')
70 W(o,"'\\'",3);
71 W(o,e+j,1);
72 j++;
73 }
74 W(o,"' \\\n",4);
75 }
76 }
77
78
79 static void
create_job(int fd,char ** args)80 create_job(int fd, char **args)
81 {
82 buffer i;
83 char ispace[512];
84 buffer o;
85 char ospace[512];
86
87 buffer_init(&o,(buffer_op) write,fd,ospace,sizeof(ospace));
88 if (-1==buffer_puts(&o,"#! /bin/sh\n")) die_write_temp();
89 if (o_env) {
90 static stralloc fn;
91 if (!stralloc_copys(&fn,o_id)) oom();
92 if (!stralloc_cats(&fn,".run")) oom();
93 if (!stralloc_0(&fn)) oom();
94
95 if (-1==buffer_puts(&o,"exec \\\n")) die_write_temp();
96 copy_env(&o);
97 if (-1==buffer_puts(&o,"/bin/sh -c ")) die_write_temp();
98 if (-1==buffer_puts(&o,"\"$SCHEDULED_COMMAND_FILE\"/'"))
99 die_write_temp();
100 if (-1==buffer_puts(&o,fn.s)) die_write_temp();
101 if (-1==buffer_puts(&o,"'\n")) die_write_temp();
102 if (-1==buffer_flush(&o)) die_write_temp();
103 if (-1==fchmod(fd,0755)) die_fchmod();
104 if (-1==fsync(fd)) die_fsync();
105 if (-1==close(fd)) die_write_temp();
106 fd=open_excl(fn.s);
107 if (fd==-1)
108 xbailout(111,errno,"failed to open_excl ",fn.s,0,0);
109 buffer_init(&o,(buffer_op) write,fd,ospace,sizeof(ospace));
110 if (-1==buffer_puts(&o,"#! /bin/sh\n")) die_write_temp();
111 }
112
113 if (args) {
114 unsigned int j;
115 const char *spc="";
116 for (j=0;args[j];j++) {
117 if (-1==buffer_puts(&o,spc)) die_write_temp();
118 if (-1==buffer_puts(&o,args[j])) die_write_temp();
119 spc=" ";
120 }
121 } else {
122 buffer_init(&i,(buffer_op) read,0,ispace,sizeof(ispace));
123 switch (buffer_copy(&o,&i)) {
124 case 0: break;
125 case -2: xbailout(111,errno,"failed to read input",0,0,0);
126 case -3: die_write_temp();
127 default: xbailout(100,errno,"unexpected errorcode from buffer_copy",0,0,0);
128 }
129 }
130 if (-1==buffer_puts(&o,"\n")) die_write_temp();
131 if (-1==buffer_flush(&o)) die_write_temp();
132 if (-1==fchmod(fd,0755)) die_fchmod();
133 if (-1==fsync(fd)) die_fsync();
134 if (-1==close(fd)) die_write_temp();
135 }
136 static uogetopt_env myoptenv={
137 "uschedulecmd",PACKAGE,VERSION,
138 "uschedulecmd [options] [COMMAND ...]",
139 "This program creates a schedule command executing COMMAND or, if that is "
140 "not given, a command read from the standard input.",
141 "long",
142 "Report bugs to uschedule@lists.ohse.de",
143 0,0,0,0,uogetopt_out,myopts
144 };
145
146
main(int argc,char ** argv)147 int main(int argc, char **argv)
148 {
149 int fd=-1; /* keep gcc quiet */
150 int prt=0;
151
152 bailout_progname(argv[0]);
153 flag_bailout_fatal_begin=3;
154 uogo_posixmode=1;
155 myoptenv.program=flag_bailout_log_name;
156 uogetopt_parse(&myoptenv,&argc,argv);
157
158 change_dir(0,o_dir,o_dot_as_home);
159 if (-1==chdir(IDDIR))
160 xbailout(111,errno,"failed to chdir to ",IDDIR, " directory",0);
161
162 if (!o_id) {
163 static stralloc sat;
164 fd=make_id(&sat);
165 o_id=sat.s;
166 prt=1;
167 } else {
168 check_id(o_id);
169 fd=open_excl(o_id);
170 if (-1==fd)
171 xbailout(111,errno,"failed to open_excl ",o_id,0,0);
172 }
173
174 create_job(fd,argv[1] ? argv+1 : 0);
175 if (prt) {
176 if (-1==buffer_puts(buffer_1,"The id of the new job is ")) die_write();
177 if (-1==buffer_puts(buffer_1,o_id)) die_write();
178 if (-1==buffer_puts(buffer_1,"\n")) die_write();
179 if (-1==buffer_flush(buffer_1)) die_write();
180 }
181 return 0;
182 }
183