2 Copyright © 2012, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <proto/exec.h>
10 #include <proto/dos.h>
20 #define ARG_TEMPLATE "FILENAME,PROFILE/K,NOGUI/S,ARGUMENTS/F"
21 #define CMD_TMPLATE_SIZE (2000)
35 static void clean_exit(struct Req
*req
, CONST_STRPTR s
)
37 LONG retval
= RETURN_OK
;
46 if (req
->rda
) FreeArgs(req
->rda
);
53 static struct Req
*alloc_req(void)
55 return AllocPooled(poolmem
, sizeof (struct Req
));
58 static BOOL
handle_args(struct Req
*req
, int argc
, char **argv
)
62 IPTR args
[ARG_COUNT
] = {(IPTR
)"R", 0, 0, 0};
64 req
->rda
= ReadArgs(ARG_TEMPLATE
, args
, NULL
);
67 PrintFault(IoErr(), argv
[0]);
71 req
->filename
= (STRPTR
)args
[ARG_FILENAME
];
72 req
->profile
= (STRPTR
)args
[ARG_PROFILE
];
73 req
->nogui
= args
[ARG_NOGUI
] ? TRUE
: FALSE
;
74 req
->arguments
= (STRPTR
)args
[ARG_ARGUMENTS
];
79 // FIXME: it should be possible to use R as default tool
86 // return TRUE if name exists and is not a directory
87 static BOOL
is_file(CONST_STRPTR name
)
93 struct FileInfoBlock
*fib
= AllocDosObject(DOS_FIB
, NULL
);
96 BPTR lock
= Lock(name
, SHARED_LOCK
);
99 if (Examine(lock
, fib
))
101 if (fib
->fib_DirEntryType
< 0)
108 FreeDosObject(DOS_FIB
, fib
);
115 // search for the command. It must
116 // be an absolute path, exist in the current directory
118 static BOOL
check_exist(struct Req
*req
)
122 if (req
->filename
== NULL
)
125 if (strchr(req
->filename
, ':')) // absolute path
127 if (is_file(req
->filename
))
129 D(bug("[R] command found by absolute path\n"));
133 else if (strchr(req
->filename
, '/') == NULL
) // not in a sub-dir
135 if (is_file(req
->filename
)) // in current directory
137 D(bug("[R] command found in current directory\n"));
142 BPTR lock
= Lock("C:", SHARED_LOCK
);
145 BPTR olddir
= CurrentDir(lock
);
146 if (is_file(req
->filename
))
148 D(bug("[R] command found in C:\n"));
162 // execute the command with "?" option and read the command template
163 static BOOL
get_template(struct Req
*req
)
167 BPTR input_fh
= BNULL
;
168 BPTR output_fh
= BNULL
;
170 TEXT out_file_name
[30];
171 TEXT in_file_name
[30];
176 __unused LONG cmd_res
= 0;
178 if (req
->filename
== NULL
)
183 cmd_len
= strlen(req
->filename
) + 20;
184 cmd
= AllocPooled(poolmem
, cmd_len
);
190 for (i
= 0; i
< 20 && output_fh
== BNULL
; i
++)
192 sprintf(out_file_name
, "t:%08u.request.outfile", (unsigned int)i
);
193 output_fh
= Open(out_file_name
, MODE_NEWFILE
);
195 if (output_fh
== BNULL
)
200 for (i
= 0; i
< 20 && input_fh
== BNULL
; i
++)
202 sprintf(in_file_name
, "t:%08u.request.infile", (unsigned int)i
);
203 input_fh
= Open(in_file_name
, MODE_NEWFILE
);
205 if (input_fh
== BNULL
)
210 input_fh
= Open(in_file_name
, MODE_OLDFILE
);
211 if (input_fh
== BNULL
)
216 // append "= ?" to the command to make ReadArgs fail so
217 // that the command prints the template and stops
218 strlcpy(cmd
, req
->filename
, cmd_len
);
219 strlcat(cmd
, " = ?", cmd_len
);
221 // shut up DOS error message
222 struct Process
*me
= (struct Process
*)FindTask(NULL
);
223 APTR oldwin
= me
->pr_WindowPtr
;
224 me
->pr_WindowPtr
= (APTR
)-1;
226 // Execute the command
227 cmd_res
= Execute(cmd
, input_fh
, output_fh
);
228 D(bug("[R] Execute() returned: %d\n", cmd_res
));
230 // restore window ptr
231 me
->pr_WindowPtr
= oldwin
;
233 req
->cmd_template
= AllocPooled(poolmem
, CMD_TMPLATE_SIZE
); // FIXME get mem size from file size
234 if (req
->cmd_template
== NULL
)
239 // go to the beginning of the output file and read the template
240 Seek(output_fh
, 0, OFFSET_BEGINNING
);
241 if (FGets(output_fh
, req
->cmd_template
, CMD_TMPLATE_SIZE
))
243 D(bug("[R] template read: %s\n", req
->cmd_template
));
251 DeleteFile(in_file_name
);
256 DeleteFile(out_file_name
);
259 FreePooled(poolmem
, cmd
, cmd_len
);
265 static BOOL
parse_template(struct Req
*req
)
271 if (req
->cmd_template
[0] == '\0')
274 // count number of arguments
277 req
->arg_cnt
= 1, chr
= req
->cmd_template
;
278 *chr
!= '\0' && req
->arg_cnt
< 50;
288 D(bug("[R/parse_template] args found %d\n", req
->arg_cnt
));
290 req
->cargs
= AllocPooled(poolmem
, sizeof (struct CArg
) * req
->arg_cnt
);
291 if (req
->cargs
== NULL
)
298 arg
= 0, chr
= req
->cmd_template
;
304 TEXT
*name_start
= chr
;
312 else if (*chr
== '=')
314 // we are only interested in the part after the "=".
322 len
= chr
- name_start
;
329 req
->cargs
[arg
].argname
= AllocPooled(poolmem
, len
+ 1);
330 if (req
->cargs
[arg
].argname
== NULL
)
334 memcpy(req
->cargs
[arg
].argname
, name_start
, len
);
335 req
->cargs
[arg
].argname
[len
] = '\0';
343 req
->cargs
[arg
].a_flag
= TRUE
;
347 req
->cargs
[arg
].f_flag
= TRUE
;
351 req
->cargs
[arg
].k_flag
= TRUE
;
355 req
->cargs
[arg
].m_flag
= TRUE
;
359 req
->cargs
[arg
].n_flag
= TRUE
;
363 req
->cargs
[arg
].s_flag
= TRUE
;
367 req
->cargs
[arg
].t_flag
= TRUE
;
384 // create the command line from the selected options
385 static void execute_command(struct Req
*req
)
391 ULONG cmd_size
= strlen(req
->filename
) + 5;
392 for (i
= 0; i
< req
->arg_cnt
; i
++)
394 cmd_size
+= strlen(req
->cargs
[i
].argname
) + 5;
395 if (!req
->cargs
[i
].s_flag
&& !req
->cargs
[i
].t_flag
)
397 cmd_size
+= strlen(get_gui_string(&req
->cargs
[i
])) + 5;
401 cmd
= AllocPooled(poolmem
, cmd_size
);
407 strcpy(cmd
, req
->filename
);
409 for (i
= 0; i
< req
->arg_cnt
; i
++)
411 if (req
->cargs
[i
].s_flag
|| req
->cargs
[i
].t_flag
)
413 if (get_gui_bool(&req
->cargs
[i
]))
416 strcat(cmd
, req
->cargs
[i
].argname
);
419 else if (req
->cargs
[i
].n_flag
)
421 str
= get_gui_string(&req
->cargs
[i
]);
425 strcat(cmd
, req
->cargs
[i
].argname
);
433 str
= get_gui_string(&req
->cargs
[i
]);
436 // do we have a space character in the string?
438 // For /M the quotes are already set by the GUI
439 if (!req
->cargs
[i
].m_flag
&& strchr(str
, ' ') && str
[0] != '\"')
444 strcat(cmd
, req
->cargs
[i
].argname
);
459 D(bug("[R] executing command %s\n", cmd
));
467 Printf(_(MSG_ERROR_RETURN
), req
->filename
, result
);
472 int main(int argc
, char **argv
)
474 poolmem
= CreatePool(MEMF_ANY
| MEMF_CLEAR
, 2000, 2000);
476 clean_exit(NULL
, _(MSG_ERROR_POOL
));
478 struct Req
*req
= alloc_req();
480 clean_exit(req
, _(MSG_ERROR_STRUCT
));
482 D(bug("[R/main] req %p\n", req
));
484 if (! handle_args(req
, argc
, argv
))
485 clean_exit(req
, _(MSG_ERROR_ARGS
));
487 if (! check_exist(req
))
488 clean_exit(req
, _(MSG_ERROR_NOTFOUND
));
490 if (! get_template(req
))
491 clean_exit(req
, _(MSG_ERROR_TMPLT_GET
));
493 if (! parse_template(req
))
494 clean_exit(req
, _(MSG_ERROR_TMPLT_PARSE
));
496 if (! create_gui(req
))
497 clean_exit(req
, _(MSG_ERROR_GUI
));
499 if (! set_defaults(req
))
500 clean_exit(req
, _(MSG_ERROR_DEFAULTS
));
504 execute_command(req
);
507 clean_exit(req
, NULL
);