home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
rxpea11.zip
/
RxPutEA.CMD
Wrap
OS/2 REXX Batch file
|
1994-08-30
|
16KB
|
657 lines
/*
Program: RxPutEA
Date: 27-Aug-1994
Original Author: Craig Schneiderwent
[CompuServe: 74631,165]
[Internet: 74631.165@compuserve.com]
Purpose: After I noticed that Golden CommPass will store file descriptions in
the EAs for a downloaded file, I decided to make more use of the
Standard Extended Attributes (SEAs) provided by OS/2. This program
provides a way to update some of the SEAs.
By writing another program to call this one, I can update SEAs en masse.
This allows me to do some record keeping within the OS/2 file system
about files contained there. This also saves me some time explaining
what's in a particular ZIP stored on a shared network drive: I tell
people to go to the 'File' pages of the settings notebook.
Syntax: Run without any parameters and the proper syntax will be shown.
Return Codes: 0 - Normal EOJ
1 - Syntax error
2 - Can't find target file
Icon file not found
3 - Invalid EA name
7 - Internal logic error
8 - EA READ error
9 - EA WRITE error
OPEN error on icon file
READ error on icon file
CLOSE error on icon file
Notes: The .SUBJECT SEA is limited to 40 characters. Values specified for
this SEA which are greater than 40 characters in length will be
truncated.
The .HISTORY and .KEYPHRASES SEAs are really supposed to be what the
IBM Control Program Guide and Reference calls Multi-Valued Multi-Typed
data. These are relatively strange creatures, consisting of
reversed-byte hex values in what I call the 'descriptor' area, followed
by the type of data to be stored (I only allow ASCII in this program),
followed by the length of the data to be stored, followed by a null
byte ('00'x), followed by the data to be stored.
Setting the .ICON SEA seems to work, except the icon doesn't
appear until you open the settings dialog for the affected file.
You can only replace the .ICON SEA (-M has no effect).
For more information about the horrors of SEAs, consult the
Control Program Reference which is part of the IBM Toolkit.
On the off-chance anyone cares: this program is public domain software. Use it,
abuse it, just don't charge for it. Take a look at the code - who'd pay for it?
Given our litigious society...
DISCLAIMER
Users of this program must accept this disclaimer of warranty:
"This program is supplied as is. The original author disclaims all
warranties, expressed or implied, including, without limitation,
the warranties of merchantability and of fitness for any purpose.
The original author assumes no liability for damages, direct or
consequential, which may result from the use of this program."
*/
Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
Call SysLoadFuncs
myName = 'RxPutEA'
version = '1.1'
EAT_ASCII = 'FDFF'
EAT_MVMT = 'DFFF'
EAT_ICON = 'F9FF'
CODEPAGE = '0000'
ASCII = 1
MVMT = 2
ICON = 3
eaType = 0
nbOfEAs = 0
nbOfEAsFirstByte = '00'
nbOfEAsSecondByte = '00'
Call LoadSEAs
quietMode = 0
modifyEA = 0
Select
When Words(Arg(1)) = 0 Then
Do
Call ShowSyntax
Call EndThisPlease 1
End
When (Translate(Word(Arg(1), 1) = '/H')) |,
(Translate(Word(Arg(1), 1) = '/?')) |,
(Translate(Word(Arg(1), 1) = '-H')) |,
(Translate(Word(Arg(1), 1) = 'HELP')) |,
(Translate(Word(Arg(1), 1) = '?')) Then
Do
Call ShowSyntax
Call EndThisPlease 0
End
When Words(Arg(1)) > 0 Then NOP
Otherwise
Do
Call ShowSyntax
Call EndThisPlease 0
End
End
Call GetSwitches Arg(1)
/*
Make sure the source file exists.
*/
rc = CheckForFile( Word(Arg(1), 1) )
If rc = 0 Then
fileName = fullPathName
Else
Do
Say myName':' Word(Arg(1), 1) 'does not exist'
Call EndThisPlease 2
End
/*
Make sure the EA Name is a Standard EA that we can deal with.
*/
rc = EditEAName( Word(Arg(1), 2) )
If rc = 0 Then
eaName = editedEAName
Else
Do
Say myName':' Word(Arg(1), 2) 'is not an acceptable EA name'
Call ShowSyntax
Call EndThisPlease 3
End
Call GetCmdLineEAValue Arg(1)
If quietMode Then
NOP
Else
Call ShowParms
If eaType = ICON Then
Do
Call DoSpecialIconStuff
End
Else
NOP
If modifyEA Then
Do
Call MassageExistingEAValue
End
Else
NOP
rc = WriteTheEA()
If rc = 0 Then
Call EndThisPlease 0
Else
Call EndThisPlease 9
Exit 0
/*
Get the EA value entered on the command line. It's delimited with single quotes, and
any single quotes within the EA value are doubled.
*/
GetCmdLineEAValue: Procedure Expose eaValue
eaValue = ''
weAreDone = 0
lookingForMatch = 0
argLine = Arg(1)
Parse Arg argLine . ' ' . ' ' restOfLine
/*
Examine each byte. We're done when we've encountered a closing single quote
followed by a space.
*/
Do i = 1 To Length(restOfLine)
aChar = Substr(restOfLine, i, 1)
If aChar = "'" Then
Do
If lookingForMatch Then
lookingForMatch = 0
Else
lookingForMatch = 1
If Length(restOfLine) > (i + 1) Then
If Substr(restOfLine, (i+1), 1) = ' ' Then
weAreDone = 1
Else
NOP
Else
weAreDone = 1
End
Else
NOP
If lookingForMatch Then
eaValue = eaValue || aChar
Else
NOP
If weAreDone Then Leave i
End
eaValue = Strip(eaValue, , "'")
/*
The .SUBJECT SEA has a limit of 40 characters.
*/
If eaName = '.SUBJECT' & (Length(eaValue) > 40) Then
eaValue = Substr(eaValue, 1, 40)
Else
NOP
Return
/*
Add the appropriate 'descriptor' to the front of the EA value and
write it out.
*/
WriteTheEA:
Select
When eaType = ASCII Then
Do
eaInfo = X2C(EAT_ASCII),
|| D2C( Length(eaValue) ),
|| '00'x,
|| eaValue
End
When eaType = MVMT Then
Do
If nbOfEAs < X2D('FF') Then
Do
nbOfEAsFirstByte = '00'
nbOfEAsSecondByte = nbOfEAs + 1
If nbOfEAsSecondByte < 10 Then
nbOfEAsSecondByte = '0' || nbOfEAsSecondByte
Else
NOP
nbOfEAsWord = nbOfEAsSecondByte || NbOfEAsFirstByte
End
Else
Do
nbOfEAsFirstByte = Substr( D2C( Length(eaValue) ), 1, 1)
nbOfEAsSecondByte = Substr( D2C( Length(eaValue) ), 2, 1)
nbOfEAsWord = nbOfEAsSecondByte || nbOfEAsFirstByte
End
If modifyEA & (nbOfEAs > 0) Then
Do
eaInfo = X2C(EAT_MVMT,
|| CODEPAGE,
|| nbOfEAsWord),
|| eaValue
End
Else
Do
eaInfo = X2C(EAT_MVMT,
|| CODEPAGE,
|| nbOfEAsWord,
|| EAT_ASCII),
|| D2C( Length(eaValue) ),
|| '00'x,
|| eaValue
End
End
When eaType = ICON Then
/*
The length of the icon data is a reversed-byte word.
*/
Do
If Length(eaValue) < X2D('00FF') Then
Do
iconLengthFirstByte = X2C('00')
iconLengthSecondByte = D2C( Length(eaValue) )
End
Else
Do
iconLengthFirstByte = Substr( D2C( Length(eaValue) ), 1, 1)
iconLengthSecondByte = Substr( D2C( Length(eaValue) ), 2, 1)
iconLength = iconLengthSecondByte || iconLengthFirstByte
End
eaInfo = X2C(EAT_ICON),
|| iconLength,
|| eaValue
End
Otherwise
Do
Say myName 'Application error - EA Type not set'
Call EndThisPlease 7
End
End
rc = SysPutEA(fileName, eaName, eaInfo)
If rc = 0 Then
NOP
Else
Say myName': Error - SysPutEA return code =' rc
Return rc
/*
Read the existing EA value and add the appropriate 'descriptor'
information.
*/
MassageExistingEAValue:
rc = GetExistingEAValue()
If rc = 0 Then
Do
Select
When eaType = ASCII Then
Do
eaValue = existingEAValue,
|| ' ',
|| eaValue
End
When eaType = MVMT Then
Do
eaValue = existingEAValue,
|| X2C(EAT_ASCII),
|| D2C( Length(eaValue) ),
|| '00'x,
|| eaValue
End
When eaType = ICON Then
Do
/*
You can't add to an icon, only replace it.
*/
NOP
End
Otherwise
Do
Say myName 'Application error - EA Type not set'
Call EndThisPlease 7
End
End
End
Else
Call EndThisPlease 8
Return
/*
Read the EA value and parse it.
*/
GetExistingEAValue:
rc = ReadTheEA()
If rc = 0 Then
Select
When eaType = ASCII Then
Do
reversedExistingEAValueAndStuff = Reverse(existingEAValueAndStuff)
Parse Var reversedExistingEAValueAndStuff reversedExistingEAValue '00'x .
existingEAValue = Reverse(reversedExistingEAValue)
End
When eaType = MVMT Then
Do
/*
This is relatively bizarre, I know. Values within the EA "descriptor"
are reversed.
*/
nbOfEAsFirstByte = Substr( existingEAValueAndStuff, 6, 1 )
nbOfEAsSecondByte = Substr( existingEAValueAndStuff, 5, 1 )
nbOfEAs = C2D( nbOfEAsFirstByte || nbOfEAsSecondByte )
existingEAValue = Substr(existingEAValueAndStuff, 7)
End
When eaType = ICON Then
Do
/*
You can't add to an icon, only replace it.
*/
NOP
End
Otherwise
Do
Say myName 'Application error - EA Type not set'
Call EndThisPlease 7
End
End
Else
rc = 1
Return rc
ReadTheEA:
rc = SysGetEA(fileName, eaName, existingEAValueAndStuff)
If rc = 0 Then
NOP
Else
Say myName': Error - SysGetEA return code =' rc
Return rc
/*
Get any command line switches.
*/
GetSwitches:
aLine = Reverse(Arg(1))
Parse Var aLine reversedCmdLineSwitches "'" .
cmdLineSwitches = Reverse(reversedCmdLineSwitches)
i = 0
Do While i \= Words(cmdLineSwitches)
i = i + 1
Select
When Translate(Word(cmdLineSwitches, i)) = '-M' Then
Do
modifyEA = 1
If switchAt = 0 Then
switchAt = i
Else
If switchAt > i Then
switchAt = i
Else
NOP
End
When Translate(Word(cmdLineSwitches, i)) = '-Q' Then
Do
quietMode = 1
If switchAt = 0 Then
switchAt = i
Else
If switchAt > i Then
switchAt = i
Else
NOP
End
Otherwise NOP
End
End
Return
/*
Make sure we can deal with this SEA.
*/
EditEAName: Procedure Expose editedEAName sea. seaEAType. eaType
rc = 1
Do i = 1 To sea.0
If Translate( Strip( Arg(1) ) ) = sea.i Then
Do
rc = 0
editedEAName = Translate( Strip( Arg(1) ) )
eaType = seaEAType.i
Leave i
End
Else
NOP
End
Return rc
/*
Make sure the specified file exists, and return its full path name
*/
CheckForFile: Procedure Expose fullPathName
fullPathName = Stream(Arg(1), 'C', 'QUERY EXISTS')
If fullPathName = '' Then
rc = 1
Else
rc = 0
Return rc
/*
The .ICON SEA is (big surprise) entirely different than the other SEAs
handled by this program. Rather than specifying the ea-value on the
command line, the user specifies the file containing the icon data (a .ICO
file) where they normally would specify the ea-value.
*/
DoSpecialIconStuff:
/*
Make sure the icon file exists.
*/
rc = CheckForFile( eaValue )
If rc = 0 Then
Do
iconFileName = fullPathName
rc = OpenFileForRead(iconFileName)
If rc = 0 Then
Do
Call GetFileSize(iconFileName)
Call ReadEntireFile iconFileName, fileLength
rc = CloseFile(iconFileName)
If rc = 0 Then
eaValue = iconFileContents
Else
Do
Say myName': CLOSE error on' iconFileName
Call EndThisPlease 9
End
End
Else
Do
Say myName': OPEN error on' iconFileName
Call EndThisPlease 9
End
End
Else
Do
Say myName':' eaValue 'does not exist'
Call EndThisPlease 2
End
Return
/*
Open the file specified in the parameter for read only.
*/
OpenFileForRead: Procedure
aString = Stream(Arg(1), 'C', 'OPEN READ')
If aString = 'READY:' Then
rc = 0
Else
rc = 1
Return rc
/*
Get the size of the file specified in the parameter.
*/
GetFileSize: Procedure Expose fileLength
fileLength = Stream(Arg(1), 'C', 'QUERY SIZE')
Return
/*
Read the entire file specified in the parameter.
*/
ReadEntireFile:
Call ON NOTREADY NAME ReadFileErr
iconFileContents = Charin( Arg(1), 1, Arg(2) )
CALL OFF NOTREADY
Return
/*
Oops, an error occurred on read.
*/
ReadFileErr:
Say myName '* File Read Error!'
Call EndThisPlease 9
Return
/*
Close the file specified in the parameter.
*/
CloseFile: Procedure Expose quietMode
aString = Stream(Arg(1), 'C', 'CLOSE')
If aString = 'READY:' Then
rc = 0
Else
rc = 1
Return rc
LoadSEAs:
sea.0 = 5
sea.1 = '.COMMENTS'
sea.2 = '.HISTORY'
sea.3 = '.SUBJECT'
sea.4 = '.KEYPHRASES'
sea.5 = '.ICON'
seaEAType.1 = ASCII
seaEAType.2 = MVMT
seaEAType.3 = ASCII
seaEAType.4 = MVMT
seaEAType.5 = ICON
Return
/*
Just what it says...
*/
ShowSyntax:
Say myName version 'Syntax:'
Say Copies(' ', Length(myName)) myName "file-name ea-name 'ea-value' [-M] [-Q]"
Say myName 'Adds/modifies a Standard Extended Attribute (SEA) for a file.'
Say Copies(' ', Length(myName)) 'Parameters are separated with spaces. The ea-value should be'
Say Copies(' ', Length(myName)) 'enclosed in single quotes. If the ea-value contains single'
Say Copies(' ', Length(myName)) 'quotes, make each single quote into two single quotes.'
Say Copies(' ', Length(myName)) 'The ea-value for an icon should refer to the icon file.'
Say myName 'switches: (separate them with spaces please)'
Say Copies(' ', Length(myName)) '-M modify existing SEA'
Say Copies(' ', Length(myName)) '-Q quiet mode (suppress messages)'
Say myName 'Accepted SEAs:'
Do i = 1 To sea.0
Say Copies(' ', Length(myName)) sea.i
End
Return
/*
Show the parameters being used in this run.
*/
ShowParms:
Say myName version ' ' Date() Time()
Say ' Source File: ' fileName
Say ' EA Name: ' eaName
If Length(eaValue) > 50 Then
Say ' EA Value: ' Substr(eaValue, 1, 50) '[...]'
Else
Say ' EA Value: ' eaValue
If modifyEA Then
Say ' Modify EA: Yes'
Else
Say ' Modify EA: No'
Return
/*
Just what it says...
*/
EndThisPlease:
If quietMode Then
NOP
Else
Say myName': return code =' Arg(1)
Exit Arg(1)