Display UIC on OpenVMS as easy as id on Unix and Linux

On Unix it is easy to get your numeric UID and the GIDs of your primary group and secondary groups. You call the program id simply. On OpenVMS it is not such easy to retrieve your numeric UIC which is OpenVMS’s equivalent to Unix’ UID and GID. With a bit DCL magic you can write a command procedure which tells you the UIC as easy as id tells you your UID and GID on Unix. By programming this little command procedure you will also get introduced to lexical functions in DCL.

If you want to know your UID, your groups and the corresponding GIDs on Unix you use the command id. For example:

$ id
uid=1374(ogm) gid=20(users)

If you want to know only the numeric values of your UID and your (primary) GID you use the flags -u and -g:

$ id -u
1374
$ id -g
20

As a Unix guy challenged by the world of OpenVMS you will always hear something about the UIC (user identification code) on OpenVMS. It is a tuple [group,member] which identifies an user or a group of users. With your Unix background you realize very soon it’s a similar concept to Unix’ UID and GID, but in some kind of a mixture. Unfortunately you do not find a command like Unix’ id to display this UIC on OpenVMS’ DCL interpreter (DEC Command Language). So let’s explore how to get a command procedure which will display us the UIC in the form of [group,member] for the current user.

Constructing a Solution

On the DCL you have several lexical functions available. They follow the format

F$Name([args,...])

F$ is a prefix indicating that the following is a lexiacal function. The Name tells what function to call. Inside the always present parentheses the arguments of the function find their place.

BTW: A complete reference of all lexical functions you will find in the HP OpenVMS DCL Dictionary.

Our solution begins with determining current user’s name. This purpose serves the lexical function F$USER(). You can put the result into a symbol and show it afterwards:

$ ME = F$USER()
$ SHOW SYMBOL ME
  [OLIVER]

Or you can print it directly:

$ WRITE SYS$OUTPUT F$USER()
[OLIVER]

Now we need to map this determined user name to a numeric UIC. For this purpose exists the lexical function F$IDENTIFIER(). For example:

$ UIC_INT = F$IDENTIFIER("OLIVER", "NAME_TO_NUMBER")
$ SHOW SYMBOL UIC_INT
  UIC_INT = 4194305   Hex = 00400001  Octal = 00020000001

Now it is only one little step to convert this output into the required form of [group,member]. To do so we use the lexical function F$FAO() which converts characters and numeric values into ASCII strings. F$FAO() operates in a similar way as printf does on UNIX’ shell. To convert a long word integer to a numeric UIC in the format [group,member] F$FAO() provides the special sequence !%U for its control string:

$ UIC = F$FAO("!%U", UIC_INT)
$ SHOW SYMBOL UIC
  UIC = "[100,1]"

This looks well and looks like it can be composed with F$USER() to one single command. Unfortunately there is one little detail to have an eye on.

Preparing the User Name

F$USER() returns the user name in brackets. F$IDENTIFIER() expects in its first argument the user name without brackets. So we need to remove the brackets to provide a working solution.

There is the lexical function F$EXTRACT() which extracts substrings from a given string. Its syntax is as follows and very simple to understand:

F$EXTRACT(sub_start, sub_length, from_string)

sub_start is the index of the first character of the substring within from_string. sub_length is the length of the resulting substring. from_string is the string from which the substring shall be extracted. For example:

$ WRITE SYS$OUTPUT F$EXTRACT(6,4,"APPLE TREE")
TREE

Note: As you see the counting of characters in a string starts at zero.

With this lexical function it is easy to extract the user name and remove the brackets respectively from F$USER()‘s output. To do so we simply need to determine the length of F$USER()‘s output and subtract 2 (the brackets) from it.

The length of a string returns the lexical function F$LENGTH(). To subtract 2 from the result we can use F$STRING(). F$STRING() evaluates the given string or numeric expression and returns the result as a string.

These ideas covered in DCL commands leads to this sequence:

$ WRITE SYS$OUTPUT F$USER()
[OLIVER]
$ WRITE SYS$OUTPUT F$LENGTH(F$USER())
8
$ WRITE SYS$OUTPUT F$STRING(F$LENGTH(F$USER())-2)
6
$ WRITE SYS$OUTPUT F$EXTRACT(1,F$STRING(F$LENGTH(F$USER())-2),F$USER())
OLIVER

The last one is exactly what we were looking for.

Final Command Procedure

All this combined in one single command results in this command procedure:

$! Program: GETUIC.COM
$! Purpose: Display UIC of current user.
$!
$! Copyright (c) 2013 Oliver Mueller, http://oliver-mueller.com
$! All rights reserved.
$!
$ WRITE SYS$OUTPUT F$FAO("!%U", -
    F$IDENTIFIER( -
      F$EXTRACT(1, F$STRING(F$LENGTH(F$USER())-2), F$USER()), -
      "NAME_TO_NUMBER"))

Feel free to download GETUIC.COM in this ZIP file.

Installation for All Users

Note: You will need the privilege SYSPRV to install GETUIC.COM for all users.

To install GETUIC.COM copy it to the location where your utilities normally reside, e.g. your own directory like DKA0:[TOOLS], or a global one like SYS$COMMON:[SYSEXE]. Afterward define a command by a symbol in SYS$COMMON:[SYSMGR]SYLOGIN.COM. For example:

$ GETUIC :== @DKA0:[TOOLS]GETUIC.COM

or

$ GETUIC :== @SYS$COMMON:[SYSEXE]GETUIC.COM

You should restrict the access rights to this file by invoking this command:

$ SET SEC/PROT=(S:RWED,O:RWED,G:E,W:E) DKA0:[TOOLS]GETUIC.COM

or

$ SET SEC/PROT=(S:RWED,O:RWED,G:E,W:E) SYS$COMMON:[SYSEXE]GETUIC.COM

After a new login everybody is able to use GETUIC as a command to determine her/his UIC. For example:

$ getuic
[100,1]

Installation Just for Your Own

An installation just for your own user is much simpler. Copy GETUIC.COM to your SYS$LOGIN folder. (This is the folder in which you reside after login.) Edit or create the file SYS$LOGIN:LOGIN.COM and put this line into it:

$ GETUIC :== @SYS$LOGIN:GETUIC.COM

Logout, login again and you are done! You can use the command GETUIC now. For example:

$ getuic
[100,1]

 

This entry was posted in DCL, OpenVMS and tagged , . Bookmark the permalink.

2 Responses to Display UIC on OpenVMS as easy as id on Unix and Linux

  1. jurgen says:

    Hi, i have reading out and i will definitely bookmarrk your site, just wanted to say i liked this article.

  2. whoah this blog is great i really like studying your posts. Stay up the good work! You know, lots of individuals are looking round for this info, you can help them greatly. |

Leave a Reply to jurgen Cancel reply

Your email address will not be published. Required fields are marked *