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

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