[Omake] patch to add getpwnam, getpwuid, getgrnam, getgrgid

Erick Tryzelaar erickt at dslextreme.com
Sat Feb 3 17:06:29 PST 2007


Hello again,

In my attempts to add an install function, I noticed that there's no 
support for querying the unix passwd and group database, so I added it 
:) This is a little bigger than just lifting a unix function into omake 
as I noticed an opportunity to refactor a small amount of code. I 
noticed that there was a couple places that had this code block in the 
function:

let obj =
   try
      match venv_find_var_exn venv ScopeGlobal pipe_object_sym with
         ValObject obj ->
            obj
       | _ ->
            venv_empty_object
   with
      Not_found ->
         venv_empty_object
in

I've replaced this with a function in src/env/omake_env.ml called 
venv_find_object_or_empty that does this. I'm not sure if that's the 
best name though. The other questionable thing is where to put it in 
Pervasives.om. I put it in Shell, but perhaps it would be better 
somewhere else. Another is that I don't think these functions are 
reentrant, so should a mutex be used to protect these functions? 
Finally, it's not windows compatible.

-e

-------------- next part --------------
Index: src/env/omake_env.mli
===================================================================
--- src/env/omake_env.mli	(revision 9985)
+++ src/env/omake_env.mli	(working copy)
@@ -398,6 +398,7 @@
 val venv_get_var      : venv -> scope_kind -> pos -> var -> value
 val venv_find_var     : venv -> scope_kind -> pos -> loc -> var -> value
 val venv_find_var_exn : venv -> scope_kind -> var -> value
+val venv_find_object_or_empty : venv -> scope_kind -> symbol -> obj
 
 (*
  * Static environments.
Index: src/env/omake_env.ml
===================================================================
--- src/env/omake_env.ml	(revision 9985)
+++ src/env/omake_env.ml	(working copy)
@@ -2168,6 +2168,17 @@
 let venv_defined venv scope v =
    List.exists (fun env -> SymbolTable.mem env v) (venv_current_objects venv scope)
 
+let venv_find_object_or_empty venv scope symbol =
+   try
+      match venv_find_var_exn venv scope symbol with
+         ValObject obj ->
+            obj
+       | _ ->
+            venv_empty_object
+   with
+      Not_found ->
+         venv_empty_object
+
 (*
  * Adding to variable environment.
  * Add to the current object and the static scope.
Index: src/builtin/omake_builtin_object.ml
===================================================================
--- src/builtin/omake_builtin_object.ml	(revision 9985)
+++ src/builtin/omake_builtin_object.ml	(working copy)
@@ -767,6 +767,8 @@
        "Select";
        "Pipe";
        "Stat";
+       "Passwd";
+       "Group";
        "Shell";
        "Lexer";
        "Parser";
Index: src/builtin/omake_builtin_io.ml
===================================================================
--- src/builtin/omake_builtin_io.ml	(revision 9985)
+++ src/builtin/omake_builtin_io.ml	(working copy)
@@ -720,17 +720,7 @@
             let write = Lm_channel.create "<writepipe>" Lm_channel.PipeChannel OutChannel false (Some fd_write) in
             let fd_read = ValChannel (InChannel, venv_add_channel venv read) in
             let fd_write = ValChannel (OutChannel, venv_add_channel venv write) in
-            let obj =
-               try
-                  match venv_find_var_exn venv ScopeGlobal pipe_object_sym with
-                     ValObject obj ->
-                        obj
-                   | _ ->
-                        venv_empty_object
-               with
-                  Not_found ->
-                     venv_empty_object
-            in
+            let obj = venv_find_object_or_empty venv ScopeGlobal pipe_object_sym in
             let obj = venv_add_field obj read_sym fd_read in
             let obj = venv_add_field obj write_sym fd_write in
                ValObject obj
@@ -823,17 +813,7 @@
             let rfd = reintern_channel rfd in
             let wfd = reintern_channel wfd in
             let efd = reintern_channel efd in
-            let obj =
-               try
-                  match venv_find_var_exn venv ScopeGlobal select_object_sym with
-                     ValObject obj ->
-                        obj
-                   | _ ->
-                        venv_empty_object
-               with
-                  Not_found ->
-                     venv_empty_object
-            in
+            let obj = venv_find_object_or_empty venv ScopeGlobal select_object_sym in
             let obj = venv_add_field obj read_sym  (ValArray rfd) in
             let obj = venv_add_field obj write_sym (ValArray wfd) in
             let obj = venv_add_field obj error_sym (ValArray efd) in
Index: src/builtin/omake_builtin_base.ml
===================================================================
--- src/builtin/omake_builtin_base.ml	(revision 9985)
+++ src/builtin/omake_builtin_base.ml	(working copy)
@@ -511,17 +511,7 @@
       pp_print_exn stdstr exp;
       flush_stdstr ()
    in
-   let obj =
-      try
-         match venv_find_var_exn venv ScopeGlobal runtime_exception_sym with
-            ValObject obj ->
-               obj
-          | _ ->
-               venv_empty_object
-      with
-         Not_found ->
-            venv_empty_object
-   in
+   let obj = venv_find_object_or_empty venv ScopeGlobal runtime_exception_sym in
    let obj = venv_add_field obj pos_sym (ValString pos) in
    let obj = venv_add_field obj message_sym (ValString exp) in
    let obj = venv_add_class obj runtime_exception_sym in
@@ -536,17 +526,7 @@
       pp_print_pos stdstr pos;
       flush_stdstr ()
    in
-   let obj =
-      try
-         match venv_find_var_exn venv ScopeGlobal runtime_exception_sym with
-            ValObject obj ->
-               obj
-          | _ ->
-               venv_empty_object
-      with
-         Not_found ->
-            venv_empty_object
-   in
+   let obj = venv_find_object_or_empty venv ScopeGlobal runtime_exception_sym in
    let obj = venv_add_field obj pos_sym (ValString pos) in
    let obj = venv_add_field obj message_sym (ValString (Printexc.to_string exn)) in
    let obj = venv_add_class obj runtime_exception_sym in
Index: src/builtin/omake_builtin_file.ml
===================================================================
--- src/builtin/omake_builtin_file.ml	(revision 9985)
+++ src/builtin/omake_builtin_file.ml	(working copy)
@@ -1755,17 +1755,7 @@
 
 let stat_aux stat_fun venv pos loc args =
    let pos = string_pos "stat" pos in
-   let obj =
-      try
-         match venv_find_var_exn venv ScopeGlobal stat_object_sym with
-            ValObject obj ->
-               obj
-          | _ ->
-               venv_empty_object
-      with
-         Not_found ->
-            venv_empty_object
-   in
+   let obj = venv_find_object_or_empty venv ScopeGlobal stat_object_sym in
       match args with
          [arg] ->
             let args = values_of_value venv pos arg in
@@ -1792,6 +1782,158 @@
       stat_aux Unix.LargeFile.lstat
 
 (************************************************************************
+ * Passwd database access.
+ *)
+
+(*
+ * \begin{doc}
+ * \fun{Passwd}
+ *
+ * The \verb+Passwd+ object represents the result returned by the 
+ * \verb+getpwnam+ and \verb+getpwuid+ functions. It contains the following
+ * fields.
+ *
+ * A \verb+passwd+ object has the following fields. Not all the fields
+ * will have meaning on all architectures.
+ *
+ * \begin{description}
+ * \item[pw_name]: the login name.
+ * \item[pw_passwd]: the encrypted password.
+ * \item[pw_uid]: user id of the user.
+ * \item[pw_gid]: group id of the user.
+ * \item[pw_gecos]: the user name or comment field.
+ * \item[pw_dir]: the user's home directory.
+ * \item[pw_shell]: the user's default shell.
+ * \end{description}
+ *
+ * \fun{getpwnam}
+ *
+ * \begin{verbatim}
+ *     $(getpwnam name...) : Passwd
+ *        name : String
+ *     $(getpwuid uid...) : Passwd
+ *        uid : Int
+ *     raises RuntimeException
+ * \end{verbatim}
+ * \end{doc}
+ *)
+
+let create_passwd_obj obj passwd =
+   let obj = venv_add_field obj pw_name_sym   (ValString passwd.Unix.pw_name) in
+   let obj = venv_add_field obj pw_passwd_sym (ValString passwd.Unix.pw_passwd) in
+   let obj = venv_add_field obj pw_uid_sym    (ValInt    passwd.Unix.pw_uid) in
+   let obj = venv_add_field obj pw_gid_sym    (ValInt    passwd.Unix.pw_gid) in
+   let obj = venv_add_field obj pw_gecos_sym  (ValString passwd.Unix.pw_gecos) in
+   let obj = venv_add_field obj pw_dir_sym    (ValString passwd.Unix.pw_dir) in
+   let obj = venv_add_field obj pw_shell_sym  (ValString passwd.Unix.pw_shell) in
+      ValObject obj
+
+let getpwnam venv pos loc args =
+   let pos = string_pos "getpwnam" pos in
+   let obj = venv_find_object_or_empty venv ScopeGlobal passwd_object_sym in
+   let user = 
+      match args with
+         [user] -> string_of_value venv pos user
+       | _ ->
+            raise (OmakeException (loc_pos loc pos, ArityMismatch (ArityExact 1, List.length args)))
+   in
+   let passwd =
+      try Unix.getpwnam user with
+         Not_found ->
+            raise (OmakeException (loc_pos loc pos, StringStringError ("unknown user", user)))
+   in
+      create_passwd_obj obj passwd
+
+let getpwuid venv pos loc args =
+   let pos = string_pos "getpwuid" pos in
+   let obj = venv_find_object_or_empty venv ScopeGlobal passwd_object_sym in
+   let uid = 
+      match args with
+         [uid] -> int_of_value venv pos uid
+       | _ ->
+            raise (OmakeException (loc_pos loc pos, ArityMismatch (ArityExact 1, List.length args)))
+   in
+   let passwd =
+      try Unix.getpwuid uid with
+         Not_found ->
+            raise (OmakeException (loc_pos loc pos, StringIntError ("unknown uid", uid)))
+   in
+      create_passwd_obj obj passwd
+
+(************************************************************************
+ * Group database access.
+ *)
+
+(*
+ * \begin{doc}
+ * \fun{Group}
+ *
+ * The \verb+Group+ object represents the result returned by the 
+ * \verb+getgrnam+ and \verb+getgrgid+ functions. It contains the following
+ * fields.
+ *
+ * A \verb+group+ object has the following fields. Not all the fields
+ * will have meaning on all architectures.
+ *
+ * \begin{description}
+ * \item[pw_name]: the group name.
+ * \item[pw_group]: the encrypted password.
+ * \item[pw_gid]: group id of the group.
+ * \item[pw_mem]: the group member's user names.
+ * \end{description}
+ *
+ * \fun{getpwnam}
+ *
+ * \begin{verbatim}
+ *     $(getpwnam name...) : Group
+ *        name : String
+ *     $(getpwgid gid...) : Group
+ *        gid : Int
+ *     raises RuntimeException
+ * \end{verbatim}
+ * \end{doc}
+ *)
+let create_group_obj obj group =
+   let gr_mem = Array.fold_right (fun s x -> ValString s::x) group.Unix.gr_mem [] in
+   let obj = venv_add_field obj gr_name_sym   (ValString group.Unix.gr_name) in
+   let obj = venv_add_field obj gr_passwd_sym (ValString group.Unix.gr_passwd) in
+   let obj = venv_add_field obj gr_gid_sym    (ValInt    group.Unix.gr_gid) in
+   let obj = venv_add_field obj gr_mem_sym    (ValArray  gr_mem) in
+      ValObject obj
+
+let getgrnam venv pos loc args =
+   let pos = string_pos "getgrnam" pos in
+   let obj = venv_find_object_or_empty venv ScopeGlobal group_object_sym in
+   let user = 
+      match args with
+         [user] -> string_of_value venv pos user
+       | _ ->
+            raise (OmakeException (loc_pos loc pos, ArityMismatch (ArityExact 1, List.length args)))
+   in
+   let group =
+      try Unix.getgrnam user with
+         Not_found ->
+            raise (OmakeException (loc_pos loc pos, StringStringError ("unknown user", user)))
+   in
+      create_group_obj obj group
+
+let getgrgid venv pos loc args =
+   let pos = string_pos "getgruid" pos in
+   let obj = venv_find_object_or_empty venv ScopeGlobal group_object_sym in
+   let gid = 
+      match args with
+         [gid] -> int_of_value venv pos gid
+       | _ ->
+            raise (OmakeException (loc_pos loc pos, ArityMismatch (ArityExact 1, List.length args)))
+   in
+   let group =
+      try Unix.getgrgid gid with
+         Not_found ->
+            raise (OmakeException (loc_pos loc pos, StringIntError ("unknown gid", gid)))
+   in
+      create_group_obj obj group
+
+(************************************************************************
  * Links.
  *)
 
@@ -2765,6 +2907,10 @@
        true, "filter-proper-targets",   filter_proper_targets,    ArityExact 1;
        true, "stat",                    stat,                     ArityExact 1;
        true, "lstat",                   lstat,                    ArityExact 1;
+       true, "getpwnam",                getpwnam,                 ArityExact 1;
+       true, "getpwuid",                getpwuid,                 ArityExact 1;
+       true, "getgrnam",                getgrnam,                 ArityExact 1;
+       true, "getgrgid",                getgrgid,                 ArityExact 1;
        true, "unlink",                  unlink,                   ArityExact 1;
        true, "rename",                  rename,                   ArityExact 2;
        true, "readlink",                readlink,                 ArityExact 1;
Index: src/ir/omake_symbol.ml
===================================================================
--- src/ir/omake_symbol.ml	(revision 9985)
+++ src/ir/omake_symbol.ml	(working copy)
@@ -56,6 +56,8 @@
 let select_object_sym          = Lm_symbol.add "Select"
 let pipe_object_sym            = Lm_symbol.add "Pipe"
 let stat_object_sym            = Lm_symbol.add "Stat"
+let passwd_object_sym          = Lm_symbol.add "Passwd"
+let group_object_sym           = Lm_symbol.add "Group"
 let lexer_object_sym           = Lm_symbol.add "Lexer"
 let parser_object_sym          = Lm_symbol.add "Parser"
 let location_object_sym        = Lm_symbol.add "Location"
@@ -87,6 +89,19 @@
 let st_mtime_sym               = Lm_symbol.add "mtime"
 let st_ctime_sym               = Lm_symbol.add "ctime"
 
+let pw_name_sym                = Lm_symbol.add "pw_name"
+let pw_passwd_sym              = Lm_symbol.add "pw_passwd"
+let pw_uid_sym                 = Lm_symbol.add "pw_uid"
+let pw_gid_sym                 = Lm_symbol.add "pw_gid"
+let pw_gecos_sym               = Lm_symbol.add "pw_gecos"
+let pw_dir_sym                 = Lm_symbol.add "pw_dir"
+let pw_shell_sym               = Lm_symbol.add "pw_shell"
+
+let gr_name_sym                = Lm_symbol.add "gr_name"
+let gr_passwd_sym              = Lm_symbol.add "gr_passwd"
+let gr_gid_sym                 = Lm_symbol.add "gr_gid"
+let gr_mem_sym                 = Lm_symbol.add "gr_mem"
+
 let target_sym                 = Lm_symbol.add "target"
 let target_effects_sym         = Lm_symbol.add "effects"
 let scanner_deps_sym           = Lm_symbol.add "scanner-deps"
Index: lib/Pervasives.om
===================================================================
--- lib/Pervasives.om	(revision 9985)
+++ lib/Pervasives.om	(working copy)
@@ -846,6 +846,14 @@
    class Stat
    extends $(Object)
 
+Passwd. +=
+   class Passwd
+   extends $(Object)
+
+Group. +=
+   class Group
+   extends $(Object)
+
 ########################################################################
 # The shell object.
 #
@@ -886,6 +894,11 @@
    #
    jobs = $(jobs)
 
+   getpwnam = $(getpwnam)
+   getpwuid = $(getpwuid)
+   getgrnam = $(getgrnam)
+   getgrgid = $(getgrgid)
+
    #
    # \begin{doc}
    # \item \verb+cd+


More information about the Omake mailing list