Merge remote-tracking branch 'origin/master' into for-steve
[sxemacs] / src / editfns.c
index 089b7f4..c2d6a01 100644 (file)
@@ -39,10 +39,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 #include "casetab.h"
 #include "chartab.h"
 #include "line-number.h"
+#include "ent/ent.h"
 
 #include "systime.h"
 #include "sysdep.h"
 #include "syspwd.h"
+#include "sysgrp.h"
 #include "sysfile.h"           /* for getcwd */
 
 /* Some static data, and a function to initialize it for each run */
@@ -617,23 +619,24 @@ On Unix it is obtained from TMPDIR, with /tmp as the default.
                } else {
                        const char* home_env = getenv("HOME");
                        if ( home_env ) {
-                               strncpy(path, home_env, sizeof(path)-1);
-                               strncat(path, "/tmp/", sizeof(path)-1);
+                               xstrncpy(path, home_env, sizeof(path));
+                               xstrncat(path, "/tmp/", sizeof(path)-1);
                                if ( mkdir(path, 0700) >= 0 || errno == EEXIST ) {
                                        int fd;
                                        char warnpath[
                                                /* strlen(".created_by_sxemacs") */
                                                19 + _POSIX_PATH_MAX + 1];
-                                       strncpy(warnpath, path, _POSIX_PATH_MAX);
-                                       warnpath[sizeof(warnpath)-1]=0;
+                                       xstrncpy(warnpath, path, sizeof(warnpath));
 
                                        /* we already are reserved these 20 bytes... */
-                                       strcat(warnpath, ".created_by_sxemacs");
+                                       xstrncat(warnpath, ".created_by_sxemacs", 
+                                                sizeof(warnpath)-1);
                                        if ((fd = open(warnpath, O_WRONLY | O_CREAT,
-                                                      0644)) > 0) {
+                                                      0644)) >= 0) {
                                                write(fd, "SXEmacs created this directory "
                                                          "because /tmp/<yourname> "
-                                                         "was unavailable -- \nPlease check !\n",  89);
+                                                         "was unavailable -- \nPlease check !\n",
+                                                     89);
                                                close(fd);
                                        }
                                }
@@ -695,9 +698,7 @@ char *user_login_name(uid_t * uid)
                   environment variables should be disregarded in that case.  --Stig */
                char *user_name = getenv("LOGNAME");
                if (!user_name)
-                       user_name = getenv(
-                                                 "USER"
-                           );
+                       user_name = getenv("USER");
                if (user_name)
                        return (user_name);
                else {
@@ -707,6 +708,47 @@ char *user_login_name(uid_t * uid)
        }
 }
 
+DEFUN("user-group-name", Fuser_group_name, 0, 1, 0,    /*
+Return the group name under which the user logged in, as a string.
+This is based on the effective gid, not the real gid.
+If the optional argument GID is present, then this function returns 
+the group name for that UID, or nil.
+*/
+      (gid))
+{
+       char *returned_name;
+       uid_t local_gid;
+
+       if (!NILP(gid)) {
+               CHECK_INT(gid);
+               local_gid = XINT(gid);
+               returned_name = user_group_name(&local_gid);
+       } else {
+               returned_name = user_group_name(NULL);
+       }
+       /* #### - I believe this should return nil instead of "unknown" when pw==0
+          pw=0 is indicated by a null return from user_login_name
+        */
+       return returned_name ? build_string(returned_name) : Qnil;
+}
+
+/* This function may be called from other C routines when a
+   character string representation of the user_group_name is
+   needed but a Lisp Object is not.  The GID is passed by
+   reference.  If GID == NULL, then the group for
+   for the user running XEmacs will be returned.  This
+   corresponds to a nil argument to Fuser_group_name.
+*/
+char *user_group_name(gid_t * gid)
+{
+       /* gid == NULL to return the group of this user */
+       struct group * grp = getgrgid( gid ? *gid : getegid());
+       if (grp == NULL) {
+               return NULL;
+       }
+       return grp->gr_name;
+}
+
 DEFUN("user-real-login-name", Fuser_real_login_name, 0, 0, 0,  /*
 Return the name of the user's real uid, as a string.
 This ignores the environment variables LOGNAME and USER, so it differs from
@@ -721,22 +763,76 @@ This ignores the environment variables LOGNAME and USER, so it differs from
        return tem;
 }
 
-DEFUN("user-uid", Fuser_uid, 0, 0, 0,  /*
-Return the effective uid of Emacs, as an integer.
+DEFUN("user-uid", Fuser_uid, 0, 1, 0,  /*
+Return the effective uid of the Emacs process, as an integer.
+If the optional argument `user_name' is specified it returns the uid of
+the user with that name. Will return `nil' if there is no user with the
+specified name,
 */
-      ())
+      (user_name))
+{
+       if (!NILP(user_name)) {
+               const char * user_name_ext = NULL;
+
+               CHECK_STRING(user_name);
+
+               TO_EXTERNAL_FORMAT(LISP_STRING, user_name,
+                                  C_STRING_ALLOCA, user_name_ext, Qnative);
+
+               struct passwd *pw = getpwnam(user_name_ext);
+               if (pw) {
+                       return make_int(pw->pw_uid);
+               } else {
+                       return Qnil;
+               }
+       } else {
+               return make_int(geteuid());
+       }
+}
+
+DEFUN("user-gid", Fuser_gid, 0, 1, 0,  /*
+Return the effective gid of the Emacs process, as an integer.
+If the optional argument `group_name' is specified it returns the gid of
+the group with that name. It will return `nil' if the system has no
+group with the specified name. 
+*/
+      (group_name))
 {
-       return make_int(geteuid());
+       if (!NILP(group_name)) {
+               const char *group_name_ext = NULL;
+
+               CHECK_STRING(group_name);
+
+               TO_EXTERNAL_FORMAT(LISP_STRING, group_name,
+                                  C_STRING_ALLOCA, group_name_ext, Qnative);
+
+               struct group *grp = getgrnam(group_name_ext);
+               if (grp) {
+                       return make_int(grp->gr_gid);
+               } else {
+                       return Qnil;
+               }
+       } else {
+               return make_int(getegid());
+       }
 }
 
 DEFUN("user-real-uid", Fuser_real_uid, 0, 0, 0,        /*
-Return the real uid of Emacs, as an integer.
+Return the real uid of the Emacs process, as an integer.
 */
       ())
 {
        return make_int(getuid());
 }
 
+DEFUN("user-real-gid", Fuser_real_gid, 0, 0, 0,        /*
+Return the real gid of the Emacs process, as an integer.
+*/
+      ())
+{
+       return make_int(getgid());
+}
+
 DEFUN("user-full-name", Fuser_full_name, 0, 1, 0,      /*
 Return the full name of the user logged in, as a string.
 If the optional argument USER is given, then the full name for that
@@ -1751,7 +1847,7 @@ DEFUN("insert-string", Finsert_string, 1, 2, 0,   /*
 Insert STRING into BUFFER at BUFFER's point.
 Point moves forward so that it ends up after the inserted text.
 Any other markers at the point of insertion remain before the text.
-If a string has non-null string-extent-data, new extents will be created.
+If a string has non-null, duplicable string-extent-data, new extents will be created.
 BUFFER defaults to the current buffer.
 */
       (string, buffer))
@@ -2693,9 +2789,12 @@ void syms_of_editfns(void)
 
        DEFSUBR(Ftemp_directory);
        DEFSUBR(Fuser_login_name);
+       DEFSUBR(Fuser_group_name);
        DEFSUBR(Fuser_real_login_name);
        DEFSUBR(Fuser_uid);
        DEFSUBR(Fuser_real_uid);
+       DEFSUBR(Fuser_gid);
+       DEFSUBR(Fuser_real_gid);
        DEFSUBR(Fuser_full_name);
        DEFSUBR(Fuser_home_directory);
        DEFSUBR(Femacs_pid);