and proc_set_variable (name, value) =
if !debug then Syslog.notice "remote call: set_variable %s" name;
- let value = variable_of_rpc value in
- variables := StringMap.add name value !variables;
+ try
+ (* Don't permit certain names. *)
+ if name = "JOBSERIAL" then
+ failwith "JOBSERIAL variable cannot be set";
+
+ let len = String.length name in
+ if len = 0 then
+ failwith "variable name is an empty string";
+ if name.[0] <> '_' && not (isalpha name.[0]) then
+ failwith "variable name must start with alphabetic character or underscore";
+
+ let rec loop i =
+ if i >= len then ()
+ else if name.[i] <> '_' && not (isalnum name.[i]) then
+ failwith "variable name contains non-alphanumeric non-underscore character"
+ else loop (i+1)
+ in
+ loop 1;
+
+ let value = variable_of_rpc value in
+ variables := StringMap.add name value !variables;
+
+ (* Which jobs need to be re-evaluated? *)
+ let jobnames = try StringMap.find name !dependencies with Not_found -> [] in
+ reevaluate_whenjobs jobnames;
- (* Which jobs need to be re-evaluated? *)
- let jobnames = try StringMap.find name !dependencies with Not_found -> [] in
- reevaluate_whenjobs jobnames
+ `ok
+ with
+ Failure msg -> `error msg
and proc_get_variable name =
if !debug then Syslog.notice "remote call: get_variable %s" name;
program When {
version V1 {
status reload_file (void) = 1;
- void set_variable (variable_name, variable) = 2;
+ status set_variable (variable_name, variable) = 2;
variable get_variable (variable_name) = 3;
variable_name_list get_variable_names (void) = 4;
status exit_daemon (void) = 5;
let (//) = Filename.concat
+let isalpha = function 'a'..'z' | 'A'..'Z' -> true | _ -> false
+let isalnum = function 'a'..'z' | 'A'..'Z' | '0'..'9' -> true | _ -> false
+
let rec filter_map f = function
| [] -> []
| x :: xs ->
val (//) : string -> string -> string
(** [dir // file] concatenates directory and file. *)
+val isalpha : char -> bool
+val isalnum : char -> bool
+(** Character tests. *)
+
val filter_map : ('a -> 'b option) -> 'a list -> 'b list
(** Filter + map. *)
) in
let client = start_client () in
- Whenproto_clnt.When.V1.set_variable client (name, value);
+ (match Whenproto_clnt.When.V1.set_variable client (name, value) with
+ | `ok -> ()
+ | `error msg ->
+ eprintf "whenjobs: set: %s\n" msg;
+ suggest_check_server_logs ();
+ exit 1
+ );
stop_client client
and get_variable name =