Mercurial > emacs
changeset 27474:ed3668c0295a
(socket_status): New function.
(main): if $LOGNAME or $USER exist and differ from our euid, look
for a socket based on the UID associated with the name.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Fri, 28 Jan 2000 15:02:20 +0000 |
parents | 2c8128604a57 |
children | d44d90480852 |
files | lib-src/emacsclient.c |
diffstat | 1 files changed, 76 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/lib-src/emacsclient.c Fri Jan 28 13:55:15 2000 +0000 +++ b/lib-src/emacsclient.c Fri Jan 28 15:02:20 2000 +0000 @@ -1,5 +1,5 @@ /* Client process that communicates with GNU Emacs acting as server. - Copyright (C) 1986, 1987, 1994, 1999 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1994, 1999, 2000 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -29,6 +29,12 @@ #include <unistd.h> #endif +#ifdef VMS +# include "vms-pwd.h" +#else +# include <pwd.h> +#endif /* not VMS */ + char *getenv (), *getwd (); char *getcwd (); @@ -217,6 +223,26 @@ extern char *strerror (); extern int errno; +/* Three possibilities: + 2 - can't be `stat'ed (sets errno) + 1 - isn't owned by us + 0 - success: none of the above */ + +static int +socket_status (socket_name) + char *socket_name; +{ + struct stat statbfr; + + if (stat (socket_name, &statbfr) == -1) + return 2; + + if (statbfr.st_uid != geteuid ()) + return 1; + + return 0; +} + int main (argc, argv) int argc; @@ -272,25 +298,60 @@ #ifndef SERVER_HOME_DIR { struct stat statbfr; + int sock_status = 0; sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name); - if (stat (server.sun_path, &statbfr) == -1) + /* See if the socket exists, and if it's owned by us. */ + sock_status = socket_status (server.sun_path); + if (sock_status) { - if (errno == ENOENT) - fprintf (stderr, - "%s: can't find socket; have you started the server?\n", - argv[0]); - else - fprintf (stderr, "%s: can't stat %s: %s\n", - argv[0], server.sun_path, strerror (errno)); - fail (argc, argv); + /* Failing that, see if LOGNAME or USER exist and differ from + our euid. If so, look for a socket based on the UID + associated with the name. This is reminiscent of the logic + that init_editfns uses to set the global Vuser_full_name. */ + + char *user_name = (char *) getenv ("LOGNAME"); + if (!user_name) + user_name = (char *) getenv ("USER"); + + if (user_name) + { + struct passwd *pw = getpwnam (user_name); + if (pw && (pw->pw_uid != geteuid ())) + { + /* We're running under su, apparently. */ + sprintf (server.sun_path, "/tmp/esrv%d-%s", + pw->pw_uid, system_name); + sock_status = socket_status (server.sun_path); + } + } } - if (statbfr.st_uid != geteuid ()) - { - fprintf (stderr, "%s: Invalid socket owner\n", argv[0]); - fail (argc, argv); - } + + switch (sock_status) + { + case 1: + /* There's a socket, but it isn't owned by us. This is OK if + we are root. */ + if (0 != geteuid ()) + { + fprintf (stderr, "%s: Invalid socket owner\n", argv[0]); + fail (argc, argv); + } + break; + + case 2: + /* `stat' failed */ + if (errno == ENOENT) + fprintf (stderr, + "%s: can't find socket; have you started the server?\n", + argv[0]); + else + fprintf (stderr, "%s: can't stat %s: %s\n", + argv[0], server.sun_path, strerror (errno)); + fail (argc, argv); + break; + } } #else if ((homedir = getenv ("HOME")) == NULL)