Engine Room - V1N2



A lot of people have asked Major Weenie, "If Warp is so great, why doesn't it come with a built-in programming language?" Clearly, these people haven't bothered to actually check their Warp core because they would have discovered that one of the very best batch, scripting, and all around programming languages ever to cross the Great Barrier comes with every copy of Warp: REXX. REXX, an IBM FLA (Four Letter Acronym), stands for REstructured eXtended eXecutor. REXX was invented and first put together by an IBM'er in the U.K., Mike Cowlishaw, in the spring of 1979. To blatantly steal from the forward to The REXX Handbook (by Gabriel Goldberg and Philip H. Smith III, McGraw-Hill, 1992), "REXX is good because so much of it is obvious;" (which is why it appeals to Major Weenie) "it is elegant and straightforward to use and easy to learn." REXX began life on IBM's VM systems, found its way to MVS, then OS/2 1.x, then eventually onto AIX (IBM's UNIX), then the OS/400 operating system found on the AS/400 midrange system, and last but not least, on IBM PC DOS 7. It has also been submitted to the American National Standards Institute for adoption as the computer batch language standard. At some point, if you decide you really want to get deeply into REXX, then contact IBM and acquire a copy of one of their "redbooks" called OS/2 REXX: From Bark to Byte which, aside from having many good programming examples, contains excellent tips on how to make your REXX code as platform NON-specific as possible (i.e., how to write a REXX program that will run in any of the places REXX is found, with the fewest number of changes). Inevitably, sometime before Major Weenie nods off, someone asks him, "Ok, if REXX is so great, what can you do with it?" In the case of Warp, a better question might be, what CAN'T you do with it? Well, for one thing, you can't really write any workplace shell applications with it, altho' it has a rudimentary popup dialog box that you can call from inside a REXX exec. At the end of the column, Major Weenie will share a nice Warped practical joke he has played over the years on rookies fresh from the Academy with this dialog box. Even without a WPS interface, that leaves a veritable galaxy of things you can do with REXX, but first, let's clear a little programmer convention-type gibberish out of the way. As you'll discover in the online REXX book, ALL REXX programs must begin with a comment. In a REXX program, anything between a slash asterisk (/*) and an asterisk slash (*/) is a comment. Comments can be nested inside comments. In Warp, a REXX program is a plain text file with a filetype of CMD. At this point one of the slackers around the replicator usually spills their prune juice and wants to know if the STARTUP.CMD file found in the root directory of their Warp system is a REXX exec. Probably not, but it could be. The chances are, if you have a STARTUP.CMD (Warp's version of the venerable AUTOEXEC.BAT), it is just a plain old batch file. You can tell easily enough by opening it with an editor and checking for that telltale beginning comment. If you decide to delve into REXX programming in Warp (or anywhere come to think of it), a good editor can make a lot of difference. IBM didn't forget REXX programmers: Check out the Enhanced Editor (EPM) in the Productivity folder. If you identify the file you are editing as having a CMD file type, EPM will do some rudimentary syntax completion for you. One of the best ways to get started with REXX is to use the REXXTRY command that is built into Warp, along with the online REXX Information. From an OS/2 command prompt, if you enter rexxtry, this is what you'll see:

'''REXXTRY.CMD lets you interactively try REXX statements. Each string is executed when you hit Enter. Enter 'call tell' for a description of the features. Go on - try a few... Enter 'exit' to end.''' If you enter the call tell that's suggested, you'll see this:

'''/* SAA-portable REXXTRY procedure 11/08/91 version 1.05 Owned by IBM SAA REXX Development, Endicott, New York. Loosely derived from an ancient formulation of Mike Cowlishaw. This procedure lets you interactively try REXX statements. If you run it with no parameter, or with a question mark as a parameter, it will briefly describe itself. You may also enter a REXX statement directly on the command line for immediate execution and exit. Example: rexxtry call show Enter 'call show' to see user variables provided by REXXTRY. Enter '=' to repeat your previous statement. Enter '?' to invoke system-provided online help for REXX. The subroutine named 'sub' can be CALLed or invoked as 'sub'. REXXTRY can be run recursively with CALL. Except for the signal instructions after a syntax error, this procedure is an example of structured programming. The 'clear' routine illustrates system-specific SAA-portable coding. */ rc = 0 ......................................... REXXTRY.CMD on OS/2''' Getting the idea? If you prefer to work from the Workplace Shell, they thought of that, too. There is a GUI REXX function library, PMREXX (it's required to use the dialog box function). If you enter 'pmrexx rexxtry' at the command prompt, you can do all the same things, only in a GUI window. It also gives you the benefit of being able to save the output in a file, so if you should be working on something that's giving you trouble, you can use the PMREXX interface to turn tracing on, then save the output to a file when you get your routine straightened out. Now at this point, Major Weenie could delve into some programming 101 type stuff, but he will have expected you to cover that at the Academy, or, barring that, use REXXTRY to cover it. Now, before we get to that practical joke, how about something useful? A true Warp aficionado knows about using the ALT-F1 keystroke at boot time to get to the recovery choices screen. Most users do not know that there is a way to customize that screen to boot to something other than the pre-programmed fall backs. (Search the Master Help Index on config.sys, then follow the instructions under Using Recovery Choices During Restart to learn about customizing the recovery choices screen.) One of the things I have discovered is useful is to be able to boot OS/2 with my regular config.sys, but without the workplace shell. In and of itself, that's easy enough to do, and is really easy if you automate it with REXX. To boot to a command prompt, you just substitute PROTSHELL=C:\OS2\CMD.EXE for the statement PROTSHELL=C:\OS2\PMSHELL.EXE in your config.sys. (Note, if you installed Warp on something other than the C: drive, then these lines will be different.) Now, part of this alternate boot is to give this altered config.sys a specific name and place it in your \OS2\BOOT directory and update the file called ALTF1BOT.SCR to point to it. All of the altered config.sys files end in a single letter, and that letter refers to the letter that identifies that choice on the recovery choices screen.

'''NOTE: Never erase the file called CONFIG.X in the OS2\BOOT subdirectory! That's the file that will get booted if you happen to choose the Boot to a command prompt choice on the recovery choices screen.''' Config.x is all well and good as a command prompt boot choice, but you don't have access, probably, to anything you have installed since Warp itself since config.x is your very first config.sys file. In my case, I have chosen the letter P for plain to designate my Workplace Shell-less configuration. Being a major weenie, my config.sys changes frequently so being too lazy to do the updating of config.p by hand, I wrote this simple exec which you are welcome to steal.

'''/* Makes a 'plain' config.sys */       /* <-- this is the leading comment */ '@c:'                          /* <-- operating system functions are enclosed in single quote marks */ '@cd\os2\boot' '@if exist config.p del config.p' dat = 'PROTSHELL=C:\OS2\CMD.EXE' /* simple, declaratives */ Prot = 'protshell' Tablein = 'PROTSHELL' Tableout = 'protshell' File = 'C:\CONFIG.SYS' Out = 'CONFIG.P' RC = Linein(File,,0)   /* <-- open a file for input; there're other ways */ RC = Lineout(Out,,1)   /* <-- open a file for output; ditto */ Do While Lines(File) > 0 RC = Linein(File) Temp = RC       Test = Left(Temp, 9) Test = Translate(Test, Tableout, Tablein) /* translates all the input to lower case before comparing it to see if it's the PROTSHELL line I'm looking for... *        If Test = Prot Then Do                       RC = Lineout(Out, Dat) Iterate End /* Do */ RC = Lineout(Out, Temp) End /* Do */ RC = Lineout(Out) RC = Stream(File, 'C', 'Close') Exit 0''' Now, the Exit statement is not absolutely required because the program will just "fall out the bottom" without it anyway. But Major Weenie does have some standards, altho' they are very low. The Major calls this exec MAKEPLAIN.CMD (he's an HPFS kinda guy, so you FAT Warped people will have to call it something else with 8 characters or less). What this program loop does is erase config.p if it exists, read in each line of config.sys, convert the line to all lower case letters (Major Weenie is not a very fastidious typist), and then examine the line to see if it starts with the letters protshell. If it doesn't then it just writes the line back out as it found it. If the line in config.sys is the protshell line, it substitutes 'PROTSHELL=C:\OS2\CMD.EXE' for the existing protshell line. The perfect gift for the lazy hacker. Perhaps next time around Major Weenie will favor you with something not quite so esoteric. If, however, you're running an OS/2 BBS system, this is the way to run it without the Workplace Shell-- saves you overhead and makes the system uninteresting to the passerby. Now, here's the practical joke Major Weenie promised you. First, the PMREXX interface cannot be called from directly inside the REXX exec, so, what better place to put the call than STARTUP.CMD where your soon-to-be ex-friend will see it every time they boot their system? So... add a line like this to their STARTUP.CMD (or create one if they don't have one):

@start pmrexx chump.cmd Then, use the editor to create CHUMP.CMD, which reads like this: '''/* a funny exec, maybe...*/ call RxFuncAdd 'RxMessageBox', 'RexxUtil', 'RxMessageBox' if RxMessageBox('Press Cancel to prevent erasing your harddisk.',, 'Fatal System Error Message','cancel','WARNING') = 2 then nop if RxMessageBox('Erasing your hard disk... ',, 'Erase Offending Disk','cancel','HAND') = 2 then nop call SysSleep 3 if RxMessageBox('Chump...','Chump Notification','Ok','Exclamation') = 7 then Exit'''

Two commas at the end of the lines of code above are line continuation characters, by the way. That is, if you have some lines of code that are too long for you to comfortably read or edit, you can split them up with a comma and they will be treated as a single line of code. You know, maybe you should try a test run of CHUMP.CMD on yourself before you decide to use it. Oops, my communicator is going off. The Captain's probably trying to get me to go to another Multicultural Society meeting. I would, but who can understand their agenda? Until next time, I remain,

Major Weenie