// // aegis - project change supervisor // Copyright (C) 1992-2000, 2002-2008, 2011, 2012 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #ifndef AEGIS_USER_H #define AEGIS_USER_H #include #include #include #include #include class project; // forward class output_ty; // forward /** * The user_ty class represents a user (usually, the operating system's * idea of a user) an information about that user, and her preferences. */ class user_ty { public: /** * The pointer typedef is to be used whenevr pointing to a user_ty * object. This allows the pointer type to be changed to a smart * pointer in the future. */ typedef aegis_shared_ptr pointer; /** * The destructor. * * It is not virtual, thou shalt not derived from this class. */ ~user_ty(); /** * The create class method is used to create new heap instances * of users. The user in this case being the user who executeed * this program. */ static user_ty::pointer create(); private: /** * The default constructor. */ user_ty(); public: /** * The create class method is used to create new heap instances of * users. The default group is derived from the password file. * * @param uid * The user ID involved. */ static user_ty::pointer create(int uid); private: /** * The constructor. * * @param uid * The user ID involved. */ user_ty(int uid); public: /** * The create class method is used to create a user structure for * the aegis/gonzo.cc file. It has a known uid and gid, and will * succeed, even if there are no relvant entries in system tables. * * @param uid * system user id * @param gid * system group id */ static user_ty::pointer create(int uid, int gid); private: /** * The constrctor. * * @param uid * system user id * @param gid * system group id */ user_ty(int uid, int gid); public: /** * The create class method is used to create a user instance from * a login name. * * The login name is mapped to a uid. The password file is * searched from beginning to end, so the cannonical name is the * first found in the password file. The cannonical name is used * even for user structures created with this function. * * @param login_name * user's login name */ static user_ty::pointer create(const nstring &login_name); /** * The create_by_directory class method is used to create a user * from the ownership of a directory. * * @param path * The absolute path pf the directory of interest. * @returns * pointer to new user_ty instance */ static user_ty::pointer create_by_directory(const nstring &path); /** * The progress_option_set class method is called by command line * processing to indicate that a --progress command line option has * been seen. * * @param usage * The function to call if a fail via a usage message is * required. */ static void progress_option_set(void (*usage)(void)); /** * The progress_option_clear class method is called by command line * processing to indicate that a --no-progress command line option * has been seen. * * @param usage * The function to call if a fail via a usage message is * required. */ static void progress_option_clear(void (*usage)(void)); /** * The progress_get method is used to determine whether or not * progress messages should be displayed. It consults the command * line settings and also the user's progress attribute. Being in * the background is not considered. The --verbose option is not * considered. The default is to return false. * * Example: * attribute = * [ * { name = "progress-preference"; value = "true"; } * ]; */ bool progress_get(); /** * The name method is used to obtain the login name of this user. */ nstring name() const; /** * The full_name method is used to obtain the human readable name * of this user, as recorded in the password file. */ nstring full_name() const; /** * The full_name class method is used to obtain the full name of a * user, given the login name. * * @param login * The login name of the user * @returns * the full name of the user, or the empty string if it doesn't * exist. */ static nstring full_name(const nstring &login); /** * The get_uid method is used to obtain the operating system user * ID associated with this user. */ int get_uid() const; /** * The check_uid method is used to verify that this user has an * acceptable level of privilege. */ bool check_uid() const; /** * The get_gid method is used to obtain the operating system group * ID associated with this user. */ int get_gid() const; /** * The check_gid method is used to verify that this user has an * acceptable level of privilege. */ bool check_gid() const; /** * The get_group_name method is used to obtain the name of the * operating system group attached to this user. */ nstring get_group_name() const; /** * The set_gid method is used to set the group ID of this user. * * @param gid * The group ID to use. * @param weak * true if it is OK that the group doesn't exists, false * (default) if it is an error if the group desn't exist. */ void set_gid(int gid, bool weak = false); /** * The umask_set method is used to set the file creation mode mosk. * * @param um * The new mask. */ void umask_set(int um); /** * The umask_get method is used to obtain the new file creation * permissions mode mask for this user. */ int umask_get() const; /** * The get_home method is used to obtain the absolute path of this * user's home directory. */ nstring get_home() const; /** * The get_email_address method is used to read the user's * preferences for her email address. Defaults to full name from * /etc/passwd, then login name at hostname (not generally useful). */ nstring get_email_address(); /** * The ustate_write method is used to write any modified ustate * file contents back to disk. */ void ustate_write(); /** * The user_own_add function is used to add a change to the user's * list of owned changes. * * @param pp * project of the change * @param chanum * the number of the change */ void own_add(project *pp, long chanum); /** * The user_own_nth function is used to fetch the n'th * change owned by a user. * The project name is derived from the user structure. * * @param pp * project of the change * @param n * selector * @param chanum * reference to where to put number of the change * @returns * true on sucess, false if no such n. */ bool own_nth(project *pp, long n, long &chanum); /** * The user_own_remove function is used to * remove a change from the user's owned change list. * * @param pp * project of the change * @param chanum * number of the change. * The change is assumed to be unique. */ void own_remove(project *pp, long chanum); /** * The default_change method is used to find the default change * number. It is a fatal error if there isn't one. * * @param pp * The project of interest. * @returns * the change number. */ long default_change(project *pp); /** * The default_project method is used to determine the default * project of the specified user. It is a fatal error if there is * no default project name for the user. */ nstring default_project(); /** * The default_development_directory method is used to determine * the absolute path of the user's default development directory. * * If the user has not explicitly set one, and the project does not * have one set, the user's home directory will be returned. * * @param pp * The project to consult for its default development * directory, as wel. */ nstring default_development_directory(project *pp); /** * The default_project_directory method is used to determine the * absolute path for where to place new projects. * * if the user has not explicitly set one, the user's home * directory will be returned. */ nstring default_project_directory(); /** * The become_begin method is used to set the effective uid and * gid to be those of this user. In this way, the code can * impersonate a variety of users, while still enforcing strict * secure semantics. */ void become_begin(); /** * The become_end method is used to reverse the effects of the * become_begin method. * * These two methods shall always be used in pairs. This is * simplified further if you use the user_ty::become class. */ void become_end(); /** * The user_ty::become class is used to take care of becoming a * user, and then ceasing to become that user at the end of the * scope. For example: * * { * user_ty::become scoped(up); * ...glue... * if (something) * return; * ...execute... * } * * No matter how the flow of execution leaves the scope (break, * continue, return, exceptions) the become_end will always occur, * because the destructor is automatically called by the compiler. * * This is an example of the Resoure Acquisition Is Initialisation * (RAII) design pattern. */ class become { public: /** * The constructor. Start impersonating the user. */ become(user_ty::pointer a_up) : up(a_up) { up->become_begin(); } /** * The destructor. Stop impersonating the user. */ ~become() { up->become_end(); } private: /** * The up instance variable is used to remember which user is * being impersonated. */ user_ty::pointer up; /** * The copy constructor. Do not use. */ become(const become &); /** * The assignment operator. Do not use. */ become &operator=(const become &); }; /** * The delete_file_query method is used to determine whether a file * should be deleted or not. * * @param filename * The name of the file to be deleted * @param isdir * whether the file is a directory (true) or a regular file (false). * @param default_preference * If the user gave no preference on the command line, use this * instead. 1 -> true, 0 -> false, -1 -> look in .aegisrc * @returns * true if the file should be deleted, or false if it should not. */ bool delete_file_query(const nstring &filename, bool isdir, int default_preference); /** * The delete_file_argument class method is used to process --keep * and --no-keep command line options. * * @param usage * Exit via this function on error. */ static void delete_file_argument(void (*usage)(void)); /** * The ustate_lock_prepare method is used to notify the lock * manager that a ustate lock will be required. */ void ustate_lock_prepare(); /** * The lock_wait_argument class method is used to process --wait * and --no-wait command line arguments. * * @param usage * Exit via this function on error. */ static void lock_wait_argument(void(*usage)(void)); /** * The lock_wait method may be used if this user wants to wait for * locks or not. */ bool lock_wait(); /** * The editor_command method is used to read the user's preferences * for editor to use with aegis. Defaults to EDITOR environment * variable, or else "ed". */ nstring editor_command(); /** * The visual_command method is used to read the user's preferences * for a visual editor to use with aegis. Defaults to VISUAL * environment variable, or else the EDITOR environment variable, * or else "vi". */ nstring visual_command(); /** * The diff_preference method is ised to obtain this user's aed * preference. * * @returns * The choices are always merge, never merge, and automatic * (default). */ uconf_diff_preference_ty diff_preference(); /** * The pager_preference method is used to obtain this user's pager * preference. * * @returns * true if should use pager, false if should not use pager. */ bool pager_preference(); /** * The pager_command method is used to read the user's preferences * for pager to use with aegis. Defaults to PAGER environment * variable. If $PAGER is not set then "more" is used. */ nstring pager_command(); /** * The persevere_preference method is used to determine whether or not * aet (and friends) should persevere in the face of errors. * * @param dflt * The default to use, should the not have set a preference. */ bool persevere_preference(bool dflt); /** * The persevere_argument class method is used to process * --presevere and -no-persevere command line arguments. * * @param usage * Exit via this function on error. */ static void persevere_argument(void(*usage)(void)); /** * The log_file_preference method may be used to obtain this user's * log file preference. * * @param dflt * If the user has not specified one, this argument is the * default to be returned (varies with command). * @returns * the choices are: none, replace, append */ uconf_log_file_preference_ty log_file_preference( uconf_log_file_preference_ty dflt); /** * The relative_filename_preference_argument class method is used * to process --base-relative and --not-base-relative command line * options. * * @param usage * Exit via this function on error. */ static void relative_filename_preference_argument(void(*usage)(void)); /** * The relative_filename_preference method may be used to obtain * this user's preference for whethger or not relative file names * on the command line are relative to the development diorectory * root, or relative to the current directory. * * @param dflt * The default to use if the user has not selected on (varies * with command). * @returns * the choices are: base, current */ uconf_relative_filename_preference_ty relative_filename_preference( uconf_relative_filename_preference_ty dflt); /** * The symlink_pref_argument is used to process the * --symbolic-links and --no-symbolic-links command line options. * * @param usage * Exit via this function on error. */ static void symlink_pref_argument(void(*usage)(void)); /** * The symlink_pref method may be used to obtain this user's * symbolic link maintenance preference. Some development * directory styles do not have to be maintained. * * If your development directory style uses hard links or copies, * this method also controls them. * * @param proj_files_changed * true if any project files have changed recently * @returns * true to update the links, false to not update the links */ bool symlink_pref(bool proj_files_changed); /** * The symlink_pref_argument is used to process the --whiteout and * --no-whiteout command line options. * * @param usage * Exit via this function on error. */ static void whiteout_argument(void (*usage)(void)); /** * The whiteout mwthod may be used to determine this user's * whiteout file preference. * * @param dflt * The default the comman wants (true (0) or false (1)) * or -1 if the user's .aegisrc file is to be consulted. * @returns * true if whiteout files are to be used, false if no whiteout * files are to be generated. */ bool whiteout(int dflt = -1); /** * The uconf_write_xml method may be used to write this user's * uconf data out as XML. * * @param op * Where to write the XML. */ void uconf_write_xml(output::pointer op); /** * The uconf_get method is used to get the uconf data corresponding * to the specified user. It is cached. This should be used * sparingly, if at all. It is preferable to use one of the above * methods if at all possible. * * @returns * pointer to uconf structure in dynamic memory * @note * this method will eventually be PRIVATE */ uconf_ty *uconf_get(); private: /** * The login_name instance variable is used to remember the login * name of this user. */ nstring login_name; /** * The login_full_name instance variable is used to remember the * full name of this user, as recorded in the password entry. */ nstring login_full_name; /** * The home instance variable is used to remember the absolute path * of this user's home directory. */ nstring home; /** * The group_name instance variable is used to remember the name * of the operating system group attached to this user. */ nstring group_name; /** * The user_id instance variable is used to remeber the operating * system user ID associated with this user. */ int user_id; /** * The group_id instance variable is used to remeber the operating * system group ID associated with this user. */ int group_id; /** * The umask instance variable is used to remember this user's * preferred new file mode creation mask. */ int umask; /** * The ustate_path instance variable is used to remember where the * ustate file is that holds this user's index of owned project. * * In some ways this is not ideal, since the path depends on which * gonzo holds the project record. There is more than one. */ nstring ustate_path; /** * The ustate_data instance variable is used to remember the * location of the cached ustate data for this user. * * In some ways this is not ideal, since the data depends on which * gonzo holds the project record. There is more than one. */ ustate_ty *ustate_data; /** * The ustate_is_new instance variable is used to remember whether * or not a new ustate file is to be created. */ bool ustate_is_new; /** * The ustate_modified instance variable is used to remember * whether or not the cahced ustate data has been modified, and * needs to be written out. */ bool ustate_modified; /** * The user_ustate_get function is used to fetch the "ustate" file * for this user, caching for future reference. * * @param pp * The project of interest */ ustate_ty *ustate_get(project *pp); /** * The uconf_path instance variable is used to remember the * absolute path of this user's .aegisrc file. */ nstring uconf_path; /** * The uconf_data instance variable is used to remember the base * address of the read-in .aegisrc file data. It is cached for * efficiency. */ uconf_ty *uconf_data; /** * The lock_magic instance variable is used to remember the last * time the locks changed, so that uconf and ustate data can be * invalidated, if necessary. See the lock_sync method. */ long lock_magic; /** * The lock_sync method is used to flush any out-of-date data * caching associated with the user structure. */ void lock_sync(); /** * The pool_nusers class variable is used to remember how many * user_ty instaces currently exist. */ static size_t pool_nusers; /** * The pool_nusers_max class variable is used to remember the size * allocated for the pool_user array. * * assert(pool_nusers <= pool_nusers_max); */ static size_t pool_nusers_max; /** * The pool_user class variable is used to remember the base * address of a dynamically allocated array of pointers to user * instances. * * assert(!pool_user == !pool_nusers_max); */ static pointer *pool_user; /** * The pool_find class method is used to look into the pool of * user_ty instances to determine wether or not the given UID * corresponds to an existing user_ty instance. * * This is an O(n) search. It is expected that there will be at * most 4, so the slow search isn't a problem - a faster search * would have a larger k - making it moot. * * @param uid * The UID to search for * @returns * pointer if found, NULL if not found */ static user_ty::pointer pool_find(int uid); /** * The pool_add class method is used to add a new user_ty instance * to the pool. */ static void pool_add(user_ty::pointer up); /** * The waiting_for_lock method is used to print a message to inform * the user of the progress acquiring the lock. */ void waiting_for_lock(); /** * The waiting_for_lock class method is used to call the * waiting_for_lock method. */ static void waiting_for_lock(void *); }; // use user_ty::create(int) instead user_ty::pointer user_numeric(int uid) DEPRECATED; // use user_ty::create(int, int) instead user_ty::pointer user_numeric2(int uid, int gid) DEPRECATED; // use user_ty::create(nstring) instead user_ty::pointer user_symbolic(string_ty *login_name) DEPRECATED; // use user_ty::create() instead user_ty::pointer user_executing(void) DEPRECATED; // use nothing at all void user_free(user_ty::pointer) DEPRECATED; // just assign it user_ty::pointer user_copy(user_ty::pointer) DEPRECATED; // use user_ty::name() instead string_ty *user_name(user_ty::pointer up) DEPRECATED; // use user_ty::full_name() instead string_ty *user_name2(user_ty::pointer up) DEPRECATED; // use user_ty::get_uid() instead int user_id(user_ty::pointer) DEPRECATED; // use user_ty::get_gid() instead int user_gid(user_ty::pointer) DEPRECATED; // use user_ty::umask_get() instead int user_umask(user_ty::pointer) DEPRECATED; // user user_ty::ustate_lock_prepare() instead void user_ustate_lock_prepare(user_ty::pointer) DEPRECATED; // use user_ty::get_group_name() instead string_ty *user_group(user_ty::pointer) DEPRECATED; // use user_ty::get_home() instead string_ty *user_home(user_ty::pointer up) DEPRECATED; // user user_ty::get_email_address() instead string_ty *user_email_address(user_ty::pointer up) DEPRECATED; // use user_ty::editor_command() instead string_ty *user_editor_command(user_ty::pointer) DEPRECATED; // user user_ty::visual_command() instead string_ty *user_visual_command(user_ty::pointer) DEPRECATED; // see user_ty::pager_command instead string_ty *user_pager_command(user_ty::pointer) DEPRECATED; // use user_ty::full_name(const nstring &) instead string_ty *user_full_name(string_ty *) DEPRECATED; // use user_ty::ustate_write() instead void user_ustate_write(user_ty::pointer) DEPRECATED; // use user_ty::own_add instead void user_own_add(user_ty::pointer up, project *pp, long chanum) DEPRECATED; // use user_ty::own_nth instead int user_own_nth(user_ty::pointer up, project *oo, long n, long *chanum_p) DEPRECATED; // use user_ty::own_remove instead void user_own_remove(user_ty::pointer up, project *pp, long chanum) DEPRECATED; // use user_ty::default_change(project *pp) instead long user_default_change(user_ty::pointer up, project *pp) DEPRECATED; // user user_ty::default_project() instead string_ty *user_default_project_by_user(user_ty::pointer) DEPRECATED; // user user_ty::default_project() instead string_ty *user_default_project(void) DEPRECATED; // use user_ty::default_development_directory(project *pp) instead string_ty *user_default_development_directory(user_ty::pointer up, project *pp) DEPRECATED; // user user_ty::default_project_directory() instead string_ty *user_default_project_directory(user_ty::pointer) DEPRECATED; // use user_ty::become_begin() instead void user_become(user_ty::pointer) DEPRECATED; // use user_ty::become_end() instead void user_become_undo(void) DEPRECATED; // use user_ty::delete_file_query instead bool user_delete_file_query(user_ty::pointer up, string_ty *filename, bool isdir, int default_preference) DEPRECATED; // use user_ty::delete_file_argument instead void user_delete_file_argument(void (*)(void)) DEPRECATED; // use user_ty::diff_preference() instead int user_diff_preference(user_ty::pointer) DEPRECATED; // use user_ty::pager_preference() instead int user_pager_preference(user_ty::pointer) DEPRECATED; // use user_ty::persevere_preference() instead int user_persevere_preference(user_ty::pointer, int) DEPRECATED; // use user_ty::persevere_argument instead void user_persevere_argument(void(*)(void)) DEPRECATED; // use user_ty::log_file_preference instead uconf_log_file_preference_ty user_log_file_preference(user_ty::pointer, uconf_log_file_preference_ty) DEPRECATED; // user user_ty::lock_wait_argument instead void user_lock_wait_argument(void(*usage)(void)) DEPRECATED; // user user_ty::lock_wait instead int user_lock_wait(user_ty::pointer up) DEPRECATED; // use user_ty::whiteout_argument instead void user_whiteout_argument(void(*)(void)) DEPRECATED; // use user_ty::whiteout instead int user_whiteout(user_ty::pointer up, int dflt = -1) DEPRECATED; // use user_ty::symlink_pref_argument instead void user_symlink_pref_argument(void(*)(void)) DEPRECATED; // use user_ty::symlink_pref instead int user_symlink_pref(user_ty::pointer, int) DEPRECATED; // use user_ty::relative_filename_preference_argument instead void user_relative_filename_preference_argument(void(*)(void)) DEPRECATED; // use user_ty::relative_filename_preference instead uconf_relative_filename_preference_ty user_relative_filename_preference( user_ty::pointer, uconf_relative_filename_preference_ty) DEPRECATED; // use user_ty::uconf_write_xml instead void user_uconf_write_xml(user_ty::pointer, output::pointer) DEPRECATED; // use user_ty::uconf_get() instead uconf_ty *user_uconf_get(user_ty::pointer) DEPRECATED; #endif // AEGIS_USER_H // vim: set ts=8 sw=4 et :