OS/2, eCS & ArcaOS - Technical > Programming

Mac Address in Classic Rexx

(1/3) > >>

Jan-Erik Lärka:
This code can list all my machines on the network (and send a wake upp call if they listen).
It doesn't however give me the hostname of the router/dhcp-server. Ideas how to?
 

--- Code: ---/*
 * Filename: macaddr.cmd
 *   Author: JAN-ERIK
 *  Created: Mon Sep 10 2012
 *  Purpose: Retrieve MAC Address
 *  Changes: 2019-07-25, Added support for Router
 *           2019-09-14, Updated support for localhost
 *           2019-09-15, OS2ENVIRONMENT -> ENVIRONMENT
 */
stem = 'host.'
IF 0 < ARG() THEN
   count = rxGetMacAddr( ARG(1) )
ELSE
   count = rxGetMacAddr()
DO i = 1 TO count
    /*magic.cmd*/
    /*Wake on Lan in REXX*/
    /*MAC = '11:22:33:44:55:66';*/
    MAC = host.i.macaddr
    SAY host.i.name||':' host.i.ipaddr||':' MAC;
    X = TRANSLATE( 'abcdefghijkl', host.i.macaddr, 'ab:cd:ef:gh:ij:kl' )
    call RxFuncAdd 'SockLoadFuncs', 'rxsock', 'SockLoadFuncs';
    call SockLoadFuncs( '*' );
    SCT = SockSocket( 'AF_INET', 'SOCK_DGRAM', 'IPPROTO_UDP' );
    RC = SockSetSockOpt( SCT, 'SOL_SOCKET', 'SO_BROADCAST', '1' );
    RC = SockIOCtl( SCT, 'FIONBIO', '0' );
    adr.!family = 'AF_INET';
    /*adr.!addr   = '255.255.255.255';*/
    adr.!addr   = host.i.ipaddr
    adr.!port   = 9;
    S = COPIES( D2C(255) ,6 );
    T = COPIES( X ,16);
    G = COPIES( D2C(0) ,6 );
    RC = SockConnect( SCT, "adr.!" );
    STG = S||T||G;
    SAY STG
    RC = SockSend( SCT, STG );
    call SockSoClose SCT;
END
RETURN 0

rxGetMacAddr: PROCEDURE EXPOSE (stem) /*<COMPUTERNAME>*/
    isStem = ( RIGHT( stem, 1 )  = '.' )
    stemval = STRIP( stem, 'T', '.' )
    retval = 0
    i = 1
    /* No parameters given, list all computers */
    IF ARG() = 0 THEN
    DO
        DO WHILE QUEUED() > 0; PARSE PULL; END;
        /* Computers on network */
        '@NET VIEW 2>&1|RXQUEUE'
        DO WHILE QUEUED() > 0
            PARSE UPPER VALUE LINEIN( 'QUEUE:' ) WITH '\\'computer.i' '.
            /* Add computer to list */
            IF LENGTH( computer.i ) > 0 THEN i = i + 1
        END
        computer.0 = i - 1
    END
    ELSE DO
        /* Search for a specific computer */
        computer.0 = 1
        computer.1 = TRANSLATE( ARG(1) )
    END
    j = 0
    DO WHILE QUEUED() > 0; PARSE PULL; END;
    DO i = 1 TO computer.0
       IF computer.i = VALUE( 'HOSTNAME',, 'ENVIRONMENT' ) THEN
       DO
          '@NETSTAT -a 2>&1|RXQUEUE'
          DO WHILE QUEUED() > 0
             PARSE UPPER VALUE LINEIN( 'QUEUE:' ) WITH 'ADDR 'ipnum' INTERFACE' .
             ipnum = STRIP( ipnum )
             IF ipnum <> '127.0.0.1' & ipnum <> '0.0.0.0' & ipnum <> '' THEN
                LEAVE
          END
          DO WHILE QUEUED() > 0; PARSE PULL; END;
          '@NETSTAT -n 2>&1|RXQUEUE'
          DO WHILE QUEUED() > 0
             PARSE UPPER VALUE LINEIN( 'QUEUE:' ) WITH 'PHYSICAL ADDRESS' machex 'MTU' .
             machex = STRIP( machex )
             IF machex <> 0 & LENGTH( machex ) = 12 & LENGTH( ipnum ) > 7 THEN
             DO
                j = j + 1
                machex = TRANSLATE( 'ab:cd:ef:gh:ij:kl', machex, 'abcdefghijkl', ':' )
                IF isStem THEN
                   INTERPRET stemval'.j.name = computer.i;'||stemval'.j.macaddr = TRANSLATE( machex, "0", " " );'||stemval'.j.ipaddr = ipnum;'||stemval'.0 = j; retval = j'
                ELSE
                   retval = retval||computer.i||' '||TRANSLATE( machex, "0", " " )||' '||ipnum||D2C(13)||D2C(10)
             END
          END
       END
       ELSE DO
          '@PING '||TRANSLATE( computer.i )||' 1 1 2>&1|RXQUEUE'
          DO WHILE QUEUED() > 0; PARSE PULL; END;
          '@ARP '||TRANSLATE( computer.i )||' 2>&1|RXQUEUE'
          DO WHILE QUEUED() > 0
             PARSE UPPER VALUE SUBWORD( LINEIN( 'QUEUE:' ), 2 ) WITH machex +17 ipnum .
             IF LENGTH( machex ) = 17 & LENGTH( ipnum ) > 7 THEN
             DO
                j = j + 1
                IF isStem THEN
                   INTERPRET stemval'.j.name = computer.i;'||stemval'.j.macaddr = TRANSLATE( machex, "0", " " );'||stemval'.j.ipaddr = ipnum;'||stemval'.0 = j; retval = j'
                ELSE
                   retval = retval||computer.i||' '||TRANSLATE( machex, "0", " " )||' '||ipnum||D2C(13)||D2C(10)
             END
          END
       END
    END
    IF 1 < computer.0 THEN
    DO
        DO WHILE QUEUED() > 0; PARSE PULL; END;
        '@ARP -a 2>&1|RXQUEUE'
        DO WHILE QUEUED() > 0
           arp = LINEIN( 'QUEUE:' )
           IF 0 < POS( ':', arp ) & 3 < WORDS( arp ) THEN
           DO
              PARSE UPPER VALUE arp WITH iface +13 macad +17 ipadd rest
              DO i = 1 To VALUE( stemval'.0' )
                 /* Add computer to list */
                 IF TRANSLATE( macad, "0", " " ) = VALUE( stemval'.i.macaddr' ) THEN LEAVE i
              END
              IF VALUE( stemval'.0' ) < i THEN
              DO
                 IF isStem THEN
                    INTERPRET stemval'.i.name = STRIP( iface );'||stemval'.i.macaddr = TRANSLATE( macad, "0", " " );'||stemval'.i.ipaddr = STRIP( ipadd );'||stemval'.0 = i;retval = i'
                 ELSE
                    retval = retval||STRIP( iface )||' '||TRANSLATE( macad, "0", " " )||' '||ipadd||D2C(13)||D2C(10)
              END
           END
        END
    END
RETURN retval
--- End code ---

xynixme:

--- Quote from: Jan-Erik Lärka on September 15, 2019, 07:43:43 am ---'@NET VIEW 2>&1|RXQUEUE'

VALUE( 'HOSTNAME',, 'OS2ENVIRONMENT' )
--- End quote ---

Two remarks not related to the question: not checking that NET exists can result in a RTFM SYS1041 error (no network, no argument) during an evaluation.

'ENVIRONMENT', please. Unless an author believes that supporting Microsoft OS/2 1.0 is more important than portable and shorter Rexx code. Both will work, but more Rexxes will support this without the superfluous 'OS2' prefix.

Jan-Erik Lärka:
The documentation should be updated as the word must indicate that no deviation from that was/is allowed in OS/2. I've altered the code anyhow.

From OS/2 Procedures Language 2/REXX Reference

--- Quote ---To use VALUE to manipulate OS/2 environment variables, selector must be the string 'OS2ENVIRONMENT' or an expression so evaluated. In this case, the variable name need not be a valid REXX symbol. When VALUE is used to set or change the value of an environment variable, the new value is retained after the REXX procedure ends.
--- End quote ---

Doug Bissett:

--- Quote ---rxGetMacAddr()
--- End quote ---

Do you not need to load support for this? I get absolutely nothing from running the program. Using TRACE ALL, it just falls through to the return.

Jan-Erik Lärka:
It use the output of commands such as arp, net view, netstat etc. that's part of IBM File and Print.
It should be possible to adapt it to Samba server as well in the future when Samba can run right away after installation.

Add the line

--- Code: ---call trace '?i'
--- End code ---
in the beginning of the code and run it.
Press Enter to continue and look at the output and you should see what it says.

Set the line to

--- Code: ---call trace 'i'
--- End code ---
and thus leave out the ? (question mark) in the beginning of the code and run it with

--- Code: ---macaddr>output.txt
--- End code ---
Then it output every row it execute without asking for confirmation.
The you can read the file output.txt and see where it fail.

Navigation

[0] Message Index

[#] Next page

Go to full version