1 #![warn(missing_copy_implementations)]
2 #![warn(missing_docs)]
3 #![warn(nonstandard_style)]
4 #![warn(trivial_numeric_casts)]
5 #![warn(unreachable_pub)]
6 #![warn(unused)]
7 
8 
9 //! This is a library for getting information on Unix users and groups. It
10 //! supports getting the system users, and creating your own mock tables.
11 //!
12 //! In Unix, each user has an individual *user ID*, and each process has an
13 //! *effective user ID* that says which user’s permissions it is using.
14 //! Furthermore, users can be the members of *groups*, which also have names and
15 //! IDs. This functionality is exposed in libc, the C standard library, but as
16 //! an unsafe Rust interface. This wrapper library provides a safe interface,
17 //! using [`User`](struct.user.html) and [`Group`](struct.group.html) types
18 //! and functions such as [`get_user_by_uid`](fn.get_user_by_uid.html) instead
19 //! of low-level pointers and strings. It also offers basic caching
20 //! functionality.
21 //!
22 //! It does not (yet) offer *editing* functionality; the values returned are
23 //! read-only.
24 //!
25 //!
26 //! ## Users
27 //!
28 //! The function [`get_current_uid`](fn.get_current_uid.html) returns a
29 //! `uid_t` value representing the user currently running the program, and the
30 //! [`get_user_by_uid`](fn.get_user_by_uid.html) function scans the users
31 //! database and returns a `User` with the user’s information. This function
32 //! returns `None` when there is no user for that ID. The `uid_t` type is
33 //! re-exported from the libc crate.
34 //!
35 //! A [`User`](struct.User.html) value has the following accessors:
36 //!
37 //! - **uid:** The user’s ID
38 //! - **name:** The user’s name
39 //! - **primary_group:** The ID of this user’s primary group
40 //!
41 //! Here is a complete example that prints out the current user’s name:
42 //!
43 //! ```
44 //! use users::{get_user_by_uid, get_current_uid};
45 //!
46 //! let user = get_user_by_uid(get_current_uid()).unwrap();
47 //! println!("Hello, {}!", user.name().to_string_lossy());
48 //! ```
49 //!
50 //! This code assumes (with `unwrap()`) that the user hasn’t been deleted after
51 //! the program has started running. For arbitrary user IDs, this is **not** a
52 //! safe assumption: it’s possible to delete a user while it’s running a
53 //! program, or is the owner of files, or for that user to have never existed.
54 //! So always check the return values!
55 //!
56 //! There is also a [`get_current_username`](fn.get_current_username.html)
57 //! function, as it’s such a common operation that it deserves special
58 //! treatment.
59 //!
60 //!
61 //! ## Caching
62 //!
63 //! Despite the above warning, the users and groups database rarely changes.
64 //! While a short program may only need to get user information once, a
65 //! long-running one may need to re-query the database many times, and a
66 //! medium-length one may get away with caching the values to save on redundant
67 //! system calls.
68 //!
69 //! For this reason, this crate offers a caching interface to the database,
70 //! which offers the same functionality while holding on to every result,
71 //! caching the information so it can be re-used.
72 //!
73 //! To introduce a cache, create a new
74 //! [`UsersCache`](cache/struct.UsersCache.html). It has functions with the
75 //! same names as the ones from earlier. For example:
76 //!
77 //! ```
78 //! use users::{Users, Groups, UsersCache};
79 //!
80 //! let mut cache = UsersCache::new();
81 //! let uid = cache.get_current_uid();
82 //! let user = cache.get_user_by_uid(uid).unwrap();
83 //! println!("Hello again, {}!", user.name().to_string_lossy());
84 //! ```
85 //!
86 //! This cache is **only additive**: it’s not possible to drop it, or erase
87 //! selected entries, as when the database may have been modified, it’s best to
88 //! start entirely afresh. So to accomplish this, just start using a new
89 //! `UsersCache`.
90 //!
91 //!
92 //! ## Groups
93 //!
94 //! Finally, it’s possible to get groups in a similar manner.
95 //! A [`Group`](struct.Group.html) has the following accessors:
96 //!
97 //! - **gid:** The group’s ID
98 //! - **name:** The group’s name
99 //!
100 //! And again, a complete example:
101 //!
102 //! ```no_run
103 //! use users::{Users, Groups, UsersCache};
104 //!
105 //! let mut cache = UsersCache::new();
106 //! let group = cache.get_group_by_name("admin").expect("No such group 'admin'!");
107 //! println!("The '{}' group has the ID {}", group.name().to_string_lossy(), group.gid());
108 //! ```
109 //!
110 //!
111 //! ## Logging
112 //!
113 //! The `logging` feature, which is on by default, uses the `log` crate to
114 //! record all interactions with the operating system.
115 //!
116 //!
117 //! ## Caveats
118 //!
119 //! You should be prepared for the users and groups tables to be completely
120 //! broken: IDs shouldn’t be assumed to map to actual users and groups, and
121 //! usernames and group names aren’t guaranteed to map either!
122 //!
123 //! Use the [`mock`](mock/index.html) module to create custom tables to test
124 //! your code for these edge cases.
125 
126 
127 extern crate libc;
128 pub use libc::{uid_t, gid_t};
129 
130 mod base;
131 pub use base::{User, Group, os};
132 pub use base::{get_user_by_uid, get_user_by_name};
133 pub use base::{get_group_by_gid, get_group_by_name};
134 pub use base::{get_current_uid, get_current_username};
135 pub use base::{get_effective_uid, get_effective_username};
136 pub use base::{get_current_gid, get_current_groupname};
137 pub use base::{get_effective_gid, get_effective_groupname};
138 pub use base::{get_user_groups, group_access_list};
139 pub use base::{all_users};
140 
141 #[cfg(feature = "cache")]
142 pub mod cache;
143 
144 #[cfg(feature = "cache")]
145 pub use cache::UsersCache;
146 
147 #[cfg(feature = "mock")]
148 pub mod mock;
149 
150 pub mod switch;
151 
152 mod traits;
153 pub use traits::{Users, Groups};
154