/** * \file os_os2.C * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Ruurd A. Reitsma * * Full author contact details are available in file CREDITS. * * Various OS specific functions */ #include #include "os.h" #include "support/filetools.h" #define INCL_DOSFILEMGR #define INCL_DOSMODULEMGR #define INCL_DOSPROCESS #define INCL_DOSNLS #define INCL_DOSERRORS #include #include using boost::scoped_array; namespace { string binpath_; string binname_; string tmpdir_; os::shell_type shell_ = os::UNIX; unsigned long cp_ = 0; } namespace os { void init(int * argc, char ** argv[]) { if (argc != 0 /* This is a hack! */) { _wildcard(argc, argv); PTIB ptib = new TIB[1]; PPIB ppib = new PIB[1]; APIRET rc = DosGetInfoBlocks(&ptib, &ppib); if (rc != NO_ERROR) exit(rc); scoped_array tmp(new char[256]); // This is the only reliable way to retrieve the executable name. rc = DosQueryModuleName(ppib->pib_hmte, 256L, tmp); if (rc != NO_ERROR) exit(rc); string p = tmp.get(); p = slashify_path(p); binname_ = OnlyFilename(p); binname_.erase(binname_.length()-4, string::npos); binpath_ = OnlyPath(p); // OS/2 cmd.exe has another use for '&' string sh = OnlyFilename(GetEnvPath("EMXSHELL")); if (sh.empty()) { // COMSPEC is set, unless user unsets sh = OnlyFilename(GetEnvPath("COMSPEC")); if (sh.empty()) sh = "cmd.exe"; } sh = lowercase(sh); // DosMapCase() is an overkill here if (contains(sh, "cmd.exe") || contains(sh, "4os2.exe")) shell_ = os::CMD_EXE; else shell_ = os::UNIX; } static bool initialized = false; if (initialized) return; initialized = true; ULONG CPList[3] = {0}; ULONG CPList_size; APIRET rc = DosQueryCp(3 * sizeof(ULONG), CPList, &CPList_size); if (rc != NO_ERROR) exit(rc); // CPList[0] == process current codepage, // CPList[1] == system default codepage, the rest are auxilary. // Once cp_ is correctly set, you can call other routines. cp_ = CPList[1]; } void warn(string const & /*mesg*/) { return; } string current_root() { APIRET rc; ULONG drv_num; ULONG drv_map; rc = DosQueryCurrentDisk(&drv_num, &drv_map); if (rc != NO_ERROR) exit(rc); char drive = 'A' + drv_num -1; string tmp(1, drive); tmp += ":/"; return tmp; } string::size_type common_path(string const & p1, string const & p2) { static bool initialized = false; if (!initialized) { init(0, 0); initialized = true; } COUNTRYCODE cntry; cntry.country = 0; cntry.codepage = cp_; string temp1 = slashify_path(p1); string temp2 = slashify_path(p2); char * tmp1 = const_cast (temp1.c_str()); char * tmp2 = const_cast (temp2.c_str()); /* rc = */ DosMapCase(p1.length(), &cntry, tmp1); // if (rc != NO_ERROR) // exit(rc); /* rc = */ DosMapCase(p2.length(), &cntry, tmp2); // if (rc != NO_ERROR) // exit(rc); // This algorithm works only if paths are slashified on DBCS systems. string::size_type i = 0; string::size_type p1_len = p1.length(); string::size_type p2_len = p2.length(); while (i < p1_len && i < p2_len && tmp1[i] == tmp2[i]) ++i; if ((i < p1_len && i < p2_len) || (i < p1_len && tmp1[i] != '/' && i == p2_len) || (i < p2_len && tmp2[i] != '/' && i == p1_len)) { if (i) --i; // here was the last match while (i && tmp1[i] != '/') --i; } return i; } string slashify_path(string const & p) { static bool initialized = false; static bool leadbyte[256] = {false}; if (!initialized) { init(0, 0); COUNTRYCODE cntry; cntry.country = 0; cntry.codepage = cp_; unsigned char *DBCSinfo = new unsigned char[12]; /* rc = */ DosQueryDBCSEnv(12, &cntry, (char*) DBCSinfo); // if (rc != NO_ERROR) // exit(rc); for (int j = 1; j < 12; j += 2) DBCSinfo[j]++; unsigned char i = 0; bool isLeadByte = false; while (*DBCSinfo != 0) { if (i == *DBCSinfo) { isLeadByte = !isLeadByte; DBCSinfo++; } leadbyte[i++] = isLeadByte; } initialized = true; } string::iterator lit = p.begin(); string::iterator end = p.end(); for (; lit < end; ++lit) { if (leadbyte[(*lit)]) lit += 2; if ((*lit) == '\\') (*lit) = '/'; } p = subst(p, "//", "/"); return p; } string external_path(string const & p) { return p; } string internal_path(string const & p) { return p; } bool is_absolute_path(string const & p) { return (p.length() > 1 && isalpha(static_cast(p[0])) && p[1] == ':'); } // returns a string suitable to be passed to popen when // reading a pipe char const * popen_read_mode() { return "r"; } string binpath() { return binpath_; } string binname() { return binname_; } void setTmpDir(string const & p) { tmpdir_ = p; } string getTmpDir() { return tmpdir_; } shell_type shell() { return shell_; } } // end namespace os