File "unix.inc"
Path: /exe2unix/inc/unix.inc
File size: 7.21 KB
MIME-type:
Charset: utf-8
'---------------------------------------------------------------------------------------------------------------------
' This is +Unix.inc v1.2+ for PBWin9
' This library offers tool functions to run Unix commands from within Wine
'---------------------------------------------------------------------------------------------------------------------
MACRO UNIX_HOME = "z:\home\" + ENVIRON$("USERNAME") + "\" ' Returns the Wine path of Unix '~' (User home)
DECLARE FUNCTION IsOnUnix() AS LONG ' Return %True if we are on a Unix system, %False otherwise
DECLARE SUB GetWineDrivesMapping() ' Get all Wine drives and their mapping
DECLARE FUNCTION WinePath(BYVAL file AS STRING) AS STRING ' Return the Wine path of a Unix file
DECLARE FUNCTION UnixPath(BYVAL file AS STRING) AS STRING ' Return the Unix path of a Wine file
DECLARE FUNCTION UnixExists(BYVAL file AS STRING) AS LONG ' Return existence of a Unix file e.g. /usr/bin/vlc
DECLARE FUNCTION GetUnixRet(BYVAL cmd AS STRING) AS STRING ' Return the full output of a Unix command
DECLARE SUB UnixShell(BYVAL cmd AS STRING) ' Execute a Unix command asynchronously
'---------------------------------------------------------------------------------------------------------------------
GLOBAL dosdevices() AS STRING ' list of Wine drives followed by their mapping, in the form "d:/media/user/myhdd"
'---------------------------------------------------------------------------------------------------------------------
#INCLUDE ONCE "Win32Api.inc"
'---------------------------------------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
FUNCTION IsOnUnix() AS LONG
' Return %True if we are on a Unix system, %False otherwise
LOCAL hNt AS DWORD
LOCAL pwv AS DWORD
hNt = GetModuleHandle("ntdll.dll")
IF hNt = 0 THEN
FUNCTION = %FALSE
ELSE
pwv = GetProcAddress(hNt, "wine_get_version")
FUNCTION = (pwv <> 0)
END IF
END FUNCTION
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
SUB GetWineDrivesMapping()
' Get all Wine drives and their mapping
LOCAL r, e AS STRING
LOCAL i, j AS LONG
REDIM dosdevices(-1)
r = GetUnixRet("ls -al ~/.wine/dosdevices")
IF r = "" THEN EXIT SUB
FOR i = 1 TO PARSECOUNT(r, $LF)
e = PARSE$(r, $LF, i)
j = INSTR(e, " -> ")
IF j = 0 THEN ITERATE FOR
j = INSTR(j - LEN(e) - 2, e, " ")
e = MID$(e, j + 1)
IF INSTR(e, "/dev/") > 0 OR _
INSTR(e, "c:") > 0 OR _
INSTR(e, "z:") > 0 THEN
ITERATE FOR
END IF
e = REMOVE$(e, " -> ")
REPLACE "::" WITH ":" IN e
REDIM PRESERVE dosdevices(UBOUND(dosdevices) + 1)
dosdevices(UBOUND(dosdevices)) = e
NEXT
END SUB
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
FUNCTION WinePath(BYVAL file AS STRING) AS STRING
' Return the Wine path of a Unix file e.g. /usr/bin/vlc -> z:\usr\bin\vlc
file = "z:" + file
REPLACE "/" WITH "\" IN file
FUNCTION = file
END FUNCTION
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
FUNCTION UnixPath(BYVAL file AS STRING) AS STRING
' Return the Unix path of a Wine file e.g. z:\usr\bin\vlc -> /usr/bin/vlc
LOCAL i AS LONG
' Get the mapping for all Wine drives
IF UBOUND(dosdevices) < 0 THEN GetWineDrivesMapping()
REPLACE "\" WITH "/" IN file
' Special cases: files on Z:\ and C:\ are easy to translate
IF LEFT$(LCASE$(file), 3) = "z:/" THEN
FUNCTION = MID$(file, 3)
EXIT FUNCTION
END IF
IF LEFT$(LCASE$(file), 3) = "c:/" THEN
FUNCTION = "/home/" + ENVIRON$("USERNAME") + "/.wine/drive_c/" + MID$(file, 4)
EXIT FUNCTION
END IF
' Else use dosdevices() mapping
FOR i = 0 TO UBOUND(dosdevices)
IF LEFT$(LCASE$(file), 3) = LEFT$(dosdevices(i), 2) + "/" THEN
FUNCTION = MID$(dosdevices(i), 3) + MID$(file, 3)
EXIT FUNCTION
END IF
NEXT
' Final case, in case drive is not mapped (should not happen?)
file = "/home/" + ENVIRON$("USERNAME") + "/.wine/dosdevices/" + file
i = INSTR(file, ":") ' the following is needed to transform the drive letter to smaller case
IF i > 1 THEN file = LEFT$(file, i-2) + LCASE$(MID$(file, i-1, 1)) + MID$(file, i)
FUNCTION = file
END FUNCTION
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
FUNCTION UnixExists(BYVAL file AS STRING) AS LONG
' Return existence of a Unix file e.g. /usr/bin/vlc
LOCAL lRes AS LONG
lRes = GETATTR(WinePath(file))
FUNCTION = (ERRCLEAR = 0)
END FUNCTION
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
SUB CreateExecSh(BYVAL cmd AS STRING)
' Create the 'Dynamic Unix Execution Script' (dues) to be called from Wine
LOCAL dues AS STRING
LOCAL lRes, ff AS LONG
' Reset script
dues = UNIX_HOME + "dues.sh"
KILL dues
' Write script
ff = FREEFILE
OPEN dues FOR BINARY ACCESS WRITE AS #ff
PUT$ #ff, "#! /usr/bin/sh" + $LF + cmd
CLOSE #ff
' Make script executable
SHELL "start /exec /usr/bin/chmod +x /home/" + ENVIRON$("USERNAME") + "/dues.sh"
END SUB
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
FUNCTION GetUnixRet(BYVAL cmd AS STRING) AS STRING
' Return the full output of a Unix command
LOCAL timout AS SINGLE
LOCAL logfl AS STRING
LOCAL ret AS STRING
LOCAL ff AS LONG
' Define temporary files
logfl = UNIX_HOME + "dues.log"
KILL logfl
' Now, synchronously call the command
UnixShell cmd + " > ~/dues.log"
' Poll the temporary file every 1/4s until filled
' or we reach a timeout of 3s (arbitrary)
DO
SLEEP 250 : timout += 0.25
ff = FREEFILE
OPEN logfl FOR BINARY ACCESS READ LOCK SHARED AS #ff
GET$ #ff, LOF(#ff), ret
CLOSE #ff
LOOP UNTIL ret <> "" OR timout >= 3
' Clean-up temporary files
KILL LEFT$(logfl,-3) + "sh"
KILL logfl
FUNCTION = ret
END FUNCTION
'-----------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------
SUB UnixShell(BYVAL cmd AS STRING)
' Execute a Unix command asynchronously
LOCAL pid AS DWORD
CreateExecSh(cmd)
pid = SHELL("start /exec /usr/bin/sh /home/" + ENVIRON$("USERNAME") + "/dues.sh", 0)
SLEEP 1000
END SUB
'-----------------------------------------------------------------------------------------