Loading commands/filesystem/chown.cpp +11 −7 Changes for commands/filesystem/chown.cpp: 11 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -54,15 +54,17 @@ namespace fresh { namespace cmd { ChownCommand():ShellCommand("chown"){} static bool chownOne(const uid_r_t &uid,bool haveUid,const gid_r_t &gid,bool haveGid, const std::string &path,bool recursive){ const std::string &path,bool recursive,bool follow){ // follow: a symlink operand means its target (POSIX), not // with -h and never below -R struct stat st; if(lstat(path.c_str(),&st)!=0){ if((follow ? stat(path.c_str(),&st) : lstat(path.c_str(),&st))!=0){ std::cerr << "chown: " << path << ": " << strerror(errno) << std::endl; return false; } bool ok=true; if(ids::chownPath(path,false,haveUid ? &uid : nullptr,haveGid ? &gid : nullptr)!=0){ if(ids::chownPath(path,follow,haveUid ? &uid : nullptr,haveGid ? &gid : nullptr)!=0){ std::cerr << "chown: " << path << ": " << strerror(errno) << std::endl; ok=false; } Loading @@ -78,7 +80,7 @@ namespace fresh { namespace cmd { std::string child=path; if(!child.empty() && child.back()!='/') child+="/"; child+=name; if(!chownOne(uid,haveUid,gid,haveGid,child,true)) if(!chownOne(uid,haveUid,gid,haveGid,child,true,false)) ok=false; } closedir(d); Loading @@ -88,15 +90,17 @@ namespace fresh { namespace cmd { } int runCommand(int argc,const char **argv){ bool recursive=false; bool recursive=false,noDeref=false; int i=1; for(; i<argc; ++i){ std::string a=argv[i]; if(a=="-R" || a=="--recursive") recursive=true; else if(a=="-h" || a=="--no-dereference") noDeref=true; else if(a=="-Rh" || a=="-hR"){ recursive=true; noDeref=true; } else break; } if(i+1>=argc){ std::cerr << "chown: usage: chown [-R] OWNER[:GROUP] FILE..." << std::endl; std::cerr << "chown: usage: chown [-R] [-h] OWNER[:GROUP] FILE..." << std::endl; return 1; } Loading Loading @@ -129,7 +133,7 @@ namespace fresh { namespace cmd { bool ok=true; for(; i<argc; ++i) if(!chownOne(uid,haveUid,gid,haveGid,argv[i],recursive)) if(!chownOne(uid,haveUid,gid,haveGid,argv[i],recursive,!noDeref && !recursive)) ok=false; return ok ? 0 : 1; } Loading commands/system/umount.cpp +8 −6 Changes for commands/system/umount.cpp: 8 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <iostream> #include <string> #include <vector> #include <cstring> #include <cerrno> Loading @@ -43,16 +44,16 @@ namespace fresh { namespace cmd { int runCommand(int argc,const char **argv){ bool force=false; bool lazy=false; std::string target; std::vector<std::string> targets; for(int i=1;i<argc;++i){ std::string a=argv[i]; if(a=="-f") force=true; else if(a=="-l") lazy=true; else target=a; else targets.push_back(a); } if(target.empty()){ if(targets.empty()){ std::cerr << "umount: missing operand" << std::endl; return 1; } Loading @@ -61,12 +62,13 @@ namespace fresh { namespace cmd { if(force) flags|=MNT_FORCE; if(lazy) flags|=MNT_DETACH; int rc=0; for(auto &target: targets) if(::umount2(target.c_str(),flags)!=0){ std::cerr << "umount: " << target << ": " << strerror(errno) << std::endl; return 1; rc=1; } return 0; return rc; } }; Loading src/shell.cpp +29 −0 Changes for src/shell.cpp: 29 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <glob.h> #include "shell.h" #include <sys/uid_r.h> #include "envoirment.h" // The asynchronous handler does only an async-signal-safe flag store. Trap Loading Loading @@ -532,6 +533,34 @@ std::vector<std::string> fresh::tokenizeShellArgs(const std::string &segment){ continue; } // Tilde expansion (POSIX 2.6.1): an unquoted '~' starting a word, // up to the first '/', is $HOME ("~") or the named user's home // directory ("~name", also a UUID or GUID user); unknown users // stay literal. The result is neither split nor globbed. if(!have && c=='~'){ size_t k=i+1; while(k<n && segment[k]!='/' && !strchr(" \t\n;|&<>()'\"\\$`",segment[k])) ++k; if(k>=n || segment[k]=='/' || strchr(" \t\n;|&<>()",segment[k])){ std::string user=segment.substr(i+1,k-i-1),dir; bool found=false; if(user.empty()){ const char *home=getenv("HOME"); if(home){ dir=home; found=true; } }else if(struct passwd_id_r *pw=getpwnam_id_r(user.c_str())){ dir=pw->pw_dir ? pw->pw_dir : ""; found=true; } if(found){ current+=dir; have=true; anyquoted=true; i=k; continue; } } } // Redirection operators are metacharacters: they end whatever word // was being built and form their own token, even glued directly // onto adjacent text with no whitespace ("cmd>file" behaves like Loading Loading
commands/filesystem/chown.cpp +11 −7 Changes for commands/filesystem/chown.cpp: 11 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -54,15 +54,17 @@ namespace fresh { namespace cmd { ChownCommand():ShellCommand("chown"){} static bool chownOne(const uid_r_t &uid,bool haveUid,const gid_r_t &gid,bool haveGid, const std::string &path,bool recursive){ const std::string &path,bool recursive,bool follow){ // follow: a symlink operand means its target (POSIX), not // with -h and never below -R struct stat st; if(lstat(path.c_str(),&st)!=0){ if((follow ? stat(path.c_str(),&st) : lstat(path.c_str(),&st))!=0){ std::cerr << "chown: " << path << ": " << strerror(errno) << std::endl; return false; } bool ok=true; if(ids::chownPath(path,false,haveUid ? &uid : nullptr,haveGid ? &gid : nullptr)!=0){ if(ids::chownPath(path,follow,haveUid ? &uid : nullptr,haveGid ? &gid : nullptr)!=0){ std::cerr << "chown: " << path << ": " << strerror(errno) << std::endl; ok=false; } Loading @@ -78,7 +80,7 @@ namespace fresh { namespace cmd { std::string child=path; if(!child.empty() && child.back()!='/') child+="/"; child+=name; if(!chownOne(uid,haveUid,gid,haveGid,child,true)) if(!chownOne(uid,haveUid,gid,haveGid,child,true,false)) ok=false; } closedir(d); Loading @@ -88,15 +90,17 @@ namespace fresh { namespace cmd { } int runCommand(int argc,const char **argv){ bool recursive=false; bool recursive=false,noDeref=false; int i=1; for(; i<argc; ++i){ std::string a=argv[i]; if(a=="-R" || a=="--recursive") recursive=true; else if(a=="-h" || a=="--no-dereference") noDeref=true; else if(a=="-Rh" || a=="-hR"){ recursive=true; noDeref=true; } else break; } if(i+1>=argc){ std::cerr << "chown: usage: chown [-R] OWNER[:GROUP] FILE..." << std::endl; std::cerr << "chown: usage: chown [-R] [-h] OWNER[:GROUP] FILE..." << std::endl; return 1; } Loading Loading @@ -129,7 +133,7 @@ namespace fresh { namespace cmd { bool ok=true; for(; i<argc; ++i) if(!chownOne(uid,haveUid,gid,haveGid,argv[i],recursive)) if(!chownOne(uid,haveUid,gid,haveGid,argv[i],recursive,!noDeref && !recursive)) ok=false; return ok ? 0 : 1; } Loading
commands/system/umount.cpp +8 −6 Changes for commands/system/umount.cpp: 8 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <iostream> #include <string> #include <vector> #include <cstring> #include <cerrno> Loading @@ -43,16 +44,16 @@ namespace fresh { namespace cmd { int runCommand(int argc,const char **argv){ bool force=false; bool lazy=false; std::string target; std::vector<std::string> targets; for(int i=1;i<argc;++i){ std::string a=argv[i]; if(a=="-f") force=true; else if(a=="-l") lazy=true; else target=a; else targets.push_back(a); } if(target.empty()){ if(targets.empty()){ std::cerr << "umount: missing operand" << std::endl; return 1; } Loading @@ -61,12 +62,13 @@ namespace fresh { namespace cmd { if(force) flags|=MNT_FORCE; if(lazy) flags|=MNT_DETACH; int rc=0; for(auto &target: targets) if(::umount2(target.c_str(),flags)!=0){ std::cerr << "umount: " << target << ": " << strerror(errno) << std::endl; return 1; rc=1; } return 0; return rc; } }; Loading
src/shell.cpp +29 −0 Changes for src/shell.cpp: 29 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <glob.h> #include "shell.h" #include <sys/uid_r.h> #include "envoirment.h" // The asynchronous handler does only an async-signal-safe flag store. Trap Loading Loading @@ -532,6 +533,34 @@ std::vector<std::string> fresh::tokenizeShellArgs(const std::string &segment){ continue; } // Tilde expansion (POSIX 2.6.1): an unquoted '~' starting a word, // up to the first '/', is $HOME ("~") or the named user's home // directory ("~name", also a UUID or GUID user); unknown users // stay literal. The result is neither split nor globbed. if(!have && c=='~'){ size_t k=i+1; while(k<n && segment[k]!='/' && !strchr(" \t\n;|&<>()'\"\\$`",segment[k])) ++k; if(k>=n || segment[k]=='/' || strchr(" \t\n;|&<>()",segment[k])){ std::string user=segment.substr(i+1,k-i-1),dir; bool found=false; if(user.empty()){ const char *home=getenv("HOME"); if(home){ dir=home; found=true; } }else if(struct passwd_id_r *pw=getpwnam_id_r(user.c_str())){ dir=pw->pw_dir ? pw->pw_dir : ""; found=true; } if(found){ current+=dir; have=true; anyquoted=true; i=k; continue; } } } // Redirection operators are metacharacters: they end whatever word // was being built and form their own token, even glued directly // onto adjacent text with no whitespace ("cmd>file" behaves like Loading