/* Various utilities - OS/2 versions Copyright (C) 1994, 1995, 1996 the Free Software Foundation. Written 1994, 1995, 1996 by: Juan Grigera, Miguel de Icaza, Janne Kukonlehto, Dugan Porter, Jakub Jelinek, Mauricio Plaza. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define INCL_DOS #define INCL_PM #define INCL_DOSPROCESS #define INCL_DOSFILEMGR #define INCL_DOSDEVICES /* Device values */ #define INCL_DOSDATETIME #define INCL_DOSERRORS #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include /* my_system */ #include /* INT_MAX */ #include /* select: timeout */ #include #include #include #include #include #include #ifdef __BORLANDC__ #define ENOTEMPTY ERROR_DIR_NOT_EMPTY #endif char * get_owner (int uid) { return "none"; } char * get_group (int gid) { return "none"; } /* Pipes are guaranteed to be able to hold at least 4096 bytes */ /* More than that would be unportable */ #define MAX_PIPE_SIZE 4096 static int error_pipe[2]; /* File descriptors of error pipe */ static int old_error; /* File descriptor of old standard error */ /* Creates a pipe to hold standard error for a later analysis. */ /* The pipe can hold 4096 bytes. Make sure no more is written */ /* or a deadlock might occur. */ void open_error_pipe (void) { return; } void close_error_pipe (int error, char *text) { return; } void check_error_pipe (void) { char error[MAX_PIPE_SIZE]; int len = 0; if (old_error >= 0){ while (len < MAX_PIPE_SIZE) { int rvalue; rvalue = read (error_pipe[0], error + len, 1); len ++; if (rvalue <= 0) break; } error[len] = 0; close (error_pipe[0]); } if (len > 0) message (0, " Warning ", error); } static int StartWindowsProg (char *name, SHORT type) { #if 0 /* FIXME: PM DDL's should be loaded (or not loaded) at run time */ PROGDETAILS pDetails; memset(&pDetails, 0, sizeof(PROGDETAILS)) ; pDetails.Length = sizeof(pDetails); pDetails.pszExecutable = name; /* program name */ pDetails.pszStartupDir = NULL; /* default directory for new app. */ pDetails.pszParameters = NULL; /* command line */ pDetails.progt.fbVisible = SHE_VISIBLE ; pDetails.pszEnvironment = NULL; switch (type) { case 0: /* Win Standard */ pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; break; case 1: /* Win 3.1 Protect */ pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; break; case 2: /* Win 3.1 Enh. Protect */ pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; break; default: pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; break; } /* endswitch */ WinStartApp(NULLHANDLE, &pDetails, NULL, NULL, SAF_INSTALLEDCMDLINE|SAF_STARTCHILDAPP) ; #endif return 0; } static int os2_system (int as_shell_command, const char *shell, const char *command, const char *parm); /* as_shell_command = 1: If a program is started during input line, CTRL-O or RETURN = 0: F3, F4 */ int my_system (int as_shell_command, const char *shell, const char *command) { char *sh; /* This is the shell -- always! */ char *cmd; /* This is the command (only the command) */ char *parm; /* This is the parameter (can be more than one) */ register int length, i; char temp[4096]; /* That's enough! */ sh = get_default_shell(); if (strcmp(sh, shell)) { /* Not equal -- That means: shell is the program and command is the parameter */ cmd = (char *) shell; parm = (char *) command; } else { /* look into the command and take out the program */ if (command) { strcpy(temp, command); length = strlen(command); for (i=length-1; i>=0; i--) { if (command[i] == ' ') { temp[i] = (char) 0; length--; } else break; } /* endfor */ if (i==-1) { /* only blanks */ return -1; } /* endif */ if (parm = strchr(temp, (char) ' ')) { *parm = (char) 0; parm++; } cmd = (char *) temp; } else { /* command is NULL */ cmd = parm = NULL; } /* endif */ } /* endif */ /* .ado: Konvertierung wenn shell <> get_default_shell */ os2_system (as_shell_command, sh, cmd, parm); } static int ux_startp (const char *shell, const char *command, const char *parm) { if (parm) { spawnlp (P_WAIT, (char *) shell, (char *) shell, "/c", (char *) command, (char *) parm, (char *) 0); } else { spawnlp (P_WAIT, (char *) shell, (char *) shell, "/c", (char *) command, (char *) 0); } /* endif */ return 0; } static int os2_system (int as_shell_command, const char *shell, const char *command, const char *parm) { register int i, j; ULONG AppType = 0; /* Application type flags (returned) */ APIRET rc = NO_ERROR; /* Return Code */ char pathValue[5] = "PATH"; /* For DosSearchPath */ UCHAR searchResult[MAX_PATH * 2 + 1]; /* For DosSearchPath */ char *cmdString; char *postFix[3]; char *line; /* ------------------------------------------------------- */ STARTDATA StartData; CHAR ObjBuf[100]; ULONG SessionID; PID pid; if (command == NULL) { /* .ado: just start a shell, we don't need the parameter */ spawnl (P_WAIT, (char *) shell, (char *) shell, (char *) command, (char *) 0); return 0; } memset(&StartData, 0, sizeof(StartData)) ; StartData.Length = sizeof(StartData); StartData.Related = SSF_RELATED_CHILD; StartData.FgBg = SSF_FGBG_BACK; StartData.TraceOpt = SSF_TRACEOPT_NONE; StartData.PgmTitle = NULL; StartData.TermQ = NULL; StartData.InheritOpt = SSF_INHERTOPT_PARENT; StartData.IconFile = 0; StartData.PgmHandle = 0; StartData.PgmControl = SSF_CONTROL_VISIBLE ; StartData.ObjectBuffer = ObjBuf; StartData.ObjectBuffLen = 100; StartData.PgmInputs = parm; postFix[0] = ".exe"; postFix[1] = ".cmd"; postFix[2] = ".bat"; i = strlen(command); if (command[i-1] == ' ') { /* The user has used ALT-RETURN */ i--; } /* endif */ cmdString = (char *) malloc(i+1); for (j=0; j 4) && (cmdString[i-4]) != '.')) { /* without Extension */ line = (char *) malloc(i+5); rc = 1; for (i=0; (i<3 && rc); i++) { /* Search for the file */ strcpy(line, cmdString); strcat(line, postFix[i]); rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY), (PSZ) pathValue, line, searchResult, sizeof(searchResult)); } /* endfor */ free (line); } else { /* Just search */ rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY), (PSZ) pathValue, cmdString, searchResult, sizeof(searchResult)); } /* endif */ free(cmdString); if (rc != 0) { /* Internal command or the program was written with absolut path */ return ux_startp(shell, command, parm); } /* endif */ /* Application to be started */ StartData.PgmName = searchResult; StartData.Environment = NULL; rc = DosQueryAppType(searchResult, &AppType); if (rc == NO_ERROR) { StartData.SessionType = PROG_WINDOWABLEVIO; if ((AppType & 0x00000007) == FAPPTYP_WINDOWAPI) { /* Window API */ StartData.SessionType = PROG_PM; return DosStartSession(&StartData, &SessionID, &pid); } /* endif */ if ((AppType & 0x00000007) == FAPPTYP_WINDOWCOMPAT) { /* Window compat */ return ux_startp(shell, command, parm); } /* endif */ if (AppType & 0x0000ffff & FAPPTYP_DOS) { /* PC/DOS Format */ StartData.SessionType = PROG_WINDOWEDVDM; return DosStartSession(&StartData, &SessionID, &pid); } /* endif */ if (AppType & 0x0000ffff & FAPPTYP_WINDOWSREAL) { /* Windows real mode app */ return StartWindowsProg(searchResult, 0); } /* endif */ if (AppType & 0x0000ffff & FAPPTYP_WINDOWSPROT) { /* Windows Protect mode app*/ return StartWindowsProg(searchResult, 1); } /* endif */ if (AppType & 0x0000ffff & FAPPTYP_WINDOWSPROT31) { /* Windows 3.1 Protect mode app*/ return StartWindowsProg(searchResult, 2); } /* endif */ rc = DosStartSession(&StartData, &SessionID, &pid) ; } else { /* It's not a known exe type or it's a CMD/BAT file */ i = strlen(searchResult); if ((toupper(searchResult[--i]) == 'T') && (toupper(searchResult[--i]) == 'A') && (toupper(searchResult[--i]) == 'B') && (searchResult[--i] == '.') ) { StartData.SessionType = PROG_WINDOWEDVDM; rc = DosStartSession(&StartData, &SessionID, &pid) ; } else { rc = ux_startp (shell, command, parm); } /* endif */ } /* endif */ return rc; } char *tilde_expand (char *directory) { return strdup (directory); } #ifndef __EMX__ void sleep(unsigned long dwMiliSecs) { DosSleep(dwMiliSecs); } #endif /* Canonicalize path, and return a new path. Do everything in situ. The new path differs from path in: Multiple BACKSLASHs are collapsed to a single BACKSLASH. Leading `./'s and trailing `/.'s are removed. Trailing BACKSLASHs are removed. Non-leading `../'s and trailing `..'s are handled by removing portions of the path. */ char * canonicalize_pathname (char *path) { int i, start; char stub_char; stub_char = (*path == PATH_SEP) ? PATH_SEP : '.'; /* Walk along path looking for things to compact. */ i = 0; for (;;) { if (!path[i]) break; while (path[i] && path[i] != PATH_SEP) i++; start = i++; /* If we didn't find any slashes, then there is nothing left to do. */ if (!path[start]) break; /* Handle multiple BACKSLASHs in a row. */ while (path[i] == PATH_SEP) i++; if ((start + 1) != i) { strcpy (path + start + 1, path + i); i = start + 1; } /* Handle backquoted BACKSLASH. */ /* if (start > 0 && path[start - 1] == '\\') continue; */ /* Check for trailing BACKSLASH. */ if (start && !path[i]) { zero_last: path[--i] = '\0'; break; } /* Check for `../', `./' or trailing `.' by itself. */ if (path[i] == '.') { /* Handle trailing `.' by itself. */ if (!path[i + 1]) goto zero_last; /* Handle `./'. */ if (path[i + 1] == PATH_SEP) { strcpy (path + i, path + i + 1); i = start; continue; } /* Handle `../' or trailing `..' by itself. Remove the previous ?/ part with the exception of ../, which we should leave intact. */ if (path[i + 1] == '.' && (path[i + 2] == PATH_SEP || !path[i + 2])) { while (--start > -1 && path[start] != PATH_SEP); if (!strncmp (path + start + 1, "..\\", 3)) continue; strcpy (path + start + 1, path + i + 2); i = start; continue; } } } if (!*path) { *path = stub_char; path[1] = '\0'; } return path; } void my_statfs (struct my_statfs *myfs_stats, char *path) { PFSALLOCATE pBuf; PFSINFO pFsInfo; ULONG lghBuf; ULONG diskNum = 0; ULONG logical = 0; UCHAR szDeviceName[3] = "A:"; ULONG ulOrdinal = 0; /* Ordinal of entry in name list */ PBYTE pszFSDName = NULL; /* pointer to FS name */ APIRET rc = NO_ERROR; /* Return code */ BYTE fsqBuffer[sizeof(FSQBUFFER2) + (3 * CCHMAXPATH)] = {0}; ULONG cbBuffer = sizeof(fsqBuffer); /* Buffer length) */ PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2) fsqBuffer; int i, len = 0; /* ------------------------------------------------------------------ */ lghBuf = sizeof(FSALLOCATE); pBuf = (PFSALLOCATE) malloc(lghBuf); /* Get the free number of Bytes */ rc = DosQueryFSInfo(0L, FSIL_ALLOC, (PVOID) pBuf, lghBuf); /* KBytes available */ myfs_stats->avail = pBuf->cSectorUnit * pBuf->cUnitAvail * pBuf->cbSector / 1024; /* KBytes total */ myfs_stats->total = pBuf->cSectorUnit * pBuf->cUnit * pBuf->cbSector / 1024; myfs_stats->nfree = pBuf->cUnitAvail; myfs_stats->nodes = pBuf->cbSector; lghBuf = sizeof(FSINFO); pFsInfo = (PFSINFO) malloc(lghBuf); rc = DosQueryFSInfo(0L, FSIL_VOLSER, (PVOID) pFsInfo, lghBuf); /* Get name */ myfs_stats->device = strdup(pFsInfo->vol.szVolLabel); /* Label of the Disk */ /* Get the current disk for DosQueryFSAttach */ rc = DosQueryCurrentDisk(&diskNum, &logical); szDeviceName[0] = (UCHAR) (diskNum + (ULONG) 'A' - 1); /* Now get the type of the disk */ rc = DosQueryFSAttach(szDeviceName, 0L, FSAIL_QUERYNAME, pfsqBuffer, &cbBuffer); pszFSDName = pfsqBuffer->szName + pfsqBuffer->cbName + 1; myfs_stats->mpoint = strdup(pszFSDName); /* FAT, HPFS ... */ myfs_stats->type = pBuf->idFileSystem; /* What is about 3 ?*/ if (myfs_stats->type == 0) { myfs_stats->typename = (char *) malloc(11); strcpy(myfs_stats->typename, "Local Disk"); } else { myfs_stats->typename = (char *) malloc(13); strcpy(myfs_stats->typename, "Other Device"); } /* endif */ free(pBuf); free(pFsInfo); } int gettimeofday (struct timeval* tvp, void *p) { DATETIME pdt = {0}; if (p != NULL) /* what is "p"? */ return 0; /* Since MC only calls this func from get_random_hint we return * some value, not exactly the "correct" one */ DosGetDateTime(&pdt); tvp->tv_usec = (pdt.hours * 60 + pdt.minutes) * 60 + pdt.seconds; /* Number of milliseconds since Windows started */ tvp->tv_sec = tvp->tv_usec * 1000 + pdt.hundredths * 10; return 0; } /* FAKE functions */ int look_for_exe(const char* pathname) { int j; char *p; int lgh = strlen(pathname); if (lgh < 4) { return 0; } else { p = (char *) pathname; for (j=0; jst_mode & S_IFDIR)) { if (look_for_exe(pathname)) { buffer->st_mode |= S_IXUSR | S_IXGRP | \ S_IXOTH; } } } /* endif */ return rc; } int getuid () { return 0; } int getgid () { return 0; } int readlink (char* path, char* buf, int size) { return -1; } int symlink (char *n1, char *n2) { return -1; } int link (char *p1, char *p2) { return -1; } int chown (char *path, int owner, int group) { return -1; } int mknod (char *path, int mode, int dev) { return -1; } void init_uid_gid_cache (void) { return; } int mc_doublepopen (int inhandle, int inlen, pid_t *the_pid, char *command, ...) { return 0; } int mc_doublepclose (int pipe, pid_t pid) { return 0; } /*hacks to get it compile, remove these after vfs works */ char * vfs_get_current_dir (void) { return NULL; } int vfs_current_is_extfs (void) { return 0; } int vfs_file_is_ftp (char *filename) { return 0; } int mc_utime (char *path, void *times) { return 0; } void extfs_run (char *file) { return; } int geteuid(void) { return 0; } #ifndef __EMX__ char * getcwd(char *buffer, int size) { APIRET rc; ULONG lgh = size; ULONG uDriveNum = 0; /* Drive number (A=1, B=2 ...) */ ULONG uDriveMap = 0; /* Mapping */ CHAR p[4] = "A:\\"; char *tmpBuf; rc = DosQueryCurrentDisk(&uDriveNum, &uDriveMap); p[0] = (char) (uDriveNum + (int) 'A' - 1); rc = DosQueryCurrentDir(0L, (PBYTE) buffer, &lgh); if (rc == NO_ERROR) { tmpBuf = (char *) malloc(strlen(buffer) + 1); strcpy(tmpBuf, buffer); strcpy(buffer, p); strcat(buffer, tmpBuf); free(tmpBuf); return strdup(buffer); } else { return NULL; } /* endif */ } #endif int mc_chdir(char *pathname) { APIRET ret; register int lgh = strlen(pathname); /* Set the current drive */ if (lgh == 0) { return -1; } else { /* First set the default drive */ if (lgh > 1) { if (pathname[1] == ':') { ret = DosSetDefaultDisk(toupper(pathname[0]) - 'A' + 1); } /* endif */ } /* endif */ /* After that, set the current dir! */ ret = DosSetCurrentDir(pathname); } /* endif */ return ret; } int mc_chmod(char *pathName, int unxmode) { /* OS/2 does not need S_REG */ int os2Mode = unxmode & 0x0FFF; return chmod(pathName, os2Mode); } static int conv_os2_unx_rc(int os2rc) { int errCode; switch (os2rc) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_FILENAME_EXCED_RANGE: errCode = ENOENT; break; case ERROR_NOT_DOS_DISK: case ERROR_SHARING_VIOLATION: case ERROR_SHARING_BUFFER_EXCEEDED: case ERROR_ACCESS_DENIED: errCode = EACCES; break; case ERROR_INVALID_PARAMETER: errCode = EINVAL; break; default: errCode = EINVAL; break; } /* endswitch */ return errCode; } int mc_open (char *file, int flags, int pmode) { return open(file, (flags | O_BINARY), pmode); } int mc_unlink(char *pathName) { /* Use OS/2 API to delete a file, if the file is set as read-only, the file will be deleted without asking the user! */ APIRET rc; rc = DosDelete(pathName); if (!rc) { return 0; } /* endif */ if (rc == ERROR_ACCESS_DENIED) { chmod(pathName, (S_IREAD|S_IWRITE)); rc = DosDelete(pathName); if (rc) { errno = conv_os2_unx_rc(rc) ; return -1; } else { return 0; } /* endif */ } else { errno = conv_os2_unx_rc(rc) ; return -1; } /* endif */ } int strncasecmp (char *s, char *d, int count) { register char result; while (count > 0){ if (result = (0x20 | *s) - (0x20 | *d)) break; if (!*s) return 0; s++; d++; count--; } return result; } FILE * _popen(const char *cmd, const char *mode) { return NULL; } int _pclose(FILE *file) { return 1; } char * get_default_editor (void) { char *tmp; APIRET rc; char pathValue[5] = "PATH"; UCHAR searchResult[MAX_PATH + 1]; /* EPM is not always be installed */ rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY), (PSZ) pathValue, "EPM.EXE", searchResult, sizeof(searchResult)); if (rc != 0) { /* The system editor is always there */ return strdup("e.exe"); } else { /* Let it be searched from my_system */ return strdup("epm.exe"); } /* endif */ } /* get_default_shell Get the default shell for the current hardware platform TODO: Get the value of %OS2_SHELL% or %SHELL%: which one? */ char * get_default_shell() { return getenv ("COMSPEC"); } int getpid (void) { return 0; } int errno_dir_not_empty (int err) { if (err == ENOTEMPTY) return 1; return 0; } char * get_mc_lib_dir () { char *mchome = getenv("MCHOME"); if (!mchome) { return "D:\\mc"; } else { return mchome; } /* endif */ } int get_user_rights (struct stat *buf) { return 2; } void init_groups (void) { } void delete_groups (void) { }