author | viric@llimona |
Sun, 25 Mar 2007 23:37:42 +0200 | |
changeset 46 | 620319858e9a |
parent 44 | 4dcf05746ece |
child 48 | 630e26b09141 |
permissions | -rw-r--r-- |
1 | 1 |
#include <unistd.h> |
11
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
2 |
#include <assert.h> |
44 | 3 |
#include <stdlib.h> |
4 |
#include <string.h> |
|
1 | 5 |
|
6 |
#include <stdio.h> |
|
7 |
||
3 | 8 |
#include "main.h" |
9 |
||
1 | 10 |
extern char *optarg; |
11 |
extern int optind, opterr, optopt; |
|
12 |
||
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
13 |
/* Globals */ |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
14 |
struct Command_line command_line; |
1 | 15 |
int server_socket; |
16 |
||
18 | 17 |
/* Allocated in get_command() */ |
18 |
char *new_command; |
|
19 |
||
46 | 20 |
static char version[] = "Task Spooler v0.2.1"; |
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
21 |
|
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
22 |
static void default_command_line() |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
23 |
{ |
36 | 24 |
command_line.request = c_LIST; |
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
25 |
command_line.need_server = 0; |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
26 |
command_line.store_output = 1; |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
27 |
command_line.should_go_background = 1; |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
28 |
} |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
29 |
|
18 | 30 |
void get_command(int index, int argc, char **argv) |
31 |
{ |
|
32 |
int size; |
|
33 |
int i; |
|
34 |
||
35 |
size = 0; |
|
36 |
/* Count bytes needed */ |
|
37 |
for (i = index; i < argc; ++i) |
|
38 |
{ |
|
39 |
/* The '1' is for spaces, and at the last i, |
|
40 |
* for the null character */ |
|
41 |
size = size + strlen(argv[i]) + 1; |
|
42 |
} |
|
43 |
||
44 |
/* Alloc */ |
|
40 | 45 |
new_command = (char *) malloc(size); |
18 | 46 |
assert(new_command != NULL); |
47 |
||
48 |
/* Build the command */ |
|
49 |
strcpy(new_command, argv[index]); |
|
50 |
for (i = index+1; i < argc; ++i) |
|
51 |
{ |
|
52 |
strcat(new_command, " "); |
|
53 |
strcat(new_command, argv[i]); |
|
54 |
} |
|
55 |
} |
|
3 | 56 |
|
1 | 57 |
void parse_opts(int argc, char **argv) |
58 |
{ |
|
2 | 59 |
int c; |
1 | 60 |
|
2 | 61 |
/* Parse options */ |
62 |
while(1) { |
|
42 | 63 |
c = getopt(argc, argv, ":VhKClnfr:t:c:o:p:w:"); |
1 | 64 |
|
2 | 65 |
if (c == -1) |
66 |
break; |
|
1 | 67 |
|
2 | 68 |
switch(c) |
69 |
{ |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
70 |
case 'K': |
31 | 71 |
command_line.request = c_KILL_SERVER; |
2 | 72 |
break; |
3 | 73 |
case 'l': |
31 | 74 |
command_line.request = c_LIST; |
3 | 75 |
break; |
36 | 76 |
case 'h': |
77 |
command_line.request = c_SHOW_HELP; |
|
78 |
break; |
|
37 | 79 |
case 'V': |
80 |
command_line.request = c_SHOW_VERSION; |
|
81 |
break; |
|
33 | 82 |
case 'C': |
83 |
command_line.request = c_CLEAR_FINISHED; |
|
84 |
break; |
|
20
d85b4c0745fa
"-c" added, for clearing the finished tasks' list.
viric@llimona
parents:
18
diff
changeset
|
85 |
case 'c': |
33 | 86 |
command_line.request = c_CAT; |
87 |
command_line.jobid = atoi(optarg); |
|
88 |
break; |
|
89 |
case 'o': |
|
90 |
command_line.request = c_SHOW_OUTPUT_FILE; |
|
91 |
command_line.jobid = atoi(optarg); |
|
20
d85b4c0745fa
"-c" added, for clearing the finished tasks' list.
viric@llimona
parents:
18
diff
changeset
|
92 |
break; |
22 | 93 |
case 'n': |
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
94 |
command_line.store_output = 0; |
22 | 95 |
break; |
31 | 96 |
case 'f': |
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
97 |
command_line.should_go_background = 0; |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
98 |
break; |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
99 |
case 't': |
31 | 100 |
command_line.request = c_TAIL; |
32 | 101 |
command_line.jobid = atoi(optarg); |
29
ca47653a4cbc
Add an option for electing not to go into background.
viric@llimona
parents:
27
diff
changeset
|
102 |
break; |
35 | 103 |
case 'p': |
104 |
command_line.request = c_SHOW_PID; |
|
105 |
command_line.jobid = atoi(optarg); |
|
106 |
break; |
|
41 | 107 |
case 'r': |
108 |
command_line.request = c_REMOVEJOB; |
|
109 |
command_line.jobid = atoi(optarg); |
|
110 |
break; |
|
42 | 111 |
case 'w': |
112 |
command_line.request = c_WAITJOB; |
|
113 |
command_line.jobid = atoi(optarg); |
|
114 |
break; |
|
31 | 115 |
case ':': |
116 |
switch(optopt) |
|
117 |
{ |
|
118 |
case 't': |
|
32 | 119 |
command_line.request = c_TAIL; |
31 | 120 |
command_line.jobid = -1; /* This means the 'last' job */ |
121 |
break; |
|
33 | 122 |
case 'c': |
123 |
command_line.request = c_CAT; |
|
124 |
command_line.jobid = -1; /* This means the 'last' job */ |
|
125 |
break; |
|
126 |
case 'o': |
|
127 |
command_line.request = c_SHOW_OUTPUT_FILE; |
|
128 |
command_line.jobid = -1; /* This means the 'last' job */ |
|
129 |
break; |
|
35 | 130 |
case 'p': |
131 |
command_line.request = c_SHOW_PID; |
|
132 |
command_line.jobid = -1; /* This means the 'last' job */ |
|
133 |
break; |
|
41 | 134 |
case 'r': |
135 |
command_line.request = c_REMOVEJOB; |
|
136 |
command_line.jobid = -1; /* This means the 'last' |
|
137 |
added job */ |
|
138 |
break; |
|
42 | 139 |
case 'w': |
140 |
command_line.request = c_WAITJOB; |
|
141 |
command_line.jobid = -1; /* This means the 'last' |
|
142 |
added job */ |
|
143 |
break; |
|
31 | 144 |
default: |
145 |
fprintf(stderr, "Option %c missing argument: %s\n", |
|
146 |
optopt, optarg); |
|
147 |
exit(-1); |
|
148 |
} |
|
149 |
break; |
|
150 |
case '?': |
|
151 |
fprintf(stderr, "Wrong option %c.\n", optopt); |
|
152 |
exit(-1); |
|
2 | 153 |
} |
154 |
} |
|
1 | 155 |
|
18 | 156 |
new_command = 0; |
157 |
||
37 | 158 |
/* if the request is still the default option... |
159 |
* (the default values should be centralized) */ |
|
160 |
if (optind < argc && command_line.request == c_LIST) |
|
31 | 161 |
{ |
162 |
command_line.request = c_QUEUE; |
|
18 | 163 |
get_command(optind, argc, argv); |
31 | 164 |
} |
3 | 165 |
|
37 | 166 |
if (command_line.request != c_SHOW_HELP && |
167 |
command_line.request != c_SHOW_VERSION) |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
168 |
command_line.need_server = 1; |
1 | 169 |
} |
170 |
||
44 | 171 |
static void go_background() |
11
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
172 |
{ |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
173 |
int pid; |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
174 |
pid = fork(); |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
175 |
|
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
176 |
switch(pid) |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
177 |
{ |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
178 |
case -1: |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
179 |
perror("fork failed"); |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
180 |
exit(-1); |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
181 |
break; |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
182 |
case 0: |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
183 |
break; |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
184 |
default: |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
185 |
exit(0); |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
186 |
} |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
187 |
} |
bb94b9890001
Going to background at for new command queued.
lbatlle@npdl268.bpo.hp.com
parents:
8
diff
changeset
|
188 |
|
37 | 189 |
static void print_help(const char *cmd) |
36 | 190 |
{ |
42 | 191 |
printf("usage: %s < -K | -C | -l | -t [id] | -c [id] | -p [id] | -r [id] >\n" |
192 |
" [-n] [ -f ] [cmd...]\n", cmd); |
|
36 | 193 |
printf(" -K kill the task spooler server\n"); |
194 |
printf(" -C clear the list of finished jobs\n"); |
|
195 |
printf(" -l show the job list (default action)\n"); |
|
196 |
printf(" -t [id] tail -f the output of the job. Last if not specified.\n"); |
|
197 |
printf(" -c [id] cat the output of the job. Last if not specified.\n"); |
|
198 |
printf(" -p [id] show the pid of the job. Last if not specified.\n"); |
|
42 | 199 |
printf(" -r [id] remove a job. The last added, if not specified.\n"); |
200 |
printf(" -w [id] wait for a job. The last added, if not specified.\n"); |
|
37 | 201 |
printf(" -h show this help\n"); |
202 |
printf(" -V show the program version\n"); |
|
36 | 203 |
printf("Adding jobs:\n"); |
204 |
printf(" -n don't store the output of the command.\n"); |
|
205 |
printf(" -f don't fork into background.\n"); |
|
206 |
} |
|
207 |
||
37 | 208 |
static void print_version() |
209 |
{ |
|
210 |
puts(version); |
|
44 | 211 |
} |
37 | 212 |
|
1 | 213 |
int main(int argc, char **argv) |
214 |
{ |
|
38
768d009604b3
The program returns the errorlevel of the job, if it doesn't go to background.
viric@llimona
parents:
37
diff
changeset
|
215 |
int errorlevel = 0; |
41 | 216 |
|
217 |
/* This is needed in a gnu system, so getopt works well */ |
|
218 |
setenv("POSIXLY_CORRECT", "YES", 1); |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
219 |
default_command_line(); |
2 | 220 |
parse_opts(argc, argv); |
1 | 221 |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
222 |
if (command_line.need_server) |
3 | 223 |
ensure_server_up(); |
224 |
||
31 | 225 |
switch(command_line.request) |
3 | 226 |
{ |
37 | 227 |
case c_SHOW_VERSION: |
228 |
print_version(argv[0]); |
|
229 |
break; |
|
36 | 230 |
case c_SHOW_HELP: |
231 |
print_help(argv[0]); |
|
37 | 232 |
break; |
31 | 233 |
case c_QUEUE: |
234 |
assert(new_command != 0); |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
235 |
if (command_line.should_go_background) |
29
ca47653a4cbc
Add an option for electing not to go into background.
viric@llimona
parents:
27
diff
changeset
|
236 |
go_background(); |
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
237 |
assert(command_line.need_server); |
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
238 |
c_new_job(new_command); |
38
768d009604b3
The program returns the errorlevel of the job, if it doesn't go to background.
viric@llimona
parents:
37
diff
changeset
|
239 |
if (!command_line.should_go_background) |
768d009604b3
The program returns the errorlevel of the job, if it doesn't go to background.
viric@llimona
parents:
37
diff
changeset
|
240 |
errorlevel = c_wait_server_commands(new_command); |
768d009604b3
The program returns the errorlevel of the job, if it doesn't go to background.
viric@llimona
parents:
37
diff
changeset
|
241 |
else |
768d009604b3
The program returns the errorlevel of the job, if it doesn't go to background.
viric@llimona
parents:
37
diff
changeset
|
242 |
c_wait_server_commands(new_command); |
18 | 243 |
free(new_command); |
31 | 244 |
break; |
245 |
case c_LIST: |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
246 |
assert(command_line.need_server); |
8 | 247 |
c_list_jobs(); |
5 | 248 |
c_wait_server_lines(); |
31 | 249 |
break; |
250 |
case c_KILL_SERVER: |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
251 |
assert(command_line.need_server); |
3 | 252 |
c_shutdown_server(); |
31 | 253 |
break; |
254 |
case c_CLEAR_FINISHED: |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
255 |
assert(command_line.need_server); |
20
d85b4c0745fa
"-c" added, for clearing the finished tasks' list.
viric@llimona
parents:
18
diff
changeset
|
256 |
c_clear_finished(); |
31 | 257 |
break; |
32 | 258 |
case c_TAIL: |
259 |
assert(command_line.need_server); |
|
260 |
c_tail(); |
|
261 |
/* This will not return! */ |
|
262 |
break; |
|
33 | 263 |
case c_CAT: |
264 |
assert(command_line.need_server); |
|
265 |
c_cat(); |
|
266 |
/* This will not return! */ |
|
267 |
break; |
|
268 |
case c_SHOW_OUTPUT_FILE: |
|
269 |
assert(command_line.need_server); |
|
270 |
c_show_output_file(); |
|
271 |
break; |
|
35 | 272 |
case c_SHOW_PID: |
273 |
assert(command_line.need_server); |
|
274 |
c_show_pid(); |
|
275 |
break; |
|
41 | 276 |
case c_REMOVEJOB: |
277 |
assert(command_line.need_server); |
|
278 |
c_remove_job(); |
|
279 |
break; |
|
42 | 280 |
case c_WAITJOB: |
281 |
assert(command_line.need_server); |
|
282 |
c_wait_job(); |
|
283 |
break; |
|
20
d85b4c0745fa
"-c" added, for clearing the finished tasks' list.
viric@llimona
parents:
18
diff
changeset
|
284 |
} |
d85b4c0745fa
"-c" added, for clearing the finished tasks' list.
viric@llimona
parents:
18
diff
changeset
|
285 |
|
30
ab88478a7e9b
The commandline parameters are centered in a struct.
viric@llimona
parents:
29
diff
changeset
|
286 |
if (command_line.need_server) |
2 | 287 |
{ |
3 | 288 |
close(server_socket); |
2 | 289 |
} |
1 | 290 |
|
38
768d009604b3
The program returns the errorlevel of the job, if it doesn't go to background.
viric@llimona
parents:
37
diff
changeset
|
291 |
return errorlevel; |
1 | 292 |
} |