From: <jfa...@us...> - 2010-01-25 22:57:30
|
Revision: 5513 http://oorexx.svn.sourceforge.net/oorexx/?rev=5513&view=rev Author: jfaucher Date: 2010-01-25 22:57:22 +0000 (Mon, 25 Jan 2010) Log Message: ----------- GUI applications are no longer blocking. Readline can be deactivated and parse pull used instead. Fixed the security manager : not all checkpoints were supported. Modified Paths: -------------- incubator/ooRexxShell/oorexxshell.rex incubator/ooRexxShell/readme.txt Modified: incubator/ooRexxShell/oorexxshell.rex =================================================================== --- incubator/ooRexxShell/oorexxshell.rex 2010-01-25 20:04:17 UTC (rev 5512) +++ incubator/ooRexxShell/oorexxshell.rex 2010-01-25 22:57:22 UTC (rev 5513) @@ -65,6 +65,8 @@ MYHANDLER> exit the exit command is supported whatever the interpreter */ +.platform~initialize + -- Use a security manager to trap the calls to the systemCommandHandler : -- Windows : don't call directly CreateProcess, to avoid loss of doskey history (prepend "cmd /c") -- Unix : support aliases (prepend "bash -O expand_aliases -c") @@ -86,6 +88,8 @@ call on halt name haltHandler +.ooRexxShell~readline = .true -- assign .false if you want only the basic "parse pull" functionality + .ooRexxShell~defaultColor = "white" .ooRexxShell~errorColor = "bred" .ooRexxShell~infoColor = "bgreen" @@ -105,7 +109,6 @@ .ooRexxShell~interpreter = address() .ooRexxShell~queuePrivateName = rxqueue("create") -say .ooRexxShell~queuePrivateName .ooRexxShell~queueInitialName = rxqueue("set", .ooRexxShell~queuePrivateName) select @@ -118,7 +121,7 @@ -- One-liner for default address() and exit. -- Beware ! It's not ooRexx by default, unless you start the line by the word oorexx. .ooRexxShell~isInteractive = .false - push unquoted(.ooRexxShell~initialArgument~strip) + push unquoted(.ooRexxShell~initialArgument) call main end end @@ -204,7 +207,7 @@ use strict arg prompt inputrx = "" select - when queued() == 0 & lines() == 0 & .ooRexxShell~systemAddress~caselessEquals("cmd") then do + when queued() == 0 & lines() == 0 & .ooRexxShell~systemAddress~caselessEquals("cmd") & .ooRexxShell~readline then do -- I want the doskey macros and filename tab autocompletion... Delegates the input to cmd. -- HKEY_CURRENT_USER/Software/Microsoft/Command Processor/CompletionChar = 9 address value .ooRexxShell~systemAddress @@ -215,7 +218,7 @@ address -- restore if queued() <> 0 then parse pull "inputrx=" inputrx end - when queued() == 0 & lines() == 0 & .ooRexxShell~systemAddress~caselessEquals("bash") then do + when queued() == 0 & lines() == 0 & .ooRexxShell~systemAddress~caselessEquals("bash") & .ooRexxShell~readline then do -- I want all the features of readline when editing my command line (history, tab completion, ...) -- Two lines are pushed to rxqueue : -- one generated by the internal command 'set', which manages the escaped characters. @@ -435,6 +438,7 @@ ::attribute isInteractive class -- Are we in interactive mode, or are we executing a one-liner ? ::attribute prompt class -- The prompt to display ::attribute RC class -- Return code from the last executed command +::attribute readline class -- When .true, the readline functionality is activated (history, tab expansion...) ::attribute securityManager class ::attribute queuePrivateName class -- Private queue for no interference with the user commands ::attribute queueInitialName class -- Backup the initial external queue name (probably "SESSION") @@ -479,6 +483,10 @@ self~traceCommand = .false +::method unknown + return 0 + + ::method command use arg info if self~traceCommand then do @@ -497,18 +505,6 @@ return 1 -::method environment - return 0 - - -::method call - return 0 - - -::method local - return 0 - - ::method adjustCommand use strict arg address, command if address~caselessEquals("cmd") then do @@ -520,8 +516,14 @@ if command~caselessPos("set ") == 1 then return command -- variable assignment if command~caselessPos("cd ") == 1 then return command -- change directory if .RegularExpression~new("[:ALPHA:]:")~~match(command)~position == 2 then return command -- change drive - if command~word(1)~caselessEquals("cmd") then return command -- already prefixed by "cmd ..." + args = .platform~string2args(command) + if args[1]~caselessEquals("cmd") then return command -- already prefixed by "cmd ..." + if args[1]~caselessEquals("start") then return command -- already prefixed by "start ..." + exepath = .platform~which(args[1]) + exefullpath = qualify(exepath) + if .platform~subsystem(exefullpath) == 2 then return 'start "" 'command -- Don't wait when GUI application return 'cmd /c "'command'"' + end else if address~caselessEquals("bash") then do -- If directly managed by the systemCommandHandler then don't add bash in front of the command @@ -577,22 +579,184 @@ ------------------------------------------------------------------------------- ::class platform ------------------------------------------------------------------------------- + +-- Class level + +::attribute current class -- the current platform is a singleton + + +::method initialize class -- init not supported (can't instatiate itself or subclass from init) + use strict arg -- none + parse source sysrx . + select + when sysrx~caselessAbbrev("windows") then self~current = .WindowsPlatform~new("windows") + when sysrx~caselessAbbrev("aix") then self~current = self~new("aix") + when sysrx~caselessAbbrev("sunos") then self~current = self~new("sunos") + when sysrx~caselessAbbrev("linux") then self~current = self~new("linux") + otherwise self~current = self~new(sysrx~word(1)~lower) + end + + ::method is class use strict arg name - return self~name == name + return self~name~caselessEquals(name) -::method name class - parse source sysrx . - select - when sysrx~caselessAbbrev("windows") then return "windows" - when sysrx~caselessAbbrev("aix") then return "aix" - when sysrx~caselessAbbrev("sunos") then return "sunos" - when sysrx~caselessAbbrev("linux") then return "linux" - otherwise return sysrx~word(1)~lower +::method unknown class -- delegates to the singleton + use strict arg msg, args + forward to (self~current) message (msg) arguments (args) + + +-- Instance level + +::attribute name + + +::method init + use strict arg name + self~name = name + + +::method which + use strict arg filespec + if filespec("location", filespec) == "" then return SysSearchPath("PATH", filespec) + else if SysIsFile(filespec) then return filespec + return "" + + +------------------------------------------------------------------------------- +::class WindowsPlatform subclass platform +------------------------------------------------------------------------------- +::method which + -- The order of precedence in locating executable files is given by the PATHEXT environment variable. + use strict arg filespec + pathext = value("PATHEXT",, "ENVIRONMENT")~translate(" ", ";") + if filespec("location", filespec) == "" then do + if filespec("name", filespec)~pos(".") == 0 then do + do while pathext <> "" + parse var pathext ext pathext + which = SysSearchPath("PATH", filespec || ext) + if which <> "" then return which + end + end + which = SysSearchPath("PATH", filespec) + if which <> "" then return which end + else do + if filespec("name", filespec)~pos(".") == 0 then do + do while pathext <> "" + parse var pathext ext pathext + if SysIsFile(filespec || ext) then return filespec || ext + end + end + if SysIsFile(filespec) then return filespec + end + return "" + + +::method string2args public + -- Converts a string to an array of arguments. + -- Arguments are separated by whitespaces (anything < 32) and can be quoted. + use strict arg string + args = .Array~new + i = 1 + loop label arguments + -- Skip whitespaces + loop + if i > string~length then return args + if string~subchar(i) > " " then leave + i += 1 + end + + current = .MutableBuffer~new + loop label current_argument + if string~subchar(i) == '"' then do + -- Chunk surrounded by quotes : whitespaces are kept, double occurrence of quotes are replaced by a single embedded quote + loop label quoted_chunk + i += 1 + if i > string~length then return args~~append(current~string) + select + when string~subchar(i) == '"' & string~subchar(i+1) == '"' then do + current~append('"') + i += 1 + end + when string~subchar(i) == '"' then do + i += 1 + leave quoted_chunk + end + otherwise current~append(string~subchar(i)) + end + end quoted_chunk + end + if string~subchar(i) <= " " then do + args~append(current~string) + leave current_argument + end + -- Chunk not surrounded by quotes : ends when a whitespace or quote is reached + loop + if i > string~length then return args~~append(current~string) + if string~subchar(i) <= " " | string~subchar(i) == '"' then leave + current~append(string~subchar(i)) + i += 1 + end + end current_argument + end arguments + return args + + +::method subsystem + -- Return the id of the subsystem needed to execute the executable. + -- Remember : GetBinaryType does not return this information. + -- Rexx adaptation of : + -- http://support.microsoft.com/?scid=kb%3Ben-us%3B90493&x=13&y=16 + /* + #define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. + #define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. + #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. + #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. + ... + More values defined in winnt.h + */ + use strict arg exename + signal on notready + stream = .Stream~new(exename) + if stream~open("read shared binary") <> "READY:" then return 0 + e_magic = stream~charIn(1, 2) + if e_magic <> "4D5A"x then return 0 -- MZ + e_lfnanew = stream~charIn(61, 4) + stream~seek(bytes2integer32(e_lfnanew) + 1) + ntSignature = stream~charIn(, 4) + if ntSignature <> "50450000"x then return 0 -- PE\0\0 + stream~seek("+88") + subsystem = stream~charIn(, 2) + return bytes2integer16(subsystem) + notready: + return .false + + +::routine bytes2integer16 + use strict arg string + byte2 = string~subchar(2)~c2d + byte1 = string~subchar(1)~c2d + integer16 = 256 * byte2 + byte1 + if byte2 >= 128 then return integer16 - 65536 + return integer16 + + +::routine bytes2integer32 + use strict arg string + numeric digits 10 + byte4 = string~subchar(4)~c2d + byte3 = string~subchar(3)~c2d + byte2 = string~subchar(2)~c2d + byte1 = string~subchar(1)~c2d + integer32 = 16777216 * byte4 + 65536 * byte3 + 256 * byte2 + byte1 + if byte4 >= 128 then return integer32 - 4294967296 + return integer32 + + ------------------------------------------------------------------------------- ::requires "rxregexp.cls" Modified: incubator/ooRexxShell/readme.txt =================================================================== --- incubator/ooRexxShell/readme.txt 2010-01-25 20:04:17 UTC (rev 5512) +++ incubator/ooRexxShell/readme.txt 2010-01-25 22:57:22 UTC (rev 5513) @@ -32,16 +32,19 @@ MYHANDLER> exit the exit command is supported whatever the interpreter -Current problems : -- Under Windows, if you want the colors then you must put ctext.exe in your PATH +Known problems under Windows : + +- If you want the colors then you must put ctext.exe in your PATH. You can get ctext here : http://dennisbareis.com/freew32.htm -- Under Windows, if you launch oorexx from a .bat file, then you need to prepend cmd /c - to have the doskey history working correctly. + +- If you launch ooRexxShell from a .bat file, then you need to prepend cmd /c to have the + doskey history working correctly. cmd /c ""my path to\rexx" "my path to\ooRexxShell"" -- Under Windows, the default console code page is the OEMCP, which does not match the - default ANSI code page (ACP). That bring troubles when you execute a command which - contains letters with accent. I could bypass this problem by converting OEMCP to ACP - in the securiy manager, but there is a more general workaround that can be used : + +- The default console code page is the OEMCP, which does not match the default ANSI + code page (ACP). That bring troubles when you execute a command which contains + letters with accent. This problem could be bypassed by converting OEMCP to ACP in the + securiy manager, but there is a more general workaround that can be used : Change the default code page of the console to ACP. For example, european users could enter this command : chcp 1252 You must also change the font of the console, because a raster font can't display letters @@ -49,14 +52,37 @@ See: http://blogs.msdn.com/michkap/archive/2005/02/08/369197.aspx http://en.wikipedia.org/wiki/Windows-1252 -- Under Windows, if you launch a GUI application then the ooRexxShell will wait until the end - of the execution (which is not the case when launched from the command prompt). -- All platforms, when the first word of the command is an interpreter name, then it is assumed - you want to temporarily select this interpreter. The first word is removed from the command - passed to the subcommand handler. Ex : if you enter cmd /? then only /? will be executed. + +- Assuming you defined this doskey macro : ll=ls -lap $* + you will see a difference of behavior between + CMD> ll + and + CMD> cmd ll + and + ooRexx[CMD]> 'll' + and + ooRexx[CMD]> ll + - In the first case, the macro works as expected. + - In the second and third case, the macro is not expanded. This is because the macro expansion + is done by readline (not when evaluating the command) and only the first word of the command + line is expanded by doskey (here "cmd" or 'll' is the first word). + - In the last case, the macro is expanded, but you don't what that... + ls -lap + Nonnumeric value ("LS") used in arithmetic operation + RC= 41.1 + [Note : these problems do not occur under Linux with Bash because the aliases are expanded + only when the interpreter is Bash and the command is evaluated.] + +Known problems under all platforms : + +- When the first word of the command is an interpreter name, then it is assumed you want to + temporarily select this interpreter. The first word is removed from the command passed to + the subcommand handler. Ex : if you enter cmd /? then only /? will be executed. If you want to execute this interpreter instead of selecting it, then you can enter : "cmd" /? cmd cmd /? + "bash" --help + bash bash --help See demo/hostemu_from_THE.png This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |