[HOWTO] - Use niutil

gatorparrots

~departed~
First, it is always a good idea to read the existing information about the user:
niutil -read . /users/userx

The output will be generally similar to this:
Code:
authentication_authority: ;basic; ;LocalWindowsHash;
picture: /Library/User Pictures/Animals/Butterfly.tif
_shadow_passwd: 
hint: 
uid: 502
_writers_passwd: userx
realname: userx
_writers_hint: userx
gid: 20
shell: /bin/tcsh
name: userx
_writers_tim_password: userx
passwd: 3wbpLri9iMo
_writers_picture: userx
home: /Users/userx
sharedDir: Public

Here is the general syntax for the command line method for changing a user's home directory:
sudo niutil -createprop . /users/userx home "/Volumes/drivename/directory"
You're creating a property on top of one that already exists, overwriting the previous home directory (i.e. /Users/userx/) with the new one on another volume and directory altogether (on/Volumes/drivename/directory).

To confirm the changes, I recommend running the initial command again:
niutil -read . /users/userx

Code:
authentication_authority: ;basic; ;LocalWindowsHash;
picture: /Library/User Pictures/Animals/Butterfly.tif
_shadow_passwd: 
hint: 
uid: 502
_writers_passwd: userx
realname: userx
_writers_hint: userx
gid: 20
shell: /bin/tcsh
name: userx
_writers_tim_password: userx
passwd: 3wbpLri9iMo
_writers_picture: userx
home: /Volumes/drivename/directory
sharedDir: Public

And of course, you would want to
chmod -R 765 /Volumes/drivename/directory
and
chown -R userx /Volumes/drivename/directory
(or whatever is appropriate for your particular scenario).
 
First, create the path structure:
sudo niutil -create / /locations/lookupd/hosts
Then create the needed values:
sudo niutil -createprop / /locations/lookupd/hosts LookupOrder CacheAgent NIAgent DNSAgent

You want to modify the hosts lookup order, since this is responsible for resolving domain names.

Finally, restart lookupd to affect the changes:
sudo kill -HUP `cat /var/run/looupd.pid`
 
On a local area network, it makes sense to have hostnames for various machines and to be able to access them via their hostname.

For example, you have "BigMac" and "Sidecar". The NetInfo databases on both machines needs to be updated to include the new hosname aliases.

Find out the IP address of each computer (if they are not known already). On each machine, issue this command:
ifconfig en0 inet

Next, add the new hostnames. Mac OS X relies on NetInfo instead of the traditional /etc/hosts file. (All of the commands below need root access, so rather than sudo each, it is more effecient to sudo -s and exit when done.)
sudo -s
niutil -create . /machines/BigMac
niutil -createprop . /machines/BigMac ip_address "192.168.1.2"
niutil -create . /machines/Sidecar
niutil -createprop . /machines/Sidecar ip_address "192.168.1.3"

Restart lookupd to register these changes:
kill -HUP `cat /var/run/lookupd.pid`
exit
 
Note that if BigMac and Sidecar both run OS 10.2, they will be able to find each other's addresses using Rendezvous name resolution. If "local" is specified in Network Preferences' "Additional Search Domains", the names "BigMac" and "Sidecar" will resolve. If not, they can be looked up with "BigMac.local" and "Sidecar.local".
 
Okay; now that we have the basics down, I have a real-world application. Our network is behind firewall/router that does not allow loopbacks. Therefore, changing the lookup order and adding machines entries to NetInfo to get local domain name resolution is the preferred method for adding entries to access our domain named e-mail server. This works fine for desktop machines within the confines of a LAN.

However, I have a laptop user to contend with who is not always on the network. He often travels and dials-up on the road. NetInfo 'machines' entries will trump his DNS resolution, making our domain-named e-mail and web server inaccessible to him when not behind our router/firewall.

The ideal solution(?) is to have the user switch lookup orders for when they are on the road and back when they are behind the network. I elected to create an AppleScript to do the job and install the Script Menu in the user's menubar to make the script easily accessible.

Overall, it seemed like the most effecient way to accomplish the goal. For those interested, here is the script in its enirety. (Save as an AppleScript application from Script Editor.)
Code:
(*
This script will set optimize your lookup order for a LAN internet connection  or dial-up
*)

set runresult to ""

tell me to activate
display dialog "Please choose your connection method to optimize your internet connection" buttons {"LAN", "Dial-up"} default button 2
set userchoice to button returned of result
if userchoice = "LAN" then
	repeat
		set theResponse to display dialog "Please enter your administrator password:" default answer "" with icon caution
		set thePassword to the text returned of theResponse
		try
			do shell script "sudo ls" password thePassword with administrator privileges
			exit repeat
		on error
			display dialog "Sorry, that password is invalid." buttons {"Cancel", "Try Again"} default button "Try Again" with icon stop
		end try
	end repeat
	try
		--LAN optimized
		tell application "Microsoft Entourage" to quit
		do shell script "sudo /usr/bin/niutil -create / /locations/lookupd/hosts" password thePassword with administrator privileges
		do shell script "sudo /usr/bin/niutil -createprop / /locations/lookupd/hosts LookupOrder CacheAgent NIAgent DNSAgent" password thePassword with administrator privileges
		do shell script "sudo /bin/kill -USR1 `/bin/cat /var/run/lookupd.pid`" password thePassword with administrator privileges
		do shell script "sleep 1"
		do shell script "/usr/bin/open '/Applications/Microsoft Office X/Microsoft Entourage'"
		do shell script "sleep 5"
		tell me to activate
		set runresult to "Network settings optimized for LAN connection" & return
	on error errormsj
		display dialog errormsj as string
		set runresult to runresult & "Settings change failed: " & errormsj & return
		--return adds ASCII13 to the output
	end try
	--end if
	
	tell me to activate
	display dialog (runresult as string) buttons {"Ok"}
	
else if userchoice = "Dial-up" then
	repeat
		set theResponse to display dialog "Please enter your administrator password:" default answer "" with icon caution
		set thePassword to the text returned of theResponse
		try
			do shell script "sudo ls" password thePassword with administrator privileges
			exit repeat
		on error
			display dialog "That's not a valid password!" buttons {"Cancel", "Try Again"} default button "Try Again" with icon stop
		end try
	end repeat
	try
		--Dial-up optimized
		tell application "Microsoft Entourage" to quit
		do shell script "/usr/bin/niutil -create / /locations/lookupd/hosts" password myPassword with administrator privileges
		do shell script "/usr/bin/niutil -createprop / /locations/lookupd/hosts LookupOrder CacheAgent DNSAgent NIAgent" password myPassword with administrator privileges
		do shell script "/bin/kill -USR1 `/bin/cat /var/run/lookupd.pid`" password myPassword with administrator privileges
		do shell script "sleep 1"
		do shell script "/usr/bin/open '/Applications/Microsoft Office X/Microsoft Entourage'"
		do shell script "sleep 5"
		tell me to activate
		--display progress
		set runresult to "Settings optimized for dial-up connection"
	on error errormsj
		display dialog errormsj as string
		set runresult to errormsj
	end try
	--end if
	tell me to activate
	display dialog ("Network Configuration:" & return & runresult) as string buttons {"Ok"}
end if
 
I had to revise the script above to include a routine to quit/restart Microsoft Entourage (the MUA used) in order to get it to notice the lookup order change. Also, I revised the authentication scheme to be more robust (handling null or incorrectly entered passwords). Please update your copy if you have download the previous version I had posted/
 
Back
Top