ACMAINT 3.0: AH Users Guide


1. Introduction

The ACMAINT Account Handler (AH) is the primary administrator interface to ACMAINT. To users familiar with earlier versions of ACMAINT, on the outside, the 3.0 ah command appears similar to its ancestors. However, in actuality, this version has involved a complete rewrite using the language, Extended Tcl (TclX). TclX's strengths enhance the interface as well as provide users with online help for the Tcl/TclX and AH commands and the opportunity to truly customize their AH environments. In addition, context-sensitive help has been added for the AH commands and their fields.

2. How to Start AH

Once the ACMAINT has been installed (by the system administrator), AH will then be able to perform account, group, and alias administrative tasks. The most common way to invoke AH is to use the command

    % ah

which starts an interactive AH shell. This way is probably the best for the beginning AH user. The other way is to execute a single AH command from the UNIX command line. This can be quite useful when desiring to execute an AH command from within a shell script. For example, to quickly look up a user's information, you could execute the following command (the backslash is need to prevent the shell from expanding it).

     % /usr/local/etc/acmaint/ah show_group other \*
     groupname: other,
                groupId: 1
                password: rzydyoVJ7LI9o
	      groupOwner: root

NOTE: after this documentation was written, the path became:

      /opt/acmaint/bin/ah    then it became:       /opt/acmaint/3.9/bin/ah

3. All Categories and Commands

ACMAINT 3.0 AH commands somewhat resemble those which were used in the 2.0 AH. In addition to the account manipulation commands, the new AH now also provides commands to enable the administration of groups and aliases. The commands are divided into seven categories as shown in Table 1. When a user is given access to AH, he/she is given access to specific categories of commands. Thus it is possible for an AH user to be authorized to create accounts but not to delete them (discussed further in Section 5).

The commands' purposes, syntaxes, and fields are presented in greater detail in Appendices A, B, and C. 9

Table 1.
Categories and their Commands
admin create modify delete fetch message any
create host create account modify account delete account fetch disable log
delete host create alias modify alias delete alias show account enable readscript
modify host create aliasmembers modify classgid delete aliasmembers show alias message  
  create classgid modify classuid delete classgid show aliasmembers unmessage  
  create classuid modify group delete classuid showclassgid    
  create group modify user delete group show classuid    
  create groupmembers setquota disk delete groupmembers show group    
  create user   delete user show groupmembers    
  copy     show host    
        show user    

4. Using AH

Even though the ACMAINT 3.0 AH utility is a complete rewrite of the old AH, we tried to maintain some consistency with respect to its functionality. Furthermore, the AH commands were written to expand the command set of Extended Tcl, not circumvent it. By doing so, the user has the ability to use standard Extended Tcl commands and constructs in order to help perform daily administrative tasks.

When entering an AH command, you can specify all of the argument as in the following example

	ah> create group other 1 ! root

However, you could instead execute the same command in the following manner.

	ah> create group
	groupName [] > other
	groupId [*] > 1
	password [!] >
	groupOwner [bac] > root
	Created group "other", groupid: "1", password: "kaNYzA9I".

Some AH commands require that others be performed first. For instance, in order to create a user's account, the user must be created and the login group must already exist (as in the previous example). In the following example, user, bac, is created: accounts are created on two hosts with the home directory /home/harbor/a/bac; and finally, a quota is set on /home/harbor/a, the file system on which the home directory resides.

	ah> create user bac Chaney {Beth A.} {} 000-00-0000 * harbor.ecn 123-
	4567 494-0000 {MSEE ???} ECN S {} zsite
	Created user "Beth A. Chaney", uniqueid: "000-00-0000", login: "bac",
	uid: "101".
	ah> create account bac
	hostName [] > harbor.ecn valkyrie.ecn
	groupName [other] >
	password [!] >
	acctType [] >
	authName [] >
	expirDate [19960515] > 19970515
	loginShell [/bin/csh] >
	homeDir [/home/harbor/a] >
	Added login "bac", password: "4iTy7oFu" on "".
	Added login "bac", password: "4iTy7oFu" on "".

	ah> setquota disk bac harbor.ecn /home/harbor/a
	soft block [0] > 2500
	hard block [0] > 3000
	soft inode [0] >
	hard inode [0] >
	Set quota for login "bac" on host "" to "/home/
	harbor/a 2500 3000 0 0".

In the above example, two methods are used to specify the use of the default value for a field's value: the "{}" used as a field value as in the case of create user command and the &gl;CR< as the field value's prompt as in the case of the create account. The default value is displayed in the prompt when AH prompts for a field's value. The "*" in the create account command is used to specify that the userId is to be selected from the list of available user ID's. Finally, the "!" as the password in the create account command (It is the default value in the prompt) indicates that the password is to be generated.

The ACMAINT 3.0 AH now makes group and alias maintenance much more manageable. The following example, shows the creation and population of a group on all hosts in the ACMAINT database.

	ah> create group staff
	groupId [*] >
	password [!] >
	groupOwner [bac] >
	Created group "staff", groupid: "105", password: "faMo3I9U".

	ah> create groupmembers staff
	loginName [] > bac davy kcd
	hostGroup [] > *
	Added login "bac davy kcd " to group "staff" for host group "*".

When many AH tasks need to be completed, an AH script can be used rather than entering the commands interactively. Such a script contains the various commands which are to be executed when the AH command readscript is run. The only difference between interactively entering commands and using an AH script is that incomplete commands result in errors rather than prompts. An AH script to execute the commands shown above would look something like

Reminder ... AH 3.0 uses ! instead of * to generate a new login or userId:

	# Example AH script containing the commands shown in the 
	# above examples.
	create group other 1 ! root

	create user bac Chaney {Beth A.} {} 000-00-0000 ! harbor.ecn 123-4
	567 494-0000 {MSEE ???} ECN S {} zsite

	create account bac {harbor.ecn valkyrie.ecn} other ! {} {} 1997051
	5 {} {}
	setquota disk bac harbor.ecn /home/harbor/a 2500 3000 {} {}
	create group staff * ! ()
	create groupmembers staff {bac kcd davy} *

5. AH Customization

As stated earlier, ACMAINT 3.0 AH was written using Extended Tcl in order to provide AH users with flexibility and with the ability to customize their AH environments. In order to do either, knowledge of Tcl and possibly TclX is necessary. A brief explanation of Tcl is provided in the ACMAINT design specification, and more detailed information can be obtained from Tcl books and online documentation.

As you use the various AH commands, you may find that you use specific combinations of commands often. One such sequence might consist of the commands: create user, create account, setquota disk. Assuming that the same home directory is to be used for all of a user's accounts, you could write a proc similar to tone of the following. The first example is rather limited and not particularly user-friendly; however, it gives you a relatively straight forward example of how you might write such a proc. The second example which performs the same set of commands is more complex but is much more useful since it sets up the new command, makeAccount, to prompt the user for additional information if it is not provided.

Example 1:
     proc makeAccount {loginName hostName surName prefName suffName uniqueId
	userId mailHost homePhone offPhone offNumber dept classif affils
	sitePref groupName password acctType authName expirDate loginShell
	homeDir soft-block hard-block soft-inode hard-inode} {

	global ACMAINT_OK
	# Build the DBD commands which are to be sent to the DBD.
	set userCommand [list createUser $loginName $surName $prefName \
		$suffName $uniqueId $ $userId $mailHost $homePhone \
		$offPhone $offNumber $dept $classif $affils $sitePref]
	set acctCommand [list create Account $loginName $hostName \
		$groupName $password $accType $authName $expirDate \
		$loginShell $homeDir]
	set quotaCommand [list setDiskQuota $loginName $hostName \
		$homeDir $soft-block $hard-block $soft-inode $hard-inode]

	# Execute the commands at the level they would have been executed
	# if they had been done from the AH prompt.  If an error occurs, then
	# display such a message and kick out.
	set result [uplevel 1 $userCommand]
	if {$result != $ACMAINT_OK} {
		puts stderr "makeAccount: createUser failed."
	set result [uplevel 1 $accountCommand]
	if {$result != $ACMAINT_OK} {
		puts stderr "makeAccount: createAccount failed."

	foreach entry $hostName {
		set quotaCommand [concat [list setDiskQuota $loginName \
			$entry] $quotaArgs]

		set result [uplevel 1 $quotaCommand]
		if {$result != $ACMAINT_OK} {
			puts stderr "makeAccount: setquota failed."

Example 2:
     # Make sure that we are accessing the global cmdinfo array containing
     # all of the command information.  This array enables us to define
     # what the AH prompt text will be, the default value, and what to 
     # execute in order to display context-sensitive help.
     global cmdinfo
     # Define the makeAccount command information.
     set cmdInfo (makeAccount,prompt) [list \
	   [list loginName	{set default (loginName)}		 \
		{help /fields/create/user/loginName}]		      \
	   [list hostName	{set default (hostName)}		 \
		{help /fields/create/user/hostName}]		      \
	   [list surName	{set default (surName)}			 \
		{help /fields/create/user/surName}]		      \
	   [list prefName	{set default (prefName)}	         \
		{help /fields/create/user/prefName}]		      \
	   [list suffName	{set default (suffName)}		 \
		{help /fields/create/user/suffName}]		      \
	   [list uniqueId	{set default (uniqueId)}		 \
		{help /fields/create/user/uniqueId}]		      \
	   [list userId		{set default (userId)}			 \
		{help /fields/create/user/userId}]		      \
	   [list mailHost	{set default (mailHost)}	         \
		{help /fields/create/user/mailHost}]		      \
	   [list homePhone	{set default (homePhone)}	         \
		{help /fields/create/user/homePhone}]		      \
	   [list offPhone	{set default (offPhone)}	         \
		{help /fields/create/user/offPhone}]		      \
	   [list offNumber	{set default (offNumber)}                \
		{help /fields/create/user/offNumber}] 		      \
	   [list dept		{set default (dept)} 		         \ 
		{help /fields/create/user/dept; displayList deptList}]\ 
	   [list classif	{set default (classif)}                  \
		{help /fields/create/user/classif; displayList classifList}] \
	   [list affils		{set default (affils)}			 \
		{help /fields/create/user/affils}]		      \
	   [list sitePref	{set default (sitePref)}		 \
		{help /fields/create/user/sitePref}]		      \
	   [list groupName	{set default (groupName)}		 \
		{help /fields/create/user/groupName}]		      \
	   [list password	{set default (password)}		 \
		{help /fields/create/user/password}]		      \
	   [list accType	{set default (accType)}			 \
		{help /fields/create/user/accType}]		      \
	   [list authName	{set default (authName)}		 \
		{help /fields/create/user/authName}]		      \
	   [list expirDate	{set default (expirDate)}		 \
		{help /fields/create/user/expirDate}]		      \
	   [list loginShell	{set default (loginShell)}		 \
		{help /fields/create/user/loginShell}]		      \
	   [list homeDir	{set default (homeDir)}			 \
		{help /fields/create/user/homeDir}]		      \
	   [list {soft block}	{set default (softBlock)}		 \
		{help /fields/setquota/disk/block}]		      \
	   [list {hard block}	{set default (hardBlock)}		 \
		{help /fields/setquota/disk/block}]		      \
	   [list {soft inode}	{set default (softInode)}		 \
		{help /fields/setquota/disk/inode}]		      \
	   [list {hard inode} 	{set default (hardInode)}		 \
		{help /fields/setquota/disk/inode}]		      \
     # Define the category to which the makeAccount proc will belong and
     # specify whether you will use the string returned by the DBD.  More
     # often than not, you will want to do so.
     set cmdInfo(makeAccount,category)		create
     set cmdInfo(makeAccount,useDBDstring)	y
     # makeAccount {} -- Proc which prompts the user for the information
     #			 needed to create a user, account, and set the 
     #			 quota.  It then executes all of the appropriate
     #			 commands.
     # proc makeAccount {loginName hostName surName prefName suffName
     #		userId mailHost homePhone offPhone offNumber dept
     #		classif affils sitePref groupName password acctType
     #		authName expirDate loginShell homeDir soft-block hard-block
     #		soft-inode hard-inode} {
     proc makeAccount {args} {

	   global cmdInfo
           # If this command is being obtained via the "readscript" 
    	   #command, then don't prompt for additional fields.
     	   set command [getCommand makeAccount $args]
     	   if {$command == {}} { 

     	   # Now that we have all of the information, grab the 
  	   # loginName and hostName fields since they are going 
	   # to be used quite a bit.  
     	   # Then remove
    	   #	  makeAccount loginName hostName
     	   # from the command.
           set loginName [lindex $command 1]
           set hostName [lindex $command 2]
           set command [lreplace $command 0 2]
     	   # Initialize the commands and quota arguments lists.
     	   set userCommand [list createUser $loginName]
     	   set accountCommand [list createAccount $loginName $hostName]
     	   set quotaArgs {}
     	   # Now let the games begin.  We are attempting to grab 
  	   # the information from the data entered which will be used 
	   # for each of the commands: create user, create account, 
	   # and setDiskQuota.
     	   # We already have the loginName, thus we don't need to 
 	   # grab it from the remaining arguments (thus the -1).
     	   set userLength [expr [llength $cmdInfo(createUser,prompt)] -1]

     	   # We already have the loginName and hostName, thus 
	   # we don't need to obtain them from the remaining information.
     	   set acctLength [expr $userLength + \
  	  	 [llength $cmdInfor(createAccount,prompt)] -2]
     	   set index 1
     	   foreach entry $command {
	  	 if {$index <= $userLength} {
			lappend userCommand $entry
	   	 } elseif {$index <= $acctLength} {
			lappend accountCommand $entry
			if {$index == $acctLength} {

		                # If so, then it is the home directory, 
				# and we need that information in order 
				# to set the quota on the file system on 
				# which the home directory resides.
		   		lappend quotaArgs $entry
     	   	} else {
	  		 lappend quotaArgs $entry
           	incr index
     	   # The rest should look pretty similar to Example 1 now 
	   # that we have complete commands.
     	   set result [uplevel 1 $userCommand]
     	   if {$result != $ACMAINT_OK} {
	  	 puts stderr "makeAccount: createUser failed."
     	   set result [uplevel 1 $accountCommand]
     	   if {$result != ACMAINT_OK} {
	  	 puts stderr "makeAccount: createAccount failed."

     	   foreach entry $hostName {
	  	 set quotaCommand [concat [list setDiskQuota $loginName \
			$entry] $quotaArgs]

	   	set result [uplevel 1 $quotaCommand]
	   	if {$result != $ACMAINT_OK} {
			puts stderr "makeAccount: setquota failed."

In addition to writing proc, AH users can define their own default values

	ah> set default (expirDate) "19970515".

You can determine what fields have defined defaults as well as their default values.

	ah> array names default
	homeDir sitePref type loginName softInode authName password 
	homePhone quotaType hostClass offNumber uniqueId userId classif
	suffName hardIn ode general softBlock loginShell mailHost 
	hardBlock mailEnable groupId hostGroup surName status accType
	affils dept offPhone expirDate groupName prefName clientEble
	ah> set default(homeDir)

if you find that there are certain AH default fields' values that you wish to have set each time you start AH, then you can place the commands to set those values in the file "$HOME/.ahrc". For example

	# Beth's AH configuration file.
	puts "Sourcing my default file"
	set default(expirDate) "19970515"
	set default(homeDir) "/home/harbor/a"
	set actions "$env(HOME)/tmp/ah.actions"
	set errors "$env(HOME)/tmp/ah.errors"

6. Online Help

Extended Tcl's built-in help facility builds a help tree which makes it possible to keep the help information somewhat organized. You can determine your current location in the help tree as well as what information is present by using commands like the following

	ah> help

	Subjects available in /:
		commands/	fields/		tcl/
	Help pages available in /:
	ah> helpcd commands
	ah> help

	Subjects available in /commands:
		create/		delete/		modify/
		setquota/	show/
	Help pages available in /commands:
		copy		disable		enable
		log		message 	readscript
		fetch		unmessage

Probably, the best way to learn about the command is to type at the AH prompt

	ah> help help

In addition to the built-in help facility, we have provided context sensitive help. If while entering an AH command you need further information on a particular field, then enter '?` at the field's prompt. For example,

	ah> create user
	loginName [] > bac
	surName [] > Chaney
	prefName [] > Beth A.
	suffName [] > ?

	suffName(n)	AH create user Fields		suffName(n)
	suffName - User's suffix name(s)
		This field should include all of the parts of the 
		name which follow the surName.  This includes
		values like "Jr.", "Sr.", and "III".

		This field is restricted to a length of no more than
		64 characters.
	fields/create/user/surName, fields/create/user/prefName

	suffName [] >

7. AH Logging

The AH log command enables the user to specify the filenames to which successful and/or erroneous commands are logged.

	ah> log actions successful/action/filename
	ah> log errors erroneous/action/filename

Unlike the 2.0 AH log files, 3.0's not only store the commands but also the resulting strings in the format of an AH script.

	# Example AH successful actions log file.
	create group other 1 ! root
	# Created group "other", groupid: "1", password: "kaNYzA91".
	create user bac Chaney {Beth A.} {} 000-00-0000 * harbor.ecn
	123-4567 494-0000 {MSEE ???} ECN S {} zsite
	# Created user "Beth A. Chaney", uniqueid: "000-00-0000", login:
	"bac", uid: "101".
	create account back {harbor.ecn valkyrie.ecn} other ! {} {}
	19970515 {} {}
	# Added login "bac", password: "4iTy7oFu" on 
	# Added login "bac", password: "4iTy7oFu" on 
	set quota disk bac harbor.ecn /home/harbor/a 2500 3000 {} {}
	# Set quota for login "bac" on host "" to
	"/home/harbor/a/ 2500 3000 0 0".
	create group staff * ! {}
	# Created group "staff", groupid: "105", password: "faMo3I9U".
	create groupmembers staff {bac kcd davy} *
	# Added login "bac davy kcd" to group "staff" for host group "*".

This format was chosen in order to make and correcting and retrying commands which had resulted in errors much easier than before. For example, if in the above example, the group other had not been created, then the subsequent create account commands would have failed, resulting in entries in the errors log file.

	create account bac {harbor.ecn valkyrie.ecn} other ! {} {}
	19970515 {} {}
	# createAccount: Group "other" does not exist.

The user could then possibly create the needed group and use the errors log file as an AH script in an attempt to successfully execute the commands which had previously failed.

8. AH Administration

In the past, all AH commands have been available to any person who had access to the ah command. For the most part, this worked well; however, there are times when it would be nice to make certain sets of commands available to users who do not necessarily have root access. With that in mind, AH is now written so that it can be run as a setuid program. Furthermore, now each authorized AH user is assigned categories of commands which he/she is permitted to use. This information is kept in a Tcl list in the AHPERMSFILE. Such a file may look something lie this.

	set ahperms [list \
		[list bac {admin create delete fetch message modify}] \
		[list johndoe {message}] \

In this case, bac and johndoe are listed as authorized AH users. The user, bac, is able to execute those commands in all of the categories. On the other hand, johndoe is only authorized to use commands in the message category: disable, enable, message, and unmessage.

The commands create host, modify host, and delete host are available to AH users who are authorized to use the admin commands. It is recommended that the number of individuals with access to the admin commands be kept at a minimum; possibly just those individuals responsible for host registrations.

9. Conclusion

For experienced AH users, this document has hopefully shown you what changes you will find. For new AH users, it is hoped that it has given you a general idea of what to expect and also to show what is possible once one becomes familiar with Tcl and the new AH commands. Books on Tcl and the online documentation are probably the best way to gain that familiarity. As always, experimenting and using AH should help you become more comfortable with the AH interface and enable you to truly utilize its strengths and features to make your administrative tasks easier. Enjoy!

Last modified: 2018/09/12 10:13:57.923160 GMT-4 by mark.senn.1
Created: 2007/10/08 09:10:32.240000 GMT-4 by brian.r.brinegar.1.



Type in a few keywords describing what information you are looking for in the text box below.

Admin Options: Edit this Document