root/lib/vfs/utilvfs.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. vfs_get_local_username
  2. vfs_finduid
  3. vfs_findgid
  4. vfs_mkstemps
  5. vfs_url_split
  6. vfs_die
  7. vfs_get_password

   1 /*
   2    Utilities for VFS modules.
   3 
   4    Copyright (C) 1988-2024
   5    Free Software Foundation, Inc.
   6 
   7    Copyright (C) 1995, 1996 Miguel de Icaza
   8 
   9    This file is part of the Midnight Commander.
  10 
  11    The Midnight Commander is free software: you can redistribute it
  12    and/or modify it under the terms of the GNU General Public License as
  13    published by the Free Software Foundation, either version 3 of the License,
  14    or (at your option) any later version.
  15 
  16    The Midnight Commander is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20 
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23  */
  24 
  25 /**
  26  * \file
  27  * \brief Source: Utilities for VFS modules
  28  * \author Miguel de Icaza
  29  * \date 1995, 1996
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <ctype.h>
  35 #include <sys/types.h>
  36 #include <pwd.h>
  37 #include <grp.h>
  38 #include <stdlib.h>
  39 #include <string.h>
  40 
  41 #include "lib/global.h"
  42 #include "lib/unixcompat.h"
  43 #include "lib/widget.h"         /* message() */
  44 #include "lib/strutil.h"        /* INVALID_CONV */
  45 
  46 #include "vfs.h"
  47 #include "utilvfs.h"
  48 
  49 /*** global variables ****************************************************************************/
  50 
  51 /*** file scope macro definitions ****************************************************************/
  52 
  53 #ifndef TUNMLEN
  54 #define TUNMLEN 256
  55 #endif
  56 #ifndef TGNMLEN
  57 #define TGNMLEN 256
  58 #endif
  59 
  60 #define MC_HISTORY_VFS_PASSWORD       "mc.vfs.password"
  61 
  62 /*
  63  * FIXME2, the "-993" is to reduce the chance of a hit on the first lookup.
  64  */
  65 #define GUID_DEFAULT_CONST -993
  66 
  67 /*** file scope type declarations ****************************************************************/
  68 
  69 /*** forward declarations (file scope functions) *************************************************/
  70 
  71 /*** file scope variables ************************************************************************/
  72 
  73 /* --------------------------------------------------------------------------------------------- */
  74 /*** file scope functions ************************************************************************/
  75 /* --------------------------------------------------------------------------------------------- */
  76 
  77 /* --------------------------------------------------------------------------------------------- */
  78 /*** public functions ****************************************************************************/
  79 /* --------------------------------------------------------------------------------------------- */
  80 /** Get current username
  81  *
  82  * @return g_malloc()ed string with the name of the currently logged in
  83  *         user ("anonymous" if uid is not registered in the system)
  84  */
  85 
  86 char *
  87 vfs_get_local_username (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  88 {
  89     struct passwd *p_i;
  90 
  91     p_i = getpwuid (geteuid ());
  92 
  93     /* Unknown UID, strange */
  94     return (p_i != NULL && p_i->pw_name != NULL) ? g_strdup (p_i->pw_name) : g_strdup ("anonymous");
  95 }
  96 
  97 /* --------------------------------------------------------------------------------------------- */
  98 /**
  99  * Look up a user or group name from a uid/gid, maintaining a cache.
 100  * FIXME, for now it's a one-entry cache.
 101  * This file should be modified for non-unix systems to do something
 102  * reasonable.
 103  */
 104 
 105 int
 106 vfs_finduid (const char *uname)
     /* [previous][next][first][last][top][bottom][index][help]  */
 107 {
 108     static int saveuid = GUID_DEFAULT_CONST;
 109     static char saveuname[TUNMLEN] = "\0";
 110 
 111     size_t uname_len;
 112 
 113     uname_len = strlen (uname);
 114 
 115     if (uname[0] != saveuname[0]        /* Quick test w/o proc call */
 116         || strncmp (uname, saveuname, MIN (uname_len, TUNMLEN - 1)) != 0)
 117     {
 118         struct passwd *pw;
 119 
 120         g_strlcpy (saveuname, uname, TUNMLEN);
 121         pw = getpwnam (uname);
 122         if (pw != NULL)
 123             saveuid = pw->pw_uid;
 124         else
 125         {
 126             static int my_uid = GUID_DEFAULT_CONST;
 127 
 128             if (my_uid < 0)
 129                 my_uid = getuid ();
 130 
 131             saveuid = my_uid;
 132         }
 133     }
 134 
 135     return saveuid;
 136 }
 137 
 138 /* --------------------------------------------------------------------------------------------- */
 139 
 140 int
 141 vfs_findgid (const char *gname)
     /* [previous][next][first][last][top][bottom][index][help]  */
 142 {
 143     static int savegid = GUID_DEFAULT_CONST;
 144     static char savegname[TGNMLEN] = "\0";
 145 
 146     size_t gname_len;
 147 
 148     gname_len = strlen (gname);
 149 
 150     if (gname[0] != savegname[0]        /* Quick test w/o proc call */
 151         || strncmp (gname, savegname, MIN (gname_len, TGNMLEN - 1)) != 0)
 152     {
 153         struct group *gr;
 154 
 155         g_strlcpy (savegname, gname, TGNMLEN);
 156         gr = getgrnam (gname);
 157         if (gr != NULL)
 158             savegid = gr->gr_gid;
 159         else
 160         {
 161             static int my_gid = GUID_DEFAULT_CONST;
 162 
 163             if (my_gid < 0)
 164                 my_gid = getgid ();
 165 
 166             savegid = my_gid;
 167         }
 168     }
 169 
 170     return savegid;
 171 }
 172 
 173 /* --------------------------------------------------------------------------------------------- */
 174 /**
 175  * Create a temporary file with a name resembling the original.
 176  * This is needed e.g. for local copies requested by extfs.
 177  * Some extfs scripts may look at the extension.
 178  * We also protect stupid scripts against dangerous names.
 179  */
 180 
 181 int
 182 vfs_mkstemps (vfs_path_t ** pname_vpath, const char *prefix, const char *param_basename)
     /* [previous][next][first][last][top][bottom][index][help]  */
 183 {
 184     const char *p;
 185     GString *suffix;
 186     int shift;
 187     int fd;
 188 
 189     /* Strip directories */
 190     p = strrchr (param_basename, PATH_SEP);
 191     if (p == NULL)
 192         p = param_basename;
 193     else
 194         p++;
 195 
 196     /* Protection against very long names */
 197     shift = strlen (p) - (MC_MAXPATHLEN - 16);
 198     if (shift > 0)
 199         p += shift;
 200 
 201     suffix = g_string_sized_new (32);
 202 
 203     /* Protection against unusual characters */
 204     for (; *p != '\0' && *p != '#'; p++)
 205         if (strchr (".-_@", *p) != NULL || g_ascii_isalnum (*p))
 206             g_string_append_c (suffix, *p);
 207 
 208     fd = mc_mkstemps (pname_vpath, prefix, suffix->str);
 209     g_string_free (suffix, TRUE);
 210 
 211     return fd;
 212 }
 213 
 214 /* --------------------------------------------------------------------------------------------- */
 215 /**  Extract the hostname and username from the path
 216  *
 217  * Format of the path is [user@]hostname:port/remote-dir, e.g.:
 218  *
 219  * ftp://sunsite.unc.edu/pub/linux
 220  * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
 221  * ftp://tsx-11.mit.edu:8192/
 222  * ftp://joe@foo.edu:11321/private
 223  * ftp://joe:password@foo.se
 224  *
 225  * @param path is an input string to be parsed
 226  * @param default_port is an input default port
 227  * @param flags are parsing modifier flags (@see vfs_url_flags_t)
 228  *
 229  * @return g_malloc()ed url info.
 230  *         If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
 231  *         is not set, then the current login name is supplied.
 232  *         Return value is a g_malloc()ed structure with the pathname relative to the
 233  *         host.
 234  */
 235 
 236 vfs_path_element_t *
 237 vfs_url_split (const char *path, int default_port, vfs_url_flags_t flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 238 {
 239     vfs_path_element_t *path_element;
 240 
 241     char *pcopy;
 242     size_t pcopy_len;
 243     const char *pend;
 244     char *colon, *at, *rest;
 245 
 246     path_element = g_new0 (vfs_path_element_t, 1);
 247     path_element->port = default_port;
 248 
 249     pcopy_len = strlen (path);
 250     pcopy = g_strndup (path, pcopy_len);
 251     pend = pcopy + pcopy_len;
 252 
 253     if ((flags & URL_NOSLASH) == 0)
 254     {
 255         char *dir;
 256 
 257         /* locate path component */
 258         dir = strchr (pcopy, PATH_SEP);
 259 
 260         if (dir == NULL)
 261             path_element->path = g_strdup (PATH_SEP_STR);
 262         else
 263         {
 264             path_element->path = g_strndup (dir, pcopy_len - (size_t) (dir - pcopy));
 265             *dir = '\0';
 266         }
 267     }
 268 
 269     /* search for any possible user */
 270     at = strrchr (pcopy, '@');
 271 
 272     /* We have a username */
 273     if (at == NULL)
 274         rest = pcopy;
 275     else
 276     {
 277         char *inner_colon;
 278 
 279         *at = '\0';
 280         inner_colon = strchr (pcopy, ':');
 281         if (inner_colon != NULL)
 282         {
 283             *inner_colon = '\0';
 284             inner_colon++;
 285             path_element->password = g_strdup (inner_colon);
 286         }
 287 
 288         if (*pcopy != '\0')
 289             path_element->user = g_strdup (pcopy);
 290 
 291         if (pend == at + 1)
 292             rest = at;
 293         else
 294             rest = at + 1;
 295     }
 296 
 297     if ((flags & URL_USE_ANONYMOUS) == 0)
 298     {
 299         g_free (path_element->user);
 300         path_element->user = vfs_get_local_username ();
 301     }
 302     /* Check if the host comes with a port spec, if so, chop it */
 303     if (*rest != '[')
 304         colon = strchr (rest, ':');
 305     else
 306     {
 307         colon = strchr (++rest, ']');
 308         if (colon != NULL)
 309         {
 310             colon[0] = '\0';
 311             colon[1] = '\0';
 312             colon++;
 313         }
 314         else
 315         {
 316             vfs_path_element_free (path_element);
 317             g_free (pcopy);
 318             return NULL;
 319         }
 320     }
 321 
 322     if (colon != NULL)
 323     {
 324         *colon = '\0';
 325         /* cppcheck-suppress invalidscanf */
 326         if (sscanf (colon + 1, "%d", &path_element->port) == 1)
 327         {
 328             if (path_element->port <= 0 || path_element->port >= 65536)
 329                 path_element->port = default_port;
 330         }
 331         else
 332             while (*(++colon) != '\0')
 333             {
 334                 switch (*colon)
 335                 {
 336                 case 'C':
 337                     path_element->port = 1;
 338                     break;
 339                 case 'r':
 340                     path_element->port = 2;
 341                     break;
 342                 default:
 343                     break;
 344                 }
 345             }
 346     }
 347 
 348     path_element->host = g_strdup (rest);
 349     g_free (pcopy);
 350 #ifdef HAVE_CHARSET
 351     path_element->dir.converter = INVALID_CONV;
 352 #endif
 353 
 354     return path_element;
 355 }
 356 
 357 /* --------------------------------------------------------------------------------------------- */
 358 
 359 void __attribute__ ((noreturn)) vfs_die (const char *m)
     /* [previous][next][first][last][top][bottom][index][help]  */
 360 {
 361     message (D_ERROR, _("Internal error:"), "%s", m);
 362     exit (EXIT_FAILURE);
 363 }
 364 
 365 /* --------------------------------------------------------------------------------------------- */
 366 
 367 char *
 368 vfs_get_password (const char *msg)
     /* [previous][next][first][last][top][bottom][index][help]  */
 369 {
 370     return input_dialog (msg, _("Password:"), MC_HISTORY_VFS_PASSWORD, INPUT_PASSWORD,
 371                          INPUT_COMPLETE_NONE);
 372 }
 373 
 374 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */