main(int argc,
     char **argv)
{
   int i, gn;
   int test = 0;
   char *action = NULL, *cmd;
#ifdef HAVE_EEZE_MOUNT
   Eina_Bool mnt = EINA_FALSE;
   const char *act = NULL;
#endif
   gid_t gid, gl[65536], egid;

   for (i = 1; i < argc; i++)
     {
        if ((!strcmp(argv[i], "-h")) ||
            (!strcmp(argv[i], "-help")) ||
            (!strcmp(argv[i], "--help")))
          {
             printf(
               "This is an internal tool for Enlightenment.\n"
               "do not use it.\n"
               );
             exit(0);
          }
     }
   if (argc >= 3)
     {
        if ((argc == 3) && (!strcmp(argv[1], "-t")))
          {
             test = 1;
             action = argv[2];
          }
#ifdef HAVE_EEZE_MOUNT
        else
          {
             const char *s;

             s = strrchr(argv[1], '/');
             if ((!s) || (!s[1])) exit(1);  /* eeze always uses complete path */
             s++;
             if (strcmp(s, "mount") && strcmp(s, "umount") && strcmp(s, "eject")) exit(1);
             mnt = EINA_TRUE;
             act = s;
             action = argv[1];
          }
#endif
     }
   else if (argc == 2)
     {
        action = argv[1];
     }
   else
     {
        exit(1);
     }
   if (!action) exit(1);

   eina_init();

   uid = getuid();
   gid = getgid();
   egid = getegid();
   gn = getgroups(65536, gl);
   if (gn < 0)
     {
        printf("ERROR: MEMBER OF MORE THAN 65536 GROUPS\n");
        exit(3);
     }
   if (setuid(0) != 0)
     {
        printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n");
        exit(5);
     }
   if (setgid(0) != 0)
     {
        printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n");
        exit(7);
     }

   if (!auth_action_ok(action, gid, gl, gn, egid))
     {
        printf("ERROR: ACTION NOT ALLOWED: %s\n", action);
        exit(10);
     }
   /* we can add more levels of auth here */

   /* when mounting, this will match the exact path to the exe,
    * as required in sysactions.conf
    * this is intentionally pedantic for security
    */
   cmd = eina_hash_find(actions, action);
   if (!cmd)
     {
        printf("ERROR: UNDEFINED ACTION: %s\n", action);
        exit(20);
     }

   /* sanitize environment */
#ifdef HAVE_UNSETENV
# define NOENV(x) unsetenv(x)
   /* pass 1 - just nuke known dangerous env vars brutally if possible via
    * unsetenv(). if you don't have unsetenv... there's pass 2 and 3 */
   NOENV("IFS");
   NOENV("CDPATH");
   NOENV("LOCALDOMAIN");
   NOENV("RES_OPTIONS");
   NOENV("HOSTALIASES");
   NOENV("NLSPATH");
   NOENV("PATH_LOCALE");
   NOENV("COLORTERM");
   NOENV("LANG");
   NOENV("LANGUAGE");
   NOENV("LINGUAS");
   NOENV("TERM");
   NOENV("LD_PRELOAD");
   NOENV("LD_LIBRARY_PATH");
   NOENV("SHLIB_PATH");
   NOENV("LIBPATH");
   NOENV("AUTHSTATE");
   NOENV("DYLD_*");
   NOENV("KRB_CONF*");
   NOENV("KRBCONFDIR");
   NOENV("KRBTKFILE");
   NOENV("KRB5_CONFIG*");
   NOENV("KRB5_KTNAME");
   NOENV("VAR_ACE");
   NOENV("USR_ACE");
   NOENV("DLC_ACE");
   NOENV("TERMINFO");
   NOENV("TERMINFO_DIRS");
   NOENV("TERMPATH");
   NOENV("TERMCAP");
   NOENV("ENV");
   NOENV("BASH_ENV");
   NOENV("PS4");
   NOENV("GLOBIGNORE");
   NOENV("SHELLOPTS");
   NOENV("JAVA_TOOL_OPTIONS");
   NOENV("PERLIO_DEBUG");
   NOENV("PERLLIB");
   NOENV("PERL5LIB");
   NOENV("PERL5OPT");
   NOENV("PERL5DB");
   NOENV("FPATH");
   NOENV("NULLCMD");
   NOENV("READNULLCMD");
   NOENV("ZDOTDIR");
   NOENV("TMPPREFIX");
   NOENV("PYTHONPATH");
   NOENV("PYTHONHOME");
   NOENV("PYTHONINSPECT");
   NOENV("RUBYLIB");
   NOENV("RUBYOPT");
# ifdef HAVE_ENVIRON
   if (environ)
     {
        int again;
        char *tmp, *p;

        /* go over environment array again and again... safely */
        do
          {
             again = 0;

             /* walk through and find first entry that we don't like */
             for (i = 0; environ[i]; i++)
               {
                  /* if it begins with any of these, it's possibly nasty */
                  if ((!strncmp(environ[i], "LD_", 3)) ||
                      (!strncmp(environ[i], "_RLD_", 5)) ||
                      (!strncmp(environ[i], "LC_", 3)) ||
                      (!strncmp(environ[i], "LDR_", 3)))
                    {
                       /* unset it */
                       tmp = strdup(environ[i]);
                       if (!tmp) abort();
                       p = strchr(tmp, '=');
                       if (!p) abort();
                       *p = 0;
                       NOENV(tmp);
                       free(tmp);
                       /* and mark our do to try again from the start in case
                        * unsetenv changes environ ptr */
                       again = 1;
                       break;
                    }
               }
          }
        while (again);
     }
# endif
#endif

   /* pass 2 - clear entire environment so it doesn't exist at all. if you
    * can't do this... you're possibly in trouble... but the worst is still
    * fixed in pass 3 */
#ifdef HAVE_CLEARENV
   clearenv();
#else
# ifdef HAVE_ENVIRON
   environ = NULL;
# endif
#endif

   /* pass 3 - set path and ifs to minimal defaults */
   putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin");
   putenv("IFS= \t\n");

   if ((!test)
#ifdef HAVE_EEZE_MOUNT
       && (!mnt)
#endif
       )
     return system(cmd);
#ifdef HAVE_EEZE_MOUNT
   if (mnt)
     {
        int ret = 0;
        const char *mp = NULL;
        Eina_Strbuf *buf = NULL;

        if (!act) exit(40);
        if (!mount_args_check(argc, argv, act)) exit(40);
        /* all options are deemed safe at this point, so away we go! */
        if (!strcmp(act, "mount"))
          {
             struct stat s;

             mp = argv[5];
             if (stat("/media", &s))
               {
                  mode_t um;

                  um = umask(0);
                  if (mkdir("/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
                    {
                       printf("ERROR: COULD NOT CREATE DIRECTORY /media\n");
                       exit(40);
                    }
                  umask(um);
               }
             else if (!S_ISDIR(s.st_mode))
               {
                  printf("ERROR: NOT A DIRECTORY: /media\n");
                  exit(40);
               }

             if (stat(mp, &s))
               {
                  mode_t um;

                  um = umask(0);
                  if (mkdir(mp, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
                    {
                       printf("ERROR: COULD NOT CREATE DIRECTORY %s\n", mp);
                       exit(40);
                    }
                  umask(um);
               }
             else if (!S_ISDIR(s.st_mode))
               {
                  printf("ERROR: NOT A DIRECTORY: %s\n", mp);
                  exit(40);
               }
          }
        buf = eina_strbuf_new();
        if (!buf) exit(30);
        for (i = 1; i < argc; i++)
          eina_strbuf_append_printf(buf, "%s ", argv[i]);
        ret = system(eina_strbuf_string_get(buf));
        if ((!strcmp(act, "umount")) && (!ret))
          {
             Eina_Iterator *it;
             char path[PATH_MAX];
             const char *s;
             struct stat st;
             Eina_Bool rm = EINA_TRUE;

             mp = strrchr(argv[2], '/');
             if (!mp) return ret;
             snprintf(path, sizeof(path), "/media%s", mp);
             if (stat(path, &st)) return ret;
             if (!S_ISDIR(st.st_mode)) return ret;
             it = eina_file_ls(path);
             EINA_ITERATOR_FOREACH(it, s)
               {
                  /* don't delete any directories with files in them */
                  rm = EINA_FALSE;
                  eina_stringshare_del(s);
               }
             if (rm)
               {
                  if (rmdir(path))
                    printf("ERROR: COULD NOT UNLINK MOUNT POINT %s\n", path);
               }
          }
        return ret;
     }
#endif
   eina_shutdown();

   return 0;
}
main(int argc,
     char **argv)
{
   int i, gn;
   int test = 0;
   char *action = NULL, *cmd;
#ifdef HAVE_EEZE_MOUNT
   Eina_Bool mnt = EINA_FALSE;
   const char *act = NULL;
#endif
   gid_t gid, gl[65536], egid;

   for (i = 1; i < argc; i++)
     {
        if ((!strcmp(argv[i], "-h")) ||
            (!strcmp(argv[i], "-help")) ||
            (!strcmp(argv[i], "--help")))
          {
             printf(
               "This is an internal tool for Enlightenment.\n"
               "do not use it.\n"
               );
             exit(0);
          }
     }
   if (argc >= 3)
     {
        if ((argc == 3) && (!strcmp(argv[1], "-t")))
          {
             test = 1;
             action = argv[2];
          }
#ifdef HAVE_EEZE_MOUNT
        else
          {
             const char *s;

             s = strrchr(argv[1], '/');
             if ((!s) || (!s[1])) exit(1);   
             s++;
             if (strcmp(s, "mount") && strcmp(s, "umount") && strcmp(s, "eject")) exit(1);
             mnt = EINA_TRUE;
             act = s;
             action = argv[1];
          }
#endif
     }
   else if (argc == 2)
     {
        action = argv[1];
     }
   else
     {
        exit(1);
     }
   if (!action) exit(1);

   eina_init();

   uid = getuid();
   gid = getgid();
   egid = getegid();
   gn = getgroups(65536, gl);
   if (gn < 0)
     {
        printf("ERROR: MEMBER OF MORE THAN 65536 GROUPS\n");
        exit(3);
     }
   if (setuid(0) != 0)
     {
        printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n");
        exit(5);
     }
   if (setgid(0) != 0)
     {
        printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n");
        exit(7);
     }

   if (!auth_action_ok(action, gid, gl, gn, egid))
     {
        printf("ERROR: ACTION NOT ALLOWED: %s\n", action);
        exit(10);
     }
    

    
   cmd = eina_hash_find(actions, action);
   if (!cmd)
     {
        printf("ERROR: UNDEFINED ACTION: %s\n", action);
        exit(20);
     }

    
#ifdef HAVE_UNSETENV
# define NOENV(x) unsetenv(x)
    
   NOENV("IFS");
   NOENV("CDPATH");
   NOENV("LOCALDOMAIN");
   NOENV("RES_OPTIONS");
   NOENV("HOSTALIASES");
   NOENV("NLSPATH");
   NOENV("PATH_LOCALE");
   NOENV("COLORTERM");
   NOENV("LANG");
   NOENV("LANGUAGE");
   NOENV("LINGUAS");
   NOENV("TERM");
   NOENV("LD_PRELOAD");
   NOENV("LD_LIBRARY_PATH");
   NOENV("SHLIB_PATH");
   NOENV("LIBPATH");
   NOENV("AUTHSTATE");
   NOENV("DYLD_*");
   NOENV("KRB_CONF*");
   NOENV("KRBCONFDIR");
   NOENV("KRBTKFILE");
   NOENV("KRB5_CONFIG*");
   NOENV("KRB5_KTNAME");
   NOENV("VAR_ACE");
   NOENV("USR_ACE");
   NOENV("DLC_ACE");
   NOENV("TERMINFO");
   NOENV("TERMINFO_DIRS");
   NOENV("TERMPATH");
   NOENV("TERMCAP");
   NOENV("ENV");
   NOENV("BASH_ENV");
   NOENV("PS4");
   NOENV("GLOBIGNORE");
   NOENV("SHELLOPTS");
   NOENV("JAVA_TOOL_OPTIONS");
   NOENV("PERLIO_DEBUG");
   NOENV("PERLLIB");
   NOENV("PERL5LIB");
   NOENV("PERL5OPT");
   NOENV("PERL5DB");
   NOENV("FPATH");
   NOENV("NULLCMD");
   NOENV("READNULLCMD");
   NOENV("ZDOTDIR");
   NOENV("TMPPREFIX");
   NOENV("PYTHONPATH");
   NOENV("PYTHONHOME");
   NOENV("PYTHONINSPECT");
   NOENV("RUBYLIB");
   NOENV("RUBYOPT");
# ifdef HAVE_ENVIRON
   if (environ)
     {
        int again;
        char *tmp, *p;

         
        do
          {
             again = 0;

              
             for (i = 0; environ[i]; i++)
               {
                   
                  if ((!strncmp(environ[i], "LD_", 3)) ||
                      (!strncmp(environ[i], "_RLD_", 5)) ||
                      (!strncmp(environ[i], "LC_", 3)) ||
                      (!strncmp(environ[i], "LDR_", 3)))
                    {
                        
                       tmp = strdup(environ[i]);
                       if (!tmp) abort();
                       p = strchr(tmp, '=');
                       if (!p) abort();
                       *p = 0;
                       NOENV(tmp);
                       free(tmp);
                        
                       again = 1;
                       break;
                    }
               }
          }
        while (again);
     }
# endif
#endif

    
#ifdef HAVE_CLEARENV
   clearenv();
#else
# ifdef HAVE_ENVIRON
   environ = NULL;
# endif
#endif

    
   putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin");
   putenv("IFS= \t\n");

   if ((!test)
#ifdef HAVE_EEZE_MOUNT
       && (!mnt)
#endif
       )
     return system(cmd);
#ifdef HAVE_EEZE_MOUNT
   if (mnt)
     {
        int ret = 0;
        const char *mp = NULL;
        Eina_Strbuf *buf = NULL;

        if (!act) exit(40);
        if (!mount_args_check(argc, argv, act)) exit(40);
         
        if (!strcmp(act, "mount"))
          {
             struct stat s;

             mp = argv[5];
             if (stat("/media", &s))
               {
                  mode_t um;

                  um = umask(0);
                  if (mkdir("/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
                    {
                       printf("ERROR: COULD NOT CREATE DIRECTORY /media\n");
                       exit(40);
                    }
                  umask(um);
               }
             else if (!S_ISDIR(s.st_mode))
               {
                  printf("ERROR: NOT A DIRECTORY: /media\n");
                  exit(40);
               }

             if (stat(mp, &s))
               {
                  mode_t um;

                  um = umask(0);
                  if (mkdir(mp, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
                    {
                       printf("ERROR: COULD NOT CREATE DIRECTORY %s\n", mp);
                       exit(40);
                    }
                  umask(um);
               }
             else if (!S_ISDIR(s.st_mode))
               {
                  printf("ERROR: NOT A DIRECTORY: %s\n", mp);
                  exit(40);
               }
          }
        buf = eina_strbuf_new();
        if (!buf) exit(30);
        for (i = 1; i < argc; i++)
          eina_strbuf_append_printf(buf, "%s ", argv[i]);
        ret = system(eina_strbuf_string_get(buf));
        if ((!strcmp(act, "umount")) && (!ret))
          {
             Eina_Iterator *it;
             char path[PATH_MAX];
             const char *s;
             struct stat st;
             Eina_Bool rm = EINA_TRUE;

             mp = strrchr(argv[2], '/');
             if (!mp) return ret;
             snprintf(path, sizeof(path), "/media%s", mp);
             if (stat(path, &st)) return ret;
             if (!S_ISDIR(st.st_mode)) return ret;
             it = eina_file_ls(path);
             EINA_ITERATOR_FOREACH(it, s)
               {
                   
                  rm = EINA_FALSE;
                  eina_stringshare_del(s);
               }
             if (rm)
               {
                  if (rmdir(path))
                    printf("ERROR: COULD NOT UNLINK MOUNT POINT %s\n", path);
               }
          }
        return ret;
     }
#endif
   eina_shutdown();

   return 0;
}