// Return temporary directory. FXString FXSystem::getTempDirectory(){ #ifndef WIN32 const FXchar* dir; if((dir=getenv("TMPDIR"))!=NULL){ return FXString(dir); } return FXString("/tmp"); #else TCHAR buffer[MAXPATHLEN]; DWORD len=GetTempPath(MAXPATHLEN,buffer); if(1<len && ISPATHSEP(buffer[len-1]) && !ISPATHSEP(buffer[len-2])) len--; return FXString(buffer,len); #endif }
void EvalMakePath(const void *data, qCtx *ctx, qStr *out, qArgAry *args) { VALID_ARGC("makepath", 2, 2); CStr path1 = (*args)[0]; CStr path2 = (*args)[1]; fslash(path1.SafeP()); fslash(path2.SafeP()); #ifdef WIN32 path1.RTrim(DIRSEP); path2.LTrim(DIRSEP); path1.RTrim('/'); path2.LTrim('/'); #else path1.RTrim(DIRSEP); path2.LTrim(DIRSEP); #endif out->PutS(path1); #ifdef WIN32 if (path1.Length() > 0 && !ISPATHSEP(path1.SafeP()[path1.Length()-1])) #endif out->PutC(DIRSEP); out->PutS(path2); }
bool _ScanDir(CStr path, int mask, CStr body, qCtx *ctx, qStr *out, DIRSTATE &st) { BOOL bMore; HANDLE hFind; BOOL showdot = false; // truncate trailing slashes char *b = path.GetBuffer(); if (!b || !*b) return false; char *p = path+path.Length() - 1; while (p >= b && ISDIRSEP(*p)) --p; if (p-b+1 > 0) { if (*p == ':') { showdot = true; if (!ISDIRSEP(p[1])) { path << '.'; b = path.GetBuffer(); p = path+path.Length() - 1; } else ++p; } st.path = path; // truncate path to parent while (p >= b && !ISPATHSEP(*p)) --p; if (p >= b) { st.path.Grow(p-b+1); } else { st.path.Grow(0); } } else { st.path = path; } // read all entries in the directory WIN32_FIND_DATA *r = &st.data; hFind = FindFirstFile(path, r); bMore = (hFind != (HANDLE) -1); while (bMore &&!st.bquit) { if ((mask & r->dwFileAttributes) && !(r->cFileName[0]=='.'&&r->cFileName[1]=='\0') ) { ctx->Parse(body, out); } else if (showdot && r->cFileName[0]=='.'&&r->cFileName[1]=='\0') { ctx->Parse(body, out); } bMore = FindNextFile(hFind, r); } FindClose(hFind); return true; } // dir_scan
static const char * keytab_name(const char *name, const char **type, size_t *type_len) { const char *residual; residual = strchr(name, ':'); if (residual == NULL || ISPATHSEP(name[0]) #ifdef _WIN32 /* Avoid treating <drive>:<path> as a keytab type * specification */ || name + 1 == residual #endif ) { *type = "FILE"; *type_len = strlen(*type); residual = name; } else { *type = name; *type_len = residual - name; residual++; } return residual; }
void EvalFileName(const void *data, qCtx *ctx, qStr *out, qArgAry *args) { VALID_ARGC("filename", 1, 1); CStr path = (*args)[0]; if (path) { const char *b = path; const char *r = b + path.Length() - 1; while (r >= b && !(ISPATHSEP(*r))) { --r; } ++r; out->PutS(r, path.Length() - (r - b)); } }
// Return the absolute path, based on the specified directory path // Remove terminating '/' on a path string to simplify a file or directory path // Thus '/bla/bla////' becomes '/bla/bla' // Special case : '/' stays to '/' FXString filePath(const FXString path, const FXString dir) { FXString in=path, out=path; while (1) { if (in[in.length()-1]=='/' && in.length()!=1) { out=in.trunc(in.length()-1); in=out; } else break; } // If absolute path if(ISPATHSEP(out[0])) return (out); else return (dir+PATHSEPSTRING+out); }
void EvalFilePath(const void *data, qCtx *ctx, qStr *out, qArgAry *args) { VALID_ARGC("filepath", 1, 1); CStr path = (*args)[0]; char *b = path.GetBuffer(); if (b) { char *r = b + path.Length() - 1; while (r >= b && !(ISPATHSEP(*r))) { --r; } if (r >= b) { *r = DIRSEP; ++r; *r = '\0'; path.Grow(r - b); out->PutS(path); } } }
// Recursively visit files and directories FXbool FXDirVisitor::traverse(const FXString& path){ FXStat data; if(FXStat::statLink(path,data)){ if(data.isDirectory()){ if(enter(path)){ FXDir directory(path); FXString name; while(directory.next(name)){ if(name[0]!='.' || (name[1]!=0 && (name[1]!='.' || name[2]!=0))){ if(!traverse(path+(ISPATHSEP(path.tail())?"":PATHSEPSTRING)+name)) break; } } return leave(path); } } else{ return visit(path); // Its a file } } return false; }
// Return the absolute path, based on the current directory path // Remove terminating '/' on a path string to simplify a file or directory path // Thus '/bla/bla////' becomes '/bla/bla' // Special case : '/' stays to '/' FXString filePath(const FXString path) { FXString in=path, out=path; while (1) { if (in[in.length()-1]=='/' && in.length()!=1) { out=in.trunc(in.length()-1); in=out; } else break; } FXString dir=FXSystem::getCurrentDirectory(); // If absolute path if(ISPATHSEP(out[0])) return (out); else return (dir+PATHSEPSTRING+out); }
int access(const char *filename, int mode) { char extension[_MAX_FNAME]; DWORD attribs; size_t extlen; const char *extptr; const char *begin, *end; int isx, hasext, trypathext = 0; /* once: get default PATHEXT or use empty exts */ if (!*exts) { DWORD rc; /* not initialized */ rc = GetEnvironmentVariable("PATHEXT", exts, sizeof(exts)); if ((rc == 0) || (rc >= sizeof(exts))) *exts = 0; } if (!filename) { errno = ENOENT; return (-1); } /* search for the extension starting at the end */ extptr = filename + strlen(filename) - 1; hasext = 0; while (extptr > filename && !ISPATHSEP(*extptr)) { if (*extptr == '.' && *(extptr - 1) != ':' && !ISPATHSEP(*(extptr - 1))) { hasext++; break; } extptr--; } if (hasext) attribs = get_file_attributes(filename, extptr, hasext, mode, &isx); else attribs = get_file_attributes(filename, "", hasext, mode, &isx); /* if mode != X_OK or file exists or filename already has an extension ignore PATHEXT */ if ((mode != X_OK) || (attribs != (DWORD)-1) || hasext) { begin = "."; end = ""; } else { /* dir/file name not found and no extension */ begin = exts; end = exts; trypathext = 1; } while (*begin) { if (trypathext) { extlen = pgetext(&begin, &end, extension, sizeof(extension)); if (!*begin) break; if (extlen) attribs = get_file_attributes(filename, extension, hasext, mode, &isx); else attribs = (DWORD)(-1); } if (attribs != (DWORD)(-1)) { /* file or directory found */ if (mode & X_OK) { if (attribs & FILE_ATTRIBUTE_DIRECTORY) break; /* appending pathext may find a directory ! */ if (trypathext || isx) return (0); break; } else if ((mode & W_OK) && (attribs & FILE_ATTRIBUTE_READONLY)) { break; } /* R_OK is always OK */ return (0); } begin = pgetnext(&begin, &end); } if (attribs == (DWORD)(-1)) errno = ENOENT; else errno = EACCES; return (-1); }
// Hit the accept button or enter in text field long FileSelector::onCmdAccept(FXObject*,FXSelector,void*) { FXSelector sel=accept->getSelector(); FXObject *tgt=accept->getTarget(); // Get (first) filename FXString path=getFilename(); // If filename is empty, we get the current directory if(path.empty()) { path=list->getDirectory(); filename->setText(path); } // Only do something if a selection was made if(!path.empty()) { // Is directory? if(::isDirectory(path)) { // In directory mode:- we got our answer! if(selectmode==SELECT_FILE_DIRECTORY || selectmode==SELECT_FILE_MULTIPLE_ALL || selectmode==SELECT_FILE_MIXED) { if(tgt) tgt->handle(accept,FXSEL(SEL_COMMAND,sel),(void*)1); return 1; } // Hop over to that directory list->setDirectory(path); pathlink->setPath(list->getDirectory()); pathtext->setText(list->getDirectory()); filename->setText(FXString::null); return 1; } // Get directory part of path FXString dir=FXPath::directory(path); // In file mode, directory part of path should exist if(::isDirectory(dir)) { // In any mode, existing directory part is good enough if(selectmode==SELECT_FILE_ANY) { if(tgt) tgt->handle(accept,FXSEL(SEL_COMMAND,sel),(void*)1); return 1; } // In existing mode, the whole filename must exist and be a file else if(selectmode==SELECT_FILE_EXISTING) { if(::isFile(path)) { if(tgt) tgt->handle(accept,FXSEL(SEL_COMMAND,sel),(void*)1); return 1; } } // In multiple mode, return if all selected files exist else if(selectmode==SELECT_FILE_MULTIPLE) { for(FXint i=0; i<list->getNumItems(); i++) { if(list->isItemSelected(i) && list->isItemFile(i)) { if(tgt) tgt->handle(accept,FXSEL(SEL_COMMAND,sel),(void*)1); return 1; } } } // Multiple files and/or directories else { for(FXint i=0; i<list->getNumItems(); i++) { if(list->isItemSelected(i) && list->getItemFilename(i)!="..") { if(tgt) tgt->handle(accept,FXSEL(SEL_COMMAND,sel),(void*)1); return 1; } } } } // Go up to the lowest directory which still exists while(!FXPath::isTopDirectory(dir) && !::isDirectory(dir)) dir=FXPath::upLevel(dir); // Switch as far as we could go list->setDirectory(dir); pathlink->setPath(list->getDirectory()); pathtext->setText(list->getDirectory()); // Put the tail end back for further editing if(ISPATHSEP(path[dir.length()])) path.erase(0,dir.length()+1); else path.erase(0,dir.length()); // Replace text box with new stuff filename->setText(path); filename->selectAll(); } return 1; }
// Perform match static bool domatch(const char *pattern,const char *string,FXuint flags){ register const char *p=pattern; register const char *q=string; register const char *s; register char c,cs,ce,cc,neg; register int level; while((c=*p++)!='\0'){ switch(c){ case '?': if(*q=='\0') return false; if((flags&FILEMATCH_FILE_NAME) && ISPATHSEP(*q)) return false; if((flags&FILEMATCH_PERIOD) && (*q=='.') && ((q==string) || ((flags&FILEMATCH_FILE_NAME) && ISPATHSEP(*(q-1))))) return false; q++; break; case '*': c=*p; while(c=='*') c=*++p; if((flags&FILEMATCH_PERIOD) && (*q=='.') && ((q==string) || ((flags&FILEMATCH_FILE_NAME) && ISPATHSEP(*(q-1))))) return false; if(c=='\0'){ // Optimize for case of trailing '*' if(flags&FILEMATCH_FILE_NAME){ for(s=q; *s; s++){ if(ISPATHSEP(*s)) return false; } } return 1; } while(!domatch(p,q,flags&~FILEMATCH_PERIOD)){ if((flags&FILEMATCH_FILE_NAME) && ISPATHSEP(*q)) return false; if(*q++=='\0') return false; } return 1; case '[': if(*q=='\0') return false; if((flags&FILEMATCH_PERIOD) && (*q=='.') && ((q==string) || ((flags&FILEMATCH_FILE_NAME) && ISPATHSEP(*(q-1))))) return false; cc=FOLD(*q); neg=((*p=='!') || (*p=='^')); if(neg) p++; c=*p++; do{ if(c=='\\' && !(flags&FILEMATCH_NOESCAPE)) c=*p++; cs=ce=FOLD(c); if(c=='\0') return false; c=*p++; c=FOLD(c); if((flags&FILEMATCH_FILE_NAME) && ISPATHSEP(c)) return false; if(c=='-' && *p!=']'){ c = *p++; if(c=='\\' && !(flags&FILEMATCH_NOESCAPE)) c=*p++; if(c=='\0') return false; ce=FOLD(c); c=*p++; } if(((FXuchar)cs)<=((FXuchar)cc) && ((FXuchar)cc)<=((FXuchar)ce)) goto match; } while(c!=']'); if(!neg) return false; q++; break; match: while(c!=']'){ if(c=='\0') return false; c=*p++; if(c=='\\' && !(flags&FILEMATCH_NOESCAPE)) p++; } if(neg) return false; q++; break; case '(': nxt: if(domatch(p,q,flags)) return true; for(level=0; *p && 0<=level; ){ switch(*p++){ case '\\': if(*p) p++; break; case '(': level++; break; case ')': level--; break; case '|': case ',': if (level==0) goto nxt; } } return false; case ')': break; case '|': case ',': for(level=0; *p && 0<=level; ){ switch(*p++){ case '\\': if(*p) p++; break; case '(': level++; break; case ')': level--; break; } } break; case '\\': if(*p && !(flags&FILEMATCH_NOESCAPE)) c=*p++; // Trailing escape represents itself default: if(FOLD(c)!=FOLD(*q)) return false; q++; break; } } return (*q=='\0') || (ISPATHSEP(*q) && (flags&FILEMATCH_LEADING_DIR)); }
// List all the files in directory FXint FXDir::listFiles(FXString*& filelist,const FXString& path,const FXString& pattern,FXuint flags){ FXDir dir(path); // Initialize to empty filelist=NULL; // Get directory stream pointer if(dir.isOpen()){ FXuint mode=(flags&CaseFold)?(FILEMATCH_FILE_NAME|FILEMATCH_NOESCAPE|FILEMATCH_CASEFOLD):(FILEMATCH_FILE_NAME|FILEMATCH_NOESCAPE); FXString *newlist; FXint size=0; FXint count=0; FXString pathname; FXString name; FXStat data; // Loop over directory entries while(dir.next(name)){ // Build full pathname pathname=path; if(!ISPATHSEP(pathname.tail())) pathname+=PATHSEPSTRING; pathname+=name; // Get info on file if(!FXStat::statFile(pathname,data)) continue; #ifdef WIN32 // Filter out files; a bit tricky... if(!data.isDirectory() && ((flags&NoFiles) || (data.isHidden() && !(flags&HiddenFiles)) || (!(flags&AllFiles) && !FXPath::match(pattern,name,mode)))) continue; // Filter out directories; even more tricky! if(data.isDirectory() && ((flags&NoDirs) || (data.isHidden() && !(flags&HiddenDirs)) || ((name[0]=='.' && (name[1]==0 || (name[1]=='.' && name[2]==0))) && (flags&NoParent)) || (!(flags&AllDirs) && !FXPath::match(pattern,name,mode)))) continue; #else // Filter out files; a bit tricky... if(!data.isDirectory() && ((flags&NoFiles) || (name[0]=='.' && !(flags&HiddenFiles)) || (!(flags&AllFiles) && !FXPath::match(pattern,name,mode)))) continue; // Filter out directories; even more tricky! if(data.isDirectory() && ((flags&NoDirs) || (name[0]=='.' && !(flags&HiddenDirs)) || ((name[0]=='.' && (name[1]==0 || (name[1]=='.' && name[2]==0))) && (flags&NoParent)) || (!(flags&AllDirs) && !FXPath::match(pattern,name,mode)))) continue; #endif // Grow list if(count+1>=size){ size=size?(size<<1):256; newlist=new FXString [size]; for(int i=0; i<count; i++){ newlist[i].adopt(filelist[i]); } delete [] filelist; filelist=newlist; } // Add to list filelist[count++].adopt(name); } return count; } return 0; }
int nt_execve(const char *prog, const char *const *args, const char *const *envir) { STARTUPINFO si; PROCESS_INFORMATION pi; enum {none, directex, shellex} execmode; DWORD exitcode; DWORD dwCreationflags; int priority; char *argv0; char *cmdstr, *cmdend; unsigned int cmdsize; size_t prognamelen, cmdlen; int hasext; char extension[_MAX_FNAME]; const char *begin, *end, *extptr; static char exts[MAX_PATH]; UNREFERENCED_PARAMETER(envir); /* get default PATHEXT or use empty exts */ if (!*exts) { DWORD rc; /* not initialized */ rc = GetEnvironmentVariable("PATHEXT", exts, sizeof(exts)); if ((rc == 0) || (rc >= sizeof(exts))) /* if error or PATHEXT too big will retry at the next call */ *exts = 0; } /* if prog has an extension initialize begin end to skip PATHEXT search */ prognamelen = strlen(prog); extptr = prog + prognamelen - 1; hasext = 0; while (extptr > prog && !ISPATHSEP(*extptr)) { if (*extptr == '.' && *(extptr - 1) != ':' && !ISPATHSEP(*(extptr - 1))) { hasext++; break; } extptr--; } if (hasext) { begin = "."; end = ""; strcpy(extension, extptr); } else { begin = exts; end = exts; *extension = '\0'; } argv0 = (char *)heap_alloc(MAX_PATH); /* (prognamelen + 1) does not really matter, argv0 is '\0' filled */ memcpy(argv0, prog, prognamelen + 1); errno = 0; execmode = none; /* NOTE: loops over PATHEXT if no extension found */ while (*begin) { size_t extlen; if (GetBinaryType(argv0, &exitcode)) { /* exists and is executable NOTE: an "xxx.exe" without a correct PE header (i.e. a text file) has type "DOS binary", but execution will generate a WOW error */ execmode = directex; break; } if (GetLastError() == ERROR_BAD_EXE_FORMAT) { /* exists but is not "executable" */ execmode = shellex; break; } if (hasext) break; /* get next PATHEXT extension */ while (*begin && (*begin != '.')) begin++; while (*end && (*end != ';')) end++; if (!*begin) break; extlen = end - begin; if (extlen < sizeof(extension)) { memcpy(extension, begin, extlen); extension[extlen] = '\0'; /* prognamelen ignores the last '\r' if present */ memcpy(argv0, prog, prognamelen); /* update argv0 adding the extension to prog */ memcpy(argv0 + prognamelen, extension, extlen + 1); } begin = end; /* skip sequences of ';' */ while (*end && *end == ';') end++; }; cmdstr = (char *)heap_alloc(MAX_PATH << 2); cmdsize = MAX_PATH << 2; cmdlen = 0; cmdend = cmdstr; dbgprintf(PR_VERBOSE, "%s(): execute [%s] extension=[%s] mode=%d hasext=%d\n", __FUNCTION__, argv0, extension, execmode, hasext); /* skip over program name */ args++; /* the file (after PATHEXT search) exists, but it's not "executable" */ if (execmode == shellex) { /* if prog had no extension or has the extension associated to shell scripts */ if ((hasext == 0 && *extension == '\0') || is_shell_script(extension)) { int res = process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize); if (res < 0) { execmode = none; } else if (res == 0) { char *newargv[2]; cmdlen = copy_quote_and_fix_slashes(gModuleName, cmdstr); cmdend = cmdstr + cmdlen; newargv[0] = path_to_slash(argv0); newargv[1] = NULL; concat_args_and_quote((const char *const *)newargv, &cmdstr, &cmdlen, &cmdend, &cmdsize); *cmdend = 0; argv0 = gModuleName; execmode = directex; } else { cmdend = cmdstr + cmdlen; execmode = directex; } } else { unsigned long shflags = 0L; /* if the file extension is in pathext, use the same console and wait for child. StrStrI() is from shlwapi */ if (StrStrI(exts, extension)) shflags = SEE_MASK_NO_CONSOLE | SEE_MASK_NOCLOSEPROCESS; if (try_shell_ex(argv0, args, shflags, &cmdstr, &cmdsize)) return (0); /* ShellExecute failed, the file has an unknown extension, but it may be a shell script with a shebang */ if (process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize) > 0) { cmdend = cmdstr + cmdlen; execmode = directex; } else { /* the file extension is NOT known and the file has NO shebang: returns EPERM, see NOTES */ errno = EPERM; return (-1); } } } else if (execmode == directex) { cmdlen = copy_quote_and_fix_slashes(prog, cmdstr); cmdend = cmdstr + cmdlen; } if (execmode == none) { /* error: prog not found even after trying PATHEXT extensions */ errno = ENOENT; return (-1); } concat_args_and_quote(args, &cmdstr, &cmdlen, &cmdend, &cmdsize); if (*cmdstr == ' ') { /* if we left a ' ' for the quote and there is no quote */ cmdstr++; cmdlen--; } *cmdend = 0; init_startupinfo(&si); dwCreationflags = GetPriorityClass(GetCurrentProcess()); priority = GetThreadPriority(GetCurrentThread()); #if defined(W32DEBUG) /* DebugView output is very difficult to read with overlong lines */ if (cmdlen < 128) dbgprintf(PR_EXEC, "%s(): CreateProcess(%s, ..) cmdstr=[%s]\n", __FUNCTION__, argv0, cmdstr); else { char shortbuf[128+4]; memcpy(shortbuf, cmdstr, 128); memcpy(shortbuf + 128, "...", 4); dbgprintf(PR_EXEC, "nt_execve(): CreateProcess(%s, ..) cmdstr=[%s]\n", argv0, shortbuf); } #endif if (!CreateProcess(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles dwCreationflags | CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { exitcode = GetLastError(); if (exitcode == ERROR_BAD_EXE_FORMAT) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error BAD_EXE_FORMAT in %s\n", argv0, __FUNCTION__); errno = ENOEXEC; } else if (exitcode == ERROR_INVALID_PARAMETER) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error INVALID_PARAMETER in %s, cmdstr len=%u\n", argv0, __FUNCTION__, strlen(cmdstr)); /* exceeded command line */ /* return NOT found, ENAMETOOLONG is correct but not understood by the shell that will retry with another path ... */ errno = ENOENT; } else { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error %ld in %s\n", argv0, exitcode, __FUNCTION__); errno = ENOENT; } goto fail_return; } else { exitcode = 0; if (!SetThreadPriority(pi.hThread, priority)) dbgprintf(PR_ERROR, "!!! SetThreadPriority(0x%p) failed, error %ld\n", pi.hThread, GetLastError()); ResumeThread(pi.hThread); if (!is_gui(argv0)) { if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) dbgprintf(PR_ERROR, "!!! error %ld waiting for process %ld\n", GetLastError(), pi.dwProcessId); if (!GetExitCodeProcess(pi.hProcess, &exitcode)) dbgprintf(PR_ERROR, "!!! GetExitCodeProcess(0x%p, ..) error %ld in %s\n", pi.hProcess, GetLastError(), __FUNCTION__); } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close_si_handles(); /* @@@@ should wait for the clipboard ? if (is_dev_clipboard_active) { CloseHandle((HANDLE)_get_osfhandle(0)); CloseHandle((HANDLE)_get_osfhandle(1)); CloseHandle((HANDLE)_get_osfhandle(2)); ... WaitForSingleObject(ghdevclipthread,60*1000); } */ dbgprintf(PR_ALL, "--- %s(): Exec'd process %ld terminated with exitcode %ld\n", __FUNCTION__, pi.dwProcessId, exitcode); exec_exit((int)exitcode); } fail_return: heap_free(cmdstr); close_si_handles(); exec_exit(-1); return (-1); }