home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March B / SCO_CASTOR4RRT.iso / scoadmin / root.3 / etc / mail / admin / multihome / multihome~
Text File  |  1998-08-19  |  49KB  |  1,947 lines

  1. #!/bin/osavtcl
  2. #******************************************************************************
  3. #
  4. #    Copyright (C) 1993-1997 The Santa Cruz Operation, Inc.
  5. #        All Rights Reserved.
  6. #
  7. #    The information in this file is provided for the exclusive use of
  8. #    the licensees of The Santa Cruz Operation, Inc.  Such users have the
  9. #    right to use, modify, and incorporate this code into other products
  10. #    for purposes authorized by the license agreement provided they include
  11. #    this notice and the associated copyright notice with any such product.
  12. #    The information in this file is provided "AS IS" without warranty.
  13. #
  14. #===============================================================================
  15. loadlibindex /usr/lib/sysadm.tlib
  16. proc SCO_USER_MHOME_MSGS {} {}
  17. global SCO_USER_MHOME_MSGS
  18. set SCO_USER_MHOME_MSGS(@catalog@) {mhome.cat@mail 1}
  19. set SCO_USER_MHOME_MSGS(MSG_HELPBOOK) {1 multihome}
  20. set SCO_USER_MHOME_MSGS(ERR_OPEN_FAIL) {2 {Unable to open file: %1$s}}
  21. set SCO_USER_MHOME_MSGS(ERR_NO_MAP) {3 {No map created for %1$s,\nfile contents may be invalid.}}
  22. set SCO_USER_MHOME_MSGS(ERR_NOHOST) {4 {Host (%1$s) not found.}}
  23. set SCO_USER_MHOME_MSGS(ERR_BADHOST) {5 {Host (%1$s) not responding.\nPlease check the following:\n   * your network configuration\n   * your network connection\n   * rhost permissions on the remote site\n   * that SCOadmin is installed at the remote site}}
  24. set SCO_USER_MHOME_MSGS(ERR_COPY_OUT) {6 {Unable to fetch %1$s\nCreate new file?}}
  25. set SCO_USER_MHOME_MSGS(ERR_COPY_BACK) {7 {Unable to copy back to %1$s.}}
  26. set SCO_USER_MHOME_MSGS(ERR_PARSE) {8 {Parse errors are contained in %1$s\nContinue and remove bad lines?}}
  27. set SCO_USER_MHOME_MSGS(ERR_WRITE) {9 {Unable to write %1$s.}}
  28. set SCO_USER_MHOME_MSGS(ERR_NO_VDOMAINS) {10 {No virtual domains found.}}
  29. set SCO_USER_MHOME_MSGS(ERR_BAD_SUSER) {11 {Bad system user.}}
  30. set SCO_USER_MHOME_MSGS(ERR_BAD_VUSER) {12 {Bad virtual user.}}
  31. set SCO_USER_MHOME_MSGS(ERR_DUP_VUSER) {13 {Duplicate virtual user.}}
  32. set SCO_USER_MHOME_MSGS(ERR_EXEC) {14 {Unable to exec (%1$s).}}
  33. set SCO_USER_MHOME_MSGS(ERR_RESOLV) {15 {Unable to resolve name (%1$s).}}
  34. set SCO_USER_MHOME_MSGS(ERR_TFADMIN) {16 {Failure in tfadmin authorization check}}
  35. set SCO_USER_MHOME_MSGS(MSG_DIRTY) {17 {Do you wish to save your changes?}}
  36. set SCO_USER_MHOME_MSGS(MSG_DOMAIN_UPDATE) {18 {The virtual domain map file is out of date:\n(%1$s)\nDo you wish to rebuild it?}}
  37. set SCO_USER_MHOME_MSGS(MSG_GO_BACK) {19 {Do you wish to return to host (%1$s)?}}
  38. set SCO_USER_MHOME_MSGS(MSG_USERS_FOR) {20 {Users for %1$s}}
  39. set SCO_USER_MHOME_MSGS(MSG_USER_ADD) {21 {Add User}}
  40. set SCO_USER_MHOME_MSGS(MSG_APP_TITLE) {22 {Virtual Domain User Manager}}
  41. set SCO_USER_MHOME_MSGS(MSG_TITLE) {23 {Virtual Domain User Manager on %1$s}}
  42. set SCO_USER_MHOME_MSGS(MSG_STATUS) {24 {Virtual Domains on %1$s}}
  43. set SCO_USER_MHOME_MSGS(MSG_MENU_HOST) {25 Host}
  44. set SCO_USER_MHOME_MSGS(MSG_MENU_HOST_MN) {26 t}
  45. set SCO_USER_MHOME_MSGS(MSG_MENU_OPEN) {27 {Open Host...}}
  46. set SCO_USER_MHOME_MSGS(MSG_TITLE_OPEN) {28 {Open Host}}
  47. set SCO_USER_MHOME_MSGS(MSG_MENU_OPEN_MN) {29 O}
  48. set SCO_USER_MHOME_MSGS(MSG_MENU_EXIT) {30 Exit}
  49. set SCO_USER_MHOME_MSGS(MSG_MENU_EXIT_MN) {31 x}
  50. set SCO_USER_MHOME_MSGS(MSG_MENU_EDIT) {32 Edit}
  51. set SCO_USER_MHOME_MSGS(MSG_MENU_EDIT_MN) {33 E}
  52. set SCO_USER_MHOME_MSGS(MSG_MENU_USER) {34 Users...}
  53. set SCO_USER_MHOME_MSGS(MSG_MENU_USER_MN) {35 U}
  54. set SCO_USER_MHOME_MSGS(MSG_MENU_ALIAS) {36 {Mail Aliases...}}
  55. set SCO_USER_MHOME_MSGS(MSG_MENU_ALIAS_MN) {37 A}
  56. set SCO_USER_MHOME_MSGS(MSG_MENU_RETIRE) {38 {Retire User...}}
  57. set SCO_USER_MHOME_MSGS(MSG_MENU_RETIRE_MN) {39 R}
  58. set SCO_USER_MHOME_MSGS(MSG_SHORT_OPEN) {40 {Manage virtual domain users on another host}}
  59. set SCO_USER_MHOME_MSGS(MSG_SHORT_EXIT) {41 {Exit Virtual Domain User Manager}}
  60. set SCO_USER_MHOME_MSGS(MSG_SHORT_USER) {42 {Edit Users in a virtual domain}}
  61. set SCO_USER_MHOME_MSGS(MSG_SHORT_ALIAS) {43 {Edit Mail Aliases in a virtual domain}}
  62. set SCO_USER_MHOME_MSGS(MSG_SHORT_RETIRE) {44 {Retire a User from all virtual domains}}
  63. set SCO_USER_MHOME_MSGS(MSG_LOADING) {45 Loading...}
  64. set SCO_USER_MHOME_MSGS(MSG_SAVING) {46 {Saving configuration...}}
  65. set SCO_USER_MHOME_MSGS(MSG_STR_OK) {47 OK}
  66. set SCO_USER_MHOME_MSGS(MSG_STR_YES) {48 Yes}
  67. set SCO_USER_MHOME_MSGS(MSG_STR_NO) {49 No}
  68. set SCO_USER_MHOME_MSGS(MSG_STR_CANCEL) {50 Cancel}
  69. set SCO_USER_MHOME_MSGS(MSG_STR_BROWSE) {51 Select...}
  70. set SCO_USER_MHOME_MSGS(MSG_STR_ADD_USER) {52 {Add User...}}
  71. set SCO_USER_MHOME_MSGS(MSG_STR_DEL_USER) {53 {Delete User}}
  72. set SCO_USER_MHOME_MSGS(MSG_VIRTUAL) {54 {Virtual User}}
  73. set SCO_USER_MHOME_MSGS(MSG_SYSTEM) {55 {System User}}
  74. proc \
  75. mhm_open_host {} \
  76. {
  77.     global mhm_host_name mhm_host_label mhm_host_resolv mhm_vdomains_data
  78.     global outerMainForm
  79.     # first save any previous changes, but keep open for cancel.
  80.     set ret [mhm_all_put]
  81.     switch $ret {
  82.     "ok" {
  83.     }
  84.     "fail" {
  85.         return
  86.     }
  87.     "cancel" {
  88.         return
  89.     }
  90.     }
  91.     # put up open host dialog and get result
  92.     set newhost [mhm_open_host_dialog]
  93.     if {"$newhost" == ""} {
  94.         return
  95.     }
  96.     # get full name of remote machine
  97.     set newhost [mhm_host_resolv $newhost]
  98.     if {"$newhost" == ""} {
  99.         VtUnLock
  100.         mhm_error1 NOHOST $newhost
  101.         VtLock
  102.         return
  103.     }
  104.     # save old host name for backout
  105.     set oldhost $mhm_host_name
  106.     # check if new host there
  107.     set ret [mhm_host_check $newhost]
  108.     if {"$ret" != "ok"} {
  109.         VtUnLock
  110.         mhm_error1 BADHOST $newhost
  111.         VtLock
  112.         return
  113.     }
  114.     # set new host name
  115.     set mhm_host_name $newhost
  116.     # unset cached list of vdomains
  117.     unset mhm_vdomains_data
  118.     set ret [mhm_all_get]
  119.     if {"$ret" == "no"} {
  120.         mhm_host_backout $oldhost
  121.         return
  122.     }
  123.     if {"$ret" == "fail"} {
  124.         mhm_host_backout $oldhost
  125.         return
  126.     }
  127.     set mhm_short_name [lindex [split $mhm_host_name "."] 0]
  128.         VtSetValues $outerMainForm -title [mhm_msg1 TITLE $mhm_short_name]
  129.     VtSetValues $mhm_host_label -label [mhm_msg1 STATUS $mhm_host_name]
  130.     mhm_display_mainlist
  131. }
  132. proc \
  133. mhm_host_backout { oldhost } \
  134. {
  135.     global mhm_host_name mhm_host_label mhm_vdomains_data DIRTY
  136.     VtUnLock
  137.     set ret [mhm_query_qyn GO_BACK $oldhost]
  138.     VtLock
  139.     if {"$ret" != "yes"} {
  140.         quit
  141.     }
  142.     set mhm_host_name $oldhost
  143.     unset mhm_vdomains_data
  144.     set DIRTY 0
  145.     set ret [mhm_all_get]
  146.     if {"$ret" == "no"} {
  147.         quit
  148.     }
  149.     if {"$ret" == "fail"} {
  150.         quit
  151.     }
  152. }
  153. proc \
  154. mhm_open_host_dialog {} \
  155. {
  156.     global ME PID
  157.     # file is used to pass results to preserve stdout for child process.
  158.     set file "/tmp/mhm.$PID"
  159.     system "rm -f $file"
  160.     VtControl -suspend
  161.     system "$ME -mhm_stand_host $file"
  162.     VtControl -resume
  163.     if {[file exists $file] == 1} {
  164.         set result [exec cat $file]
  165.         system "rm -f $file"
  166.     } else {
  167.         set result ""
  168.     }
  169.     return $result
  170. }
  171. proc \
  172. mhm_stand_host { file } \
  173. {
  174.     global app
  175.     global mhm_stand_text mhm_stand_outfile mhm_stand_form
  176.     # globals for callbacks
  177.     set mhm_stand_outfile $file
  178.     # init widget server
  179.     set app [VtOpen mailchild "mailadmin"]
  180.     mhm_setcat SCO_USER_MHOME
  181.     # std dialog box.
  182.     set mhm_stand_form [ \
  183.         VtFormDialog $app.mailchild \
  184.         -title [mhm_msg TITLE_OPEN] \
  185.         -resizable FALSE \
  186.         -ok -okCallback mhm_stand_host_ok \
  187.         -cancel -cancelCallback mhm_stand_open_quit \
  188.         -wmCloseCallback mhm_stand_open_quit \
  189.     ]
  190.     set mhm_stand_text [ \
  191.         VtText $mhm_stand_form.text \
  192.         -columns 40 \
  193.         -callback mhm_stand_host_jump \
  194.     ]
  195.     VtPushButton $mhm_stand_form.browse \
  196.         -leftSide $mhm_stand_text \
  197.         -topSide FORM \
  198.         -callback mhm_stand_host_browse \
  199.         -label [mhm_msg STR_BROWSE]
  200.     VtShow $mhm_stand_form
  201.     VtSetFocus $mhm_stand_text
  202.     VtMainLoop
  203. }
  204. proc \
  205. mhm_stand_host_jump { cbs } \
  206. {
  207.     global mhm_stand_form
  208.     set ok [VtGetValues $mhm_stand_form -ok]
  209.     VtSetFocus $ok
  210. }
  211. proc \
  212. mhm_stand_host_browse { cbs } \
  213. {
  214.     global mhm_stand_form
  215.     keylset parms parent $mhm_stand_form
  216.     keylset parms instance abc
  217.     keylset parms labeltext [mhm_msg MENU_HOST]
  218.     keylset parms buttontext [mhm_msg STR_BROWSE]
  219.     keylset parms userproc mhm_stand_host_browse_done
  220.     SaSelectHostDialog $parms $cbs
  221. }
  222. proc \
  223. mhm_stand_host_browse_done { cbs } \
  224. {
  225.     global mhm_stand_text
  226.     set value[SaSelectHostGetSelection abc]
  227.     VtSetValues $mhm_stand_text -value $value
  228. }
  229. proc \
  230. mhm_stand_host_ok { cbs } \
  231. {
  232.     global mhm_stand_text mhm_stand_outfile
  233.     set value [VtGetValues $mhm_stand_text -value]
  234.     if {[catch {open $mhm_stand_outfile w} fd] == 0} {
  235.         puts $fd $value
  236.         close $fd
  237.     }
  238.     VtClose
  239.     exit 0
  240. }
  241. proc \
  242. mhm_stand_open_quit { cbs } \
  243. {
  244.     VtClose
  245.     exit 0
  246. }
  247. proc \
  248. mhm_host_check { host } \
  249. {
  250.     global mhm_host_name mhm_local_host
  251.     if {"$host" == "$mhm_local_host"} {
  252.         return ok
  253.     }
  254.     set class [ list sco remoteCommand ]
  255.     set instance [GetInstanceList NULL $host]
  256.     set command [list ObjectAction $class $instance uname "-n"]
  257.     set result [SaMakeObjectCall $command]
  258.     set result [lindex $result 0]
  259.     if { [BmipResponseErrorIsPresent result] } {
  260.         return fail
  261.     }
  262.     set retStr [BmipResponseActionInfo result]
  263.     return ok
  264. }
  265. proc \
  266. mhm_remote_copyout { src dst } \
  267. {
  268.     global mhm_host_name mhm_local_host
  269.     if {"$mhm_host_name" == "$mhm_local_host"} {
  270.         return [mhm_local_copy $src $dst]
  271.     }
  272.     set host $mhm_host_name
  273.     set instance [GetInstanceList NULL $host]
  274.     set uid [id effective userid]
  275.     if {$uid == 0} {
  276.         if {[catch {system "/bin/rcp $src $host:$dst"} ret] == 0} {
  277.             return ok
  278.         } else {
  279.             return fail
  280.         }
  281.     } else {
  282.         # first copy to a temp file on remote machine
  283.         set tmp "/tmp/[file tail $src].[pid]"
  284.         if {[catch {system "/bin/rcp $src $host:$tmp"} ret] != 0} {
  285.             return fail
  286.         }
  287.         # then on remote machine, copy the temp file to destination,
  288.         # using tfadmin cpfile
  289.         set class [list sco remoteCommand]
  290.         set command [list ObjectAction $class $instance /sbin/tfadmin "cpfile $tmp $dst"]
  291.         set result [SaMakeObjectCall $command]
  292.         set result [lindex $result 0]
  293.         if {[BmipResponseErrorIsPresent result]} {
  294.             return fail
  295.         }
  296.         # now remove the temp file on remote machine
  297.         set class [list sco remoteCommand]
  298.         set command [list ObjectAction $class $instance /bin/rm "-f $tmp"]
  299.         set result [SaMakeObjectCall $command]
  300.         return ok
  301.     }
  302. }
  303. proc \
  304. mhm_remote_copyin { src dst } \
  305. {
  306.     global mhm_host_name mhm_local_host
  307.     if {"$mhm_host_name" == "$mhm_local_host"} {
  308.         return [mhm_local_copy $src $dst]
  309.     }
  310.     set host $mhm_host_name
  311.     set instance [GetInstanceList NULL $host]
  312.     set uid [id effective userid]
  313.     if {$uid == 0} {
  314.         if {[catch {system "/bin/rcp $host:$src $dst"} ret] == 0} {
  315.             return ok
  316.         } else {
  317.             return fail
  318.         }
  319.     } else {
  320.         # copy to a temp file on remote machine, using tfadmin
  321.         set tmp "/tmp/[file tail $src].[pid]"
  322.         set class [list sco remoteCommand]
  323.         set command [list ObjectAction $class $instance /sbin/tfadmin "cpfile $src $tmp"]
  324.         set result [SaMakeObjectCall $command]
  325.         set result [lindex $result 0]
  326.         if {[BmipResponseErrorIsPresent result]} {
  327.             return fail
  328.         }
  329.         # copy the remote temp file in to local destination using rcp
  330.         if {[catch {system "/bin/rcp $host:$tmp $dst"} ret] != 0} {
  331.             return fail
  332.         }
  333.         # remove the temp file on remote machine
  334.         set class [list sco remoteCommand]
  335.         set command [list ObjectAction $class $instance /bin/rm "-f $tmp"]
  336.         set result [SaMakeObjectCall $command]
  337.                 return ok
  338.     }
  339. }
  340. proc \
  341. mhm_local_copy { src dst } \
  342. {
  343.     set uid [id effective userid]
  344.     if {$uid == 0} {
  345.         catch {system "copy $src $dst > /dev/null 2>&1"} ret
  346.     } else {
  347.         catch {system "/sbin/tfadmin cpfile $src $dst > /dev/null 2>&1"} ret
  348.     }
  349.     if {"$ret" == 0} {
  350.         return ok
  351.     } else {
  352.         return fail
  353.     }
  354. }
  355. proc \
  356. GetInstanceList { names host } \
  357. {
  358.     set instanceList {}
  359.     if { $host == "localhost" } {
  360.         foreach name $names {
  361.             set instance [list $name]
  362.             lappend instanceList $instance
  363.         }
  364.     } else {
  365.         foreach name $names {
  366.             set instance [list [list systemId $host] [list $name]]
  367.             lappend instanceList $instance
  368.         }
  369.     }
  370.     return $instanceList
  371. }
  372. proc \
  373. mhm_host_local {} \
  374. {
  375.     set localhost [exec uname -n]
  376.     set fqdn [mhm_host_resolv $localhost]
  377.     return $fqdn
  378. }
  379. proc \
  380. mhm_host_resolv { hostname } \
  381. {
  382.     global RESOLVER
  383.     set ret [catch {exec $RESOLVER $hostname} hostlist]
  384.     if {"$ret" != "0"} {
  385.         return $hostname
  386.     }
  387.     set newhost [lindex $hostlist 0]
  388.     return $newhost
  389. }
  390. proc \
  391. mhm_list_users {} \
  392. {
  393.     global mhm_host_name mhm_local_host
  394.     if {"$mhm_host_name" == "$mhm_local_host"} {
  395.         set users [SaUsersGet]
  396.     } else {
  397.         set users [SaUsersGet $mhm_host_name]
  398.     }
  399.     set users [string tolower $users]
  400.     return $users
  401. }
  402. proc \
  403. mhm_remote_file_exists { path } \
  404. {
  405.     global mhm_host_name mhm_local_host
  406.     if {"$mhm_host_name" == "$mhm_local_host"} {
  407.         return [file exists $path]
  408.     }
  409.     set host $mhm_host_name
  410.     set class [list sco remoteCommand]
  411.     set instance [GetInstanceList NULL $host]
  412.     set command [list ObjectAction $class $instance file $path]
  413.     set result [SaMakeObjectCall $command]
  414.     set result [lindex $result 0]
  415.     if { [BmipResponseErrorIsPresent result] } {
  416.         return 0
  417.     }
  418.     return 1
  419. }
  420. proc \
  421. mhm_remote_mkdir { path } \
  422. {
  423.     global mhm_host_name mhm_local_host
  424.     set uid [id effective userid]
  425.     if {[mhm_remote_file_exists $path]} {
  426.         return 1
  427.     }
  428.     if {"$mhm_host_name" == "$mhm_local_host"} {
  429.         if {$uid == 0} {
  430.             catch {system "mkdir -p $path > /dev/null 2>&1"} ret
  431.             if {$ret == 0} {
  432.                 return 1
  433.             } else {
  434.                 return 0
  435.             }
  436.         } else {
  437.             # create the path in /tmp
  438.             set tmpdir "/tmp/tmpdir.[pid]"
  439.             set tmpvar $path
  440.             set basedir [ctoken tmpvar "/"]
  441.             catch {system "mkdir -p $tmpdir/$path > /dev/null 2>&1"} ret
  442.             if {$ret != 0} {
  443.                 return 0
  444.             }
  445.             # now use tfadmin cpfile to create the path
  446.             if {[catch {exec /sbin/tfadmin cpfile [list -r $tmpdir/$basedir] /} ret] != 0} {
  447.                 return 0
  448.             }
  449.             # remove the tmp dir
  450.             catch {system "rm -rf $tmpdir"} ret
  451.             return 1
  452.         }
  453.     }
  454.     # guess this is remote
  455.     set host $mhm_host_name
  456.     set instance [GetInstanceList NULL $host]
  457.     if {$uid == 0} {
  458.         set class [list sco remoteCommand]
  459.         set command [list ObjectAction $class $instance mkdir "-p $path"]
  460.         set result [SaMakeObjectCall $command]
  461.         set result [lindex $result 0]
  462.         if { [BmipResponseErrorIsPresent result] } {
  463.             return 0
  464.         }
  465.         return 1
  466.     } else {
  467.         # create the path in /tmp on remote host
  468.         set tmpdir "/tmp/tmpdir.[pid]"
  469.         set class [list sco remoteCommand]
  470.         set command [list ObjectAction $class $instance mkdir "-p $tmpdir/$path"]
  471.         set result [SaMakeObjectCall $command]
  472.         set result [lindex $result 0]
  473.         if { [BmipResponseErrorIsPresent result] } {
  474.             return 0
  475.         }
  476.         # now use tfadmin cpfile to create the path on remote host
  477.         set tmpvar $path
  478.         set basedir [ctoken tmpvar "/"]
  479.         set arglist [list cpfile [list -r $tmpdir/$basedir] /]
  480.         set command [list ObjectAction $class $instance /sbin/tfadmin $arglist]
  481.         set result [SaMakeObjectCall $command]
  482.         set result [lindex $result 0]
  483.         if { [BmipResponseErrorIsPresent result] } {
  484.             return 0
  485.         }
  486.         # remove the tmp dir on remote host
  487.         set command [list ObjectAction $class $instance /bin/rm "-rf $tmpdir"]
  488.         set result [SaMakeObjectCall $command]
  489.         set result [lindex $result 0]
  490.         return 1
  491.     }
  492. }
  493. proc \
  494. mhm_vdomains {} \
  495. {
  496.     global mhm_host_name mhm_local_host VDOMAINS mhm_vdomains_data
  497.     if {[info exists mhm_vdomains_data]} {
  498.         return $mhm_vdomains_data
  499.     }
  500.     if {"$mhm_host_name" == "$mhm_local_host"} {
  501.         set ret [catch {exec "$VDOMAINS"} output]
  502.         if {$ret != 0} {
  503.             set mhm_vdomains_data ""
  504.             return $mhm_vdomains_data
  505.         }
  506.         set newlist [split $output "\n"]
  507.         set mhm_vdomains_data $newlist
  508.         return $mhm_vdomains_data
  509.     }
  510.     set host $mhm_host_name
  511.     set class [list sco remoteCommand]
  512.     set instance [GetInstanceList NULL $host]
  513.     set command [list ObjectAction $class $instance $VDOMAINS ""]
  514.     set result [SaMakeObjectCall $command]
  515.     set result [lindex $result 0]
  516.     if { [BmipResponseErrorIsPresent result] } {
  517.         return ""
  518.     }
  519.     set output [BmipResponseActionInfo result]
  520.     set newlist [split $output "\n"]
  521.     set mhm_vdomains_data $newlist
  522.     return $mhm_vdomains_data
  523. }
  524. proc \
  525. mhm_remote_aliases {} \
  526. {
  527.     global mhm_host_name mhm_local_host
  528.     set list [mhm_vdomains]
  529.     set newlist ""
  530.     foreach item $list {
  531.         set value [lindex $item 0]
  532.         lappend newlist $value
  533.     }
  534.     return $newlist
  535. }
  536. proc \
  537. mhm_remote_alias_to_ip { alias } \
  538. {
  539.     set list [mhm_vdomains]
  540.     foreach item $list {
  541.         set value [lindex $item 0]
  542.         if {"$value" == "$alias"} {
  543.             set ip [lindex $item 1]
  544.             return $ip
  545.         }
  546.     }
  547.     return fail
  548. }
  549. proc \
  550. mh_open { file } \
  551. {
  552.     global mhi_file mhi_domain
  553.     if {[info exists mhi_domain]} {
  554.         unset mhi_domain
  555.     }    
  556.     set mhi_file $file
  557.     if {[catch {open $mhi_file r} fd] != 0} {
  558.         return fail
  559.     }
  560.     set errs 0
  561.     while {[gets $fd line] != -1} {
  562.         set line [string tolower $line]
  563.         set list ""
  564.         while {"$line" != ""} {
  565.             lappend list [ctoken line " \t"]
  566.         }
  567.         if {[llength $list] != 2} {
  568.             set errs 1
  569.             continue
  570.         }
  571.         set tmp [lindex $list 0]
  572.         set vuser [ctoken tmp "@"]
  573.         set domain [ctoken tmp "@"]
  574.         if {"$domain" == ""} {
  575.             set errs 1
  576.             continue
  577.         }
  578.         if {"$tmp" != ""} {
  579.             set errs 1
  580.             continue
  581.         }
  582.         set puser [lindex $list 1]
  583.         set list [list $vuser $puser]
  584.         lappend mhi_domain($domain) $list
  585.     }
  586.     close $fd
  587.     # now sort all user lists
  588.     foreach i [array names mhi_domain] {
  589.         set list $mhi_domain($i)
  590.         set list [lsort $list]
  591.         set mhi_domain($i) $list
  592.     }
  593.     if {$errs == 1} {
  594.         return parserr
  595.     }
  596.     return ok
  597. }
  598. proc \
  599. mh_write {} \
  600. {
  601.     global mhi_domain mhi_file
  602.     set names [array names mhi_domain]
  603.     set names [lsort $names]
  604.     if {[catch {open $mhi_file w} fd] != 0} {
  605.         return fail
  606.     }
  607.     foreach i $names {
  608.         set list $mhi_domain($i)
  609.         foreach j $list {
  610.             set vuser [lindex $j 0]
  611.             set puser [lindex $j 1]
  612.             puts $fd "$vuser@$i $puser"
  613.         }
  614.     }
  615.     close $fd
  616.     return ok
  617. }
  618. proc \
  619. mh_vd_names_get {} \
  620. {
  621.     global mhi_domain
  622.     set list [array names mhi_domain]
  623.     set list [lsort $list]
  624.     return $list
  625. }
  626. proc \
  627. mh_vd_users_get { vd } \
  628. {
  629.     global mhi_domain
  630.     if {[info exists mhi_domain($vd)]} {
  631.         set list $mhi_domain($vd)
  632.     } else {
  633.         set list ""
  634.     }
  635.     return $list
  636. }
  637. proc \
  638. mh_vd_users_set { vd list } \
  639. {
  640.     global mhi_domain
  641.     set list [lsort $list]
  642.     set mhi_domain($vd) $list
  643. }
  644. proc \
  645. mhm_cmd_line_main {} \
  646. {
  647.     global argv argv0 mhm_host_name DIRTY
  648.     if {"$argv" == ""} {
  649.         return
  650.     }
  651.     # check if remote host is there
  652.     if {"[mhm_host_check $mhm_host_name]" != "ok"} {
  653.         echo "multihome: Unable to connect to host $mhm_host_name"
  654.         exit 0
  655.     }
  656.     # check if authorized
  657.     if {"[mhm_authorized $mhm_host_name]" == "fail"} {
  658.         set mhm_short_name [lindex [split $mhm_host_name "."] 0]
  659.         echo "multihome: You are not authorized to run the Virtual Domain User Manager\n           on $mhm_short_name"
  660.         exit 0
  661.     }
  662.     # get our remote files from the appropriate host
  663.     mhm_cmd_file_get
  664.     set DIRTY 0
  665.     # now process rest of command line
  666.     while {"$argv" != ""} {
  667.         # do one command
  668.         mhm_cmd_one
  669.     }
  670.     # put our remote files
  671.     mhm_cmd_file_put
  672.     mhm_cmd_quit 0
  673. }
  674. proc \
  675. mhm_cmd_one {} \
  676. {
  677.     global CMD argv DIRTY
  678.     global ALIAS ALIASDB ALIASTMP ALIASTMPDB MHOMEPATH MAKEMAP
  679.     set cmd [mhm_cmd_popargv]
  680.     set CMD $cmd
  681.     switch -- "$cmd" {
  682.     list {
  683.         set type [mhm_cmd_popargv]
  684.         switch "$type" {
  685.         domains {
  686.             set list [mhm_union_domains]
  687.         }
  688.         users {
  689.             set domain [mhm_cmd_popargv]
  690.             mhm_cmd_valid_domain $domain
  691.             set list [mh_vd_users_get $domain]
  692.         }
  693.         default {
  694.             echo "multihome: Invalid list type: $type"
  695.             mhm_cmd_quit 1
  696.         }
  697.         }
  698.         foreach item $list {
  699.             echo $item
  700.         }
  701.     }
  702.     del {
  703.         set user [mhm_cmd_popargv]
  704.         set useri [string tolower $user]
  705.         set domain [mhm_cmd_popargv]
  706.         mhm_cmd_valid_domain $domain
  707.         set users [mh_vd_users_get $domain]
  708.         set index -1
  709.         set found -1
  710.         foreach i $users {
  711.             set index [expr $index + 1]
  712.             set t1 [lindex $i 0]
  713.             set t1 [string tolower $t1]
  714.             if {$t1 == $useri} {
  715.                 set found $index
  716.                 break
  717.             }
  718.         }
  719.         if {$found == -1} {
  720.             echo "multihome: User not found for delete: $user"
  721.             mhm_cmd_quit 1
  722.         }
  723.         set users [lreplace $users $index $index]
  724.         mh_vd_users_set $domain $users
  725.         set DIRTY 1
  726.     }
  727.     add {
  728.         set user [mhm_cmd_popargv]
  729.         set realuser [mhm_cmd_popargv]
  730.         set useri [string tolower $user]
  731.         set domain [mhm_cmd_popargv]
  732.         mhm_cmd_valid_domain $domain
  733.         set users [mh_vd_users_get $domain]
  734.         set index -1
  735.         set found -1
  736.         foreach i $users {
  737.             set index [expr $index + 1]
  738.             set t1 [lindex $i 0]
  739.             set t1 [string tolower $t1]
  740.             if {$t1 == $useri} {
  741.                 set found $index
  742.                 break
  743.             }
  744.         }
  745.         if {$found != -1} {
  746.             echo "multihome: User already exists in domain: $user@$domain"
  747.             mhm_cmd_quit 1
  748.         }
  749.         set newuser [list $user $realuser]
  750.         lappend users $newuser
  751.         mh_vd_users_set $domain $users
  752.         set DIRTY 1
  753.     }
  754.     aliasget {
  755.         set domain [mhm_cmd_popargv]
  756.         mhm_cmd_valid_domain $domain
  757.         set file [mhm_cmd_popargv]
  758.         set addr [mhm_remote_alias_to_ip $domain]
  759.         if {"$addr" == "fail"} {
  760.             echo "multihome: Unable to resolv name $domain"
  761.             mhm_cmd_quit 1
  762.         }
  763.         set rfile $MHOMEPATH/$addr/mail/$ALIAS
  764.         set ret [mhm_remote_copyin $rfile $file]
  765.         if {"$ret" != "ok"} {
  766.             echo "multihome: Copy error on $rfile"
  767.             mhm_cmd_quit 1
  768.         }
  769.     }
  770.     aliasput {
  771.         set domain [mhm_cmd_popargv]
  772.         mhm_cmd_valid_domain $domain
  773.         set file [mhm_cmd_popargv]
  774.         set addr [mhm_remote_alias_to_ip $domain]
  775.         if {"$addr" == "fail"} {
  776.             echo "multihome: Unable to resolv name $domain"
  777.             mhm_cmd_quit 1
  778.         }
  779.         set rfile $MHOMEPATH/$addr/mail/$ALIAS
  780.         system "rm -fr $ALIASTMP $ALIASTMPDB"
  781.         # first make db file
  782.         mhm_local_copy $file $ALIASTMP
  783.         catch {system "$MAKEMAP hash $file < $file > /dev/null 2>&1"} ret
  784.         if {$ret != 0} {
  785.             echo "multihome: Unable to make db file: $file"
  786.             mhm_cmd_quit 1
  787.         }
  788.         # make the directory if it doesn't exist
  789.         if {[mhm_remote_file_exists $MHOMEPATH/$addr/mail] == 0} {
  790.             mhm_remote_mkdir $MHOMEPATH/$addr/mail
  791.         }
  792.         # copy out alias file
  793.         set ret [mhm_remote_copyout $file $rfile]
  794.         if {"$ret" != "ok"} {
  795.             echo "multihome: Copy error on $domain:$rfile"
  796.             mhm_cmd_quit 1
  797.         }
  798.         # copy out alias db file
  799.         set ret [mhm_remote_copyout $file.db $rfile.db]
  800.         if {"$ret" != "ok"} {
  801.             echo "multihome: Copy error on $domain:$rfile.db"
  802.             mhm_cmd_quit 1
  803.         }
  804.     }
  805.     retire {
  806.         set user [mhm_cmd_popargv]
  807.         set ret [mhm_retire $user]
  808.         if {"$ret" != "ok"} {
  809.             echo "multihome: Retire user not found in any domain: $user"
  810.             mhm_cmd_quit 1
  811.         } else {
  812.             set DIRTY 1
  813.         }
  814.     }
  815.     domain {
  816.         mhm_rebuild_domain_map no
  817.     }
  818.     default {
  819.         echo "multihome: Unknown command: $cmd"
  820.         mhm_cmd_usage
  821.         mhm_cmd_quit 1
  822.     }
  823.     }
  824. }
  825. proc \
  826. mhm_cmd_usage {} \
  827. {
  828. echo "Usage:"
  829. echo "multihome"
  830. echo "    invoke GUI"
  831. echo "multihome \[-h host\] command \[arguments\]"
  832. echo "    Command line mode, following are the commands and their arguments."
  833. echo "    Multiple command may be strung together on the command line."
  834. echo "    If any of them fail no changes to the config files are made."
  835. echo
  836. echo "commands:"
  837. echo "list domains - output list of virtual domains."
  838. echo "list users domain - output list of users contained in that virtual domain."
  839. echo "    The virtual usernames are listed in the first column,"
  840. echo "    followed by their physical user name in the second."
  841. echo "del user domain - delete a virtual user from a domain name."
  842. echo "add user realuser domain - add a virtual user to a domain."
  843. echo "retire user - retire a system user from all virtual domains."
  844. echo "aliasget domain file - get the remote alias file for a domain."
  845. echo "aliasput domain file - put the remote alias file for a domain."
  846. echo "domain - rebuild domain database file from TCP configuration"
  847. echo "    if virtual domains have been added or deleted then this must be done."
  848. echo "    It is done automatically in GUI mode."
  849. }
  850. proc \
  851. mhm_cmd_popargv {} \
  852. {
  853.     global argv CMD
  854.     if {"$argv" == ""} {
  855.         echo "multihome: Not enough arguments for command: $CMD"
  856.         mhm_cmd_quit 1
  857.     }
  858.     return [lvarpop argv]
  859. }
  860. proc \
  861. mhm_cmd_file_get {} \
  862. {
  863.     global MHOME MHOMEDB MHOMETMP MHOMETMPDB MHOMETMPODB MHOMEPATH
  864.     global mhm_host_name MHOMELPATH
  865.     system "rm -fr $MHOMETMP $MHOMETMPDB $MHOMETMPODB"
  866.     set ret [mhm_remote_copyin $MHOME $MHOMETMP]
  867.     if {"$ret" != "ok"} {
  868.         # assume file was not there, create the directory, make file.
  869.         set ret [mhm_remote_mkdir $MHOMELPATH]
  870.         if {$ret != 1} {
  871.             echo "multihome: Unable to mkdir $MHOMELPATH"
  872.             mhm_cmd_quit 1
  873.         }
  874.         system "rm -fr $MHOMETMP; touch $MHOMETMP"
  875.     }
  876.     mhm_remote_copyin $MHOMEDB $MHOMETMPODB
  877.     # now open it
  878.     set ret [mh_open $MHOMETMP]
  879.     if {"$ret" == "fail"} {
  880.         echo "multihome: Unable to parse $mhm_host_name:$MHOME"
  881.         mhm_cmd_quit 1
  882.     }    
  883. }
  884. proc \
  885. mhm_cmd_file_put {} \
  886. {
  887.     global MHOME MHOMEDB MHOMETMP MHOMETMPDB MHOMETMPODB MAKEMAP
  888.     global mhm_host_name DIRTY
  889.     if {$DIRTY == 1} {
  890.         set ret [mh_write]
  891.         if {"$ret" != "ok"} {
  892.             echo "multihome: Unable to save: $MHOME"
  893.             mhm_cmd_quit 1
  894.         }
  895.         set ret [mhm_remote_copyout $MHOMETMP $MHOME]
  896.         if {"$ret" != "ok"} {
  897.             echo "multihome: Unable to save: $mhm_host_name:$MHOME"
  898.             mhm_cmd_quit 1
  899.         }
  900.         catch {system "$MAKEMAP hash $MHOMETMP < $MHOMETMP > /dev/null 2>&1"} ret
  901.         if {$ret != 0} {
  902.             echo "multihome: Unable to make map for $MHOME"
  903.             mhm_cmd_quit 1
  904.         }
  905.         set ret [mhm_remote_copyout $MHOMETMPDB $MHOMEDB]
  906.         if {"$ret" != "ok"} {
  907.             echo "multihome: Unable to save: $mhm_host_name:$MHOMEDB"
  908.             mhm_cmd_quit 1
  909.         }
  910.     }
  911. }
  912. proc \
  913. mhm_cmd_quit { code } \
  914. {
  915.     global MHOMETMP MHOMETMPDB MHOMETMPODB ALIASTMP ALIASTMPDB ALIASTMPODB
  916.     system "rm -fr $MHOMETMP $MHOMETMPDB $MHOMETMPODB $ALIASTMP $ALIASTMPDB $ALIASTMPODB"
  917.     exit $code
  918. }
  919. proc \
  920. mhm_cmd_valid_domain { domain } \
  921. {
  922.     set list [mhm_union_domains]
  923.     set list [string tolower $list]
  924.     set idomain [string tolower $domain]
  925.     set index [lsearch $list $idomain]
  926.     if {$index == -1} {
  927.         echo "multihome: Invalid domain: $domain"
  928.         mhm_cmd_quit 1
  929.     }
  930. }
  931. proc \
  932. mhm_edit_users { domain } \
  933. {
  934.     global outerMainForm mhm_user_form mhm_edit_users_domain mhm_user_list
  935.     set mhm_edit_users_domain $domain
  936.     # build the form.
  937.     set mhm_user_form [VtFormDialog $outerMainForm.users \
  938.         -title [mhm_msg1 USERS_FOR $domain] \
  939.         -okCallback mhi_edit_users_ok \
  940.         -cancelCallback mhi_edit_users_cancel \
  941.         -wmCloseCallback mhi_edit_users_cancel \
  942.     ]
  943.     set lbl1 [VtLabel $mhm_user_form.label1 -label [mhm_msg VIRTUAL]\
  944.         -columns 19 -labelLeft]
  945.     set lbl2 [VtLabel $mhm_user_form.label2 -label [mhm_msg SYSTEM] \
  946.         -topSide FORM -leftSide $lbl1]
  947.     set formatlist [list "STRING 20" "STRING 20"]
  948.     set list [VtDrawnList $mhm_user_form.list \
  949.         -autoSelect TRUE \
  950.         -selection MULTIPLE \
  951.         -leftSide FORM \
  952.         -formatList $formatlist \
  953.         -bottomSide FORM \
  954.     ]
  955.     set btn_add [VtPushButton $mhm_user_form.add -callback mhi_edit_add \
  956.         -leftSide $list -topSide $lbl2 -label [mhm_msg STR_ADD_USER]]
  957.     set btn_del [VtPushButton $mhm_user_form.del -callback mhi_edit_del \
  958.         -leftSide $list -topSide $btn_add -label [mhm_msg STR_DEL_USER]]
  959.     # load up user list.
  960.     set users [mh_vd_users_get $domain]
  961.     set position 0
  962.     foreach user $users {
  963.         set position [expr $position + 1]
  964.         VtDrawnListAddItem $list \
  965.             -position $position \
  966.             -fieldList $user
  967.     }
  968.     set mhm_user_list $list
  969.     VtShow $mhm_user_form
  970.     VtSetFocus $btn_add
  971. }
  972. proc \
  973. mhi_edit_users_ok { cbs } \
  974. {
  975.     global mhm_user_form mhm_user_list mhm_edit_users_domain DIRTY
  976.     VtLock
  977.     set domain $mhm_edit_users_domain
  978.     set users [VtDrawnListGetItem $mhm_user_list -all]
  979.     set oldusers [mh_vd_users_get $domain]
  980.     if {"$users" != "$oldusers"} {
  981.         mh_vd_users_set $domain $users
  982.         set DIRTY 1
  983.     }
  984.     VtUnLock
  985.     VtDestroy $mhm_user_form
  986. }
  987. proc \
  988. mhi_edit_users_cancel { cbs } \
  989. {
  990.     global mhm_user_form
  991.     VtDestroy $mhm_user_form
  992. }
  993. proc \
  994. mhi_edit_del { cbs } \
  995. {
  996.     global mhm_user_list
  997.     VtLock
  998.     set poslist [VtDrawnListGetSelectedItem $mhm_user_list -byPositionList]
  999.     if {"$poslist" != "0"} {
  1000.         VtDrawnListDeleteItem $mhm_user_list -positionList $poslist
  1001.     }
  1002.     VtUnLock
  1003. }
  1004. proc \
  1005. mhi_edit_add { cbs } \
  1006. {
  1007.     global mhm_user_form
  1008.     global mhm_edit_add_form mhm_edit_add_system mhm_edit_add_virtual
  1009.     VtLock
  1010.     set form [VtFormDialog $mhm_user_form.addForm \
  1011.         -title [mhm_msg USER_ADD] \
  1012.         -okCallback mhi_edit_add_ok \
  1013.         -cancelCallback mhi_edit_add_cancel \
  1014.         -wmCloseCallback mhi_edit_add_cancel]
  1015.     set lbl1 [VtLabel $form.label1 -label [mhm_msg SYSTEM]]
  1016.     set combo [VtComboBox $form.combo1 \
  1017.         -leftSide FORM -rightSide FORM -columns 20 \
  1018.         -itemList [mhm_list_users] \
  1019.         -valueChangedCallback mhi_edit_add_combo \
  1020.         ]
  1021.     set lbl2 [VtLabel $form.label2 -label [mhm_msg VIRTUAL]]
  1022.     set value [VtGetValues $combo -value]
  1023.     set text [VtText $form.text -leftSide FORM -rightSide FORM -columns 20 \
  1024.         -value $value]
  1025.     VtSetValues $combo -callback "mhi_jump $text"
  1026.     set ok [VtGetValues $form -ok]
  1027.     VtSetValues $text -callback "mhi_jump $ok"
  1028.     set mhm_edit_add_form $form
  1029.     set mhm_edit_add_system $combo
  1030.     set mhm_edit_add_virtual $text
  1031.     VtShow $form
  1032.     VtSetFocus $combo
  1033.     VtUnLock
  1034. }
  1035. proc \
  1036. mhi_jump { widget cbs } \
  1037. {
  1038.     VtSetFocus $widget
  1039. }
  1040. proc \
  1041. mhi_edit_add_cancel { cbs } \
  1042. {
  1043.     global mhm_edit_add_form
  1044.     VtDestroy $mhm_edit_add_form
  1045. }
  1046. proc \
  1047. mhi_edit_add_combo { cbs } \
  1048. {
  1049.     global mhm_edit_add_system mhm_edit_add_virtual
  1050.     set value [VtGetValues $mhm_edit_add_system -value]
  1051.     VtSetValues $mhm_edit_add_virtual -value $value
  1052. }
  1053. proc \
  1054. mhi_edit_add_ok { cbs } \
  1055. {
  1056.     global mhm_edit_add_form
  1057.     global mhm_edit_add_system mhm_edit_add_virtual
  1058.     global mhm_user_list
  1059.     VtLock
  1060.     set system [VtGetValues $mhm_edit_add_system -value]
  1061.     set virtual [VtGetValues $mhm_edit_add_virtual -value]
  1062.     set system [string trim $system]
  1063.     set virtual [string trim $virtual]
  1064.     set system [string tolower $system]
  1065.     set virtual [string tolower $virtual]
  1066.     set users [mhm_list_users]
  1067.     if {"$system" == ""} {
  1068.         VtUnLock
  1069.         mhm_error BAD_SUSER
  1070.         return
  1071.     }
  1072.     # system user must exist
  1073.     if {[lsearch $users $system] == -1} {
  1074.         VtUnLock
  1075.         mhm_error BAD_SUSER
  1076.         return
  1077.     }
  1078.     if {"$virtual" == ""} {
  1079.         VtUnLock
  1080.         mhm_error BAD_VUSER
  1081.         return
  1082.     }
  1083.     # virtual user must be unique
  1084.     set users [VtDrawnListGetItem $mhm_user_list -all]
  1085.     if {[string first "\{$virtual " $users] >= 0} {
  1086.         VtUnLock
  1087.         mhm_error DUP_VUSER
  1088.         return
  1089.     }
  1090.     # find place in mhm_user_list, insert it, select it, and scroll to it.
  1091.     set index 0
  1092.     set newuser [list $virtual $system]
  1093.     foreach i $users {
  1094.         set index [expr $index + 1]
  1095.         if {"$i" > "$newuser"} {
  1096.             break
  1097.         }
  1098.     }
  1099.     VtDrawnListAddItem $mhm_user_list \
  1100.         -position $index \
  1101.         -fieldList $newuser
  1102.     VtDrawnListSelectItem $mhm_user_list -position $index
  1103.     VtUnLock
  1104.     VtDestroy $mhm_edit_add_form
  1105. }
  1106. proc \
  1107. mhm_edit_aliases { domain } \
  1108. {
  1109.     global MHOMEPATH ALIAS ALIAS_EDITOR
  1110.     VtLock
  1111.     set addr [mhm_remote_alias_to_ip $domain]
  1112.     if {"$addr" == "fail"} {
  1113.         VtUnLock
  1114.         mhm_error1 RESOLV $domain
  1115.         return
  1116.     }
  1117.     set fdir "$MHOMEPATH/$addr/mail"
  1118.     if {[mhm_remote_file_exists $fdir] == 0} {
  1119.         mhm_remote_mkdir $fdir
  1120.     }
  1121.     set fname "$MHOMEPATH/$addr/mail/$ALIAS"
  1122.     mhm_stand_call_editor $ALIAS_EDITOR $fname
  1123.     VtUnLock
  1124. }
  1125. proc \
  1126. mhm_stand_call_editor { editor file } \
  1127. {
  1128.     global PID mhm_host_name mhm_local_host
  1129.     set class hash
  1130.     set fname $file
  1131.     # tmp file names
  1132.     set fnamedb "$fname.db"
  1133.     set base [exec basename $editor]
  1134.     set tmp1 "/tmp/$base.$PID"
  1135.     set tmp1db "/tmp/$base.$PID.db"
  1136.     set tmp2 "/tmp/$base.1.$PID"
  1137.     set tmp2db "/tmp/$base.1.$PID.db"
  1138.     # copy in files
  1139.     system "rm -fr $tmp1 $tmp1db $tmp2 $tmp2db"
  1140.     set ret [mhm_remote_copyin $fname $tmp1]
  1141.     set ret [mhm_remote_copyin $fname $tmp2]
  1142.     set ret [mhm_remote_copyin $fnamedb $tmp1db]
  1143.     set host ""
  1144.     if {"$mhm_host_name" != "$mhm_local_host"} {
  1145.         set host "-h $mhm_host_name"
  1146.     }
  1147.     if {"$class" != ""} {
  1148.         set cmd "$editor $host -f $class:$tmp2"
  1149.     } else {
  1150.         set cmd "$editor $host -f $tmp2"
  1151.     }
  1152.     VtControl -suspend
  1153.     catch {system "$cmd"} ret
  1154.     VtControl -resume
  1155.     if {$ret != 0} {
  1156.         VtUnLock
  1157.         mhm_error1 EXEC $editor
  1158.         VtLock
  1159.         system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  1160.         return
  1161.     }
  1162.     # copy back main file
  1163.     set ret ok
  1164.     if {[file exists $tmp2] == 1} {
  1165.         if {[file exists $tmp1] == 1} {
  1166.             catch {system "cmp $tmp2 $tmp1 > /dev/null 2>&1"} tmp
  1167.             # files are different
  1168.             if {$tmp == 1} {
  1169.                 set ret [mhm_remote_copyout $tmp2 $fname]
  1170.             }
  1171.         } else {
  1172.             set ret [mhm_remote_copyout $tmp2 $fname]
  1173.         }
  1174.     }
  1175.     if {"$ret" != "ok"} {
  1176.         VtUnLock
  1177.         mhm_error1 COPY_BACK $fname
  1178.         VtLock
  1179.         system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  1180.         return
  1181.     }
  1182.     # copy back db file
  1183.     set ret ok
  1184.     if {[file exists $tmp2db] == 1} {
  1185.         if {[file exists $tmp1db] == 1} {
  1186.             catch {system "cmp $tmp2db $tmp1db > /dev/null 2>&1"} tmp
  1187.             # files are different
  1188.             if {$tmp == 1} {
  1189.                 set ret [mhm_remote_copyout $tmp2db $fnamedb]
  1190.             }
  1191.         } else {
  1192.             set ret [mhm_remote_copyout $tmp2db $fnamedb]
  1193.         }
  1194.     }
  1195.     if {"$ret" != "ok"} {
  1196.         VtUnLock
  1197.         mhm_error1 COPY_BACK $fnamedb
  1198.         VtLock
  1199.         system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  1200.         return
  1201.     }
  1202.     system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  1203. }
  1204. proc \
  1205. mhm_retire_user {} \
  1206. {
  1207.     global outerMainForm mhm_retire_form mhm_retire_combo
  1208.     # build the form.
  1209.     set form [VtFormDialog $outerMainForm.retire \
  1210.         -title [mhm_msg MENU_RETIRE] \
  1211.         -okCallback mhi_retire_ok \
  1212.         -cancelCallback mhi_retire_cancel \
  1213.         -wmCloseCallback mhi_retire_cancel \
  1214.     ]
  1215.     set ok [VtGetValues $form -ok]
  1216.     set combo [VtComboBox $form.combo1 \
  1217.         -leftSide FORM -rightSide FORM -columns 20 \
  1218.         -itemList [mhm_list_users] \
  1219.         -callback "mhi_jump $ok" \
  1220.     ]
  1221.     set mhm_retire_form $form
  1222.     set mhm_retire_combo $combo
  1223.     VtShow $form
  1224.     VtSetFocus $combo
  1225. }
  1226. proc \
  1227. mhi_retire_cancel { cbs } \
  1228. {
  1229.     global mhm_retire_form
  1230.     VtDestroy $mhm_retire_form
  1231. }
  1232. proc \
  1233. mhi_retire_ok { cbs } \
  1234. {
  1235.     global mhm_retire_form mhm_retire_combo DIRTY
  1236.     VtLock
  1237.     # first verify user is valid
  1238.     set user [VtGetValues $mhm_retire_combo -value]
  1239.     set user [string tolower $user]
  1240.     set users [mhm_list_users]
  1241.     if {[lsearch $users $user] == -1} {
  1242.         VtUnLock
  1243.         mhm_error BAD_SUSER
  1244.         return
  1245.     }
  1246.     set ret [mhm_retire $user]
  1247.     if {"$ret" == "ok"} {
  1248.         set DIRTY 1
  1249.     }
  1250.     VtUnLock
  1251.     VtDestroy $mhm_retire_form
  1252. }
  1253. proc \
  1254. mhm_setcat { catname } \
  1255. {
  1256.     global mhm_catname
  1257.     set mhm_catname $catname
  1258. }
  1259. proc \
  1260. mhm_msg { msg } \
  1261. {
  1262.     global mhm_catname
  1263.     return [IntlLocalizeMsg ${mhm_catname}_MSG_$msg]
  1264. }
  1265. proc \
  1266. mhm_msg1 { msg arg } \
  1267. {
  1268.     global mhm_catname
  1269.     return [IntlLocalizeMsg ${mhm_catname}_MSG_$msg $arg]
  1270. }
  1271. proc \
  1272. mhm_err { msg } \
  1273. {
  1274.     global mhm_catname
  1275.     return [IntlLocalizeMsg ${mhm_catname}_ERR_$msg]
  1276. }
  1277. proc \
  1278. mhm_err1 { msg arg } \
  1279. {
  1280.     global mhm_catname
  1281.     return [IntlLocalizeMsg ${mhm_catname}_ERR_$msg $arg]
  1282. }
  1283. proc \
  1284. mhm_query_eyn { msg arg } \
  1285. {
  1286.     global app
  1287.     set ret [VtErrorDialog $app.err -block \
  1288.         -message [mhm_err1 $msg $arg] \
  1289.         -ok -okLabel [mhm_msg STR_YES] \
  1290.         -apply -applyLabel [mhm_msg STR_NO]]
  1291.     switch "$ret" {
  1292.     "OK"     {
  1293.         return yes
  1294.     }
  1295.     "APPLY"     {
  1296.         return no
  1297.     }
  1298.     }
  1299.     error "mhm_query_eyn: Unknown result code"
  1300. }
  1301. proc \
  1302. mhm_query_eok { msg arg } \
  1303. {
  1304.     global app
  1305.     set ret [VtErrorDialog $app.err -block \
  1306.         -message [mhm_err1 $msg $arg] \
  1307.         -ok -okLabel [mhm_msg STR_OK]]
  1308.     if {"$ret" == "OK"} {
  1309.         return yes
  1310.     }
  1311.     error "mhm_query_eok: Unknown result code"
  1312. }
  1313. proc \
  1314. mhm_query_qync { msg arg } \
  1315. {
  1316.     global app
  1317.     set ret [VtQuestionDialog $app.err -block \
  1318.         -message [mhm_msg1 $msg $arg] \
  1319.         -ok -okLabel [mhm_msg STR_YES] \
  1320.         -apply -applyLabel [mhm_msg STR_NO] \
  1321.         -cancel -cancelLabel [mhm_msg STR_CANCEL]]
  1322.     switch "$ret" {
  1323.      "OK"     {
  1324.          return yes
  1325.      }
  1326.     "APPLY"     {
  1327.         return no
  1328.     }
  1329.     "CANCEL" {
  1330.         return cancel
  1331.     }
  1332.     }
  1333.     error "mhm_query_qync: Unknown result code"
  1334. }
  1335. proc \
  1336. mhm_query_qyn { msg arg } \
  1337. {
  1338.     global app
  1339.     set ret [VtQuestionDialog $app.err -block \
  1340.         -message [mhm_msg1 $msg $arg] \
  1341.         -ok -okLabel [mhm_msg STR_YES] \
  1342.         -apply -applyLabel [mhm_msg STR_NO]]
  1343.     switch "$ret" {
  1344.      "OK"     {
  1345.          return yes
  1346.      }
  1347.     "APPLY"     {
  1348.         return no
  1349.     }
  1350.     }
  1351.     error "mhm_query_qyn: Unknown result code"
  1352. }
  1353. proc \
  1354. mhm_error { msg } \
  1355. {
  1356.     global app
  1357.     VtErrorDialog $app.err -block -ok -message [mhm_err $msg]
  1358. }
  1359. proc \
  1360. mhm_error1 { msg arg } \
  1361. {
  1362.     global app
  1363.     VtErrorDialog $app.err -block -ok -message [mhm_err1 $msg $arg]
  1364. }
  1365. proc \
  1366. mhm_union_domains {} \
  1367. {
  1368.     set list1 [mhm_remote_aliases]
  1369.     set list2 [mh_vd_names_get]
  1370.     foreach i $list2 {
  1371.         set found 0
  1372.         foreach j $list1 {
  1373.             if {$i == $j} {
  1374.                 set found 1
  1375.                 break
  1376.             }
  1377.         }
  1378.         if {$found == 0} {
  1379.             lappend list1 $i
  1380.         }
  1381.     }
  1382.     set list1 [lsort $list1]
  1383.     return $list1
  1384. }
  1385. proc \
  1386. mhm_retire { user } \
  1387. {
  1388.     set useri [string tolower $user]
  1389.     set domains [mhm_union_domains]
  1390.     set found fail
  1391.     foreach domain $domains {
  1392.         set users [mh_vd_users_get $domain]
  1393.         set newusers ""
  1394.         foreach item $users {
  1395.             set puser [lindex $item 1]
  1396.             set puser [string tolower $puser]
  1397.             if {"$puser" != "$useri"} {
  1398.                 lappend newusers $item
  1399.             }
  1400.         }
  1401.         if {"$users" != "$newusers"} {
  1402.             mh_vd_users_set $domain $newusers
  1403.             set found ok
  1404.         }
  1405.     }
  1406.     return $found
  1407. }
  1408. proc \
  1409. mhm_rebuild_domain_map { prompt } \
  1410. {
  1411.     global PID MAKEMAP MDOMAIN MDOMAINDB MDOMAINPATH
  1412.     # yes, check if domain map is out of date.
  1413.     set tmp1 "/tmp/domain.$PID"
  1414.     set tmp1db "/tmp/domain.$PID.db"
  1415.     set tmp2db "/tmp/domain.1.$PID.db"
  1416.     system "rm -f $tmp1 $tmp1db $tmp2db"
  1417.     set ret [mhm_remote_copyin $MDOMAINDB $tmp2db]
  1418.     # must write out our domains to tmp1
  1419.     if {[catch {open $tmp1 w} fd] != 0} {
  1420.         return fail
  1421.     }
  1422.     # only use the ones that really exist
  1423.     set domains [mhm_remote_aliases]
  1424.     foreach domain $domains {
  1425.         set ip [mhm_remote_alias_to_ip $domain]
  1426.         if {"$ip" == "fail"} {
  1427.             set ip "N/A"
  1428.         }
  1429.         puts $fd "$domain $ip"
  1430.     }
  1431.     close $fd
  1432.     # now make a map
  1433.     if {[file exists $tmp1] == 1} {
  1434.         set copy no
  1435.         catch {system "$MAKEMAP hash $tmp1 < $tmp1 >/dev/null 2>&1"} ret
  1436.         if {$ret != 0} {
  1437.             if {"$prompt" == "yes"} {
  1438.                 VtUnLock
  1439.                 mhm_error1 NO_MAP $MDOMAINDB
  1440.                 VtLock
  1441.             }
  1442.             system "rm -f $tmp1 $tmp1db $tmp2db"
  1443.             return fail
  1444.         }
  1445.         # no previous map, always copy back
  1446.         if {[file exists $tmp2db] == 0} {
  1447.             set copy yes
  1448.         } else {
  1449.             catch {system "cmp $tmp1db $tmp2db > /dev/null 2>&1"} tmp
  1450.             # files are different
  1451.             if {$tmp == 1} {
  1452.                 set copy yes
  1453.             }
  1454.         }
  1455.         if {"$prompt" == "no"} {
  1456.             set copy yes
  1457.         }
  1458.         if {"$copy" == "no"} {
  1459.             system "rm -f $tmp1 $tmp1db $tmp2db"
  1460.             return ok
  1461.         }
  1462.         # prompt if copy is ok.
  1463.         set ret yes
  1464.         if {"$prompt" == "yes"} {
  1465.             VtUnLock
  1466.             set ret [mhm_query_qyn DOMAIN_UPDATE $MDOMAINDB]
  1467.             VtLock
  1468.         }
  1469.         if {"$ret" == "yes"} {
  1470.             # first mkdir
  1471.             mhm_remote_mkdir $MDOMAINPATH
  1472.             set ret [mhm_remote_copyout $tmp1 $MDOMAIN]
  1473.             if {"$ret" == "fail"} {
  1474.                 if {"$prompt" == "yes"} {
  1475.                     VtUnLock
  1476.                     mhm_error1 COPY_BACK $MDOMAIN
  1477.                     VtLock
  1478.                 }
  1479.                 system "rm -f $tmp1 $tmp1db $tmp2db"
  1480.                 return fail
  1481.             }
  1482.             set ret [mhm_remote_copyout $tmp1db $MDOMAINDB]
  1483.             if {"$ret" == "fail"} {
  1484.                 if {"$prompt" == "yes"} {
  1485.                     VtUnLock
  1486.                     mhm_error1 COPY_BACK $MDOMAINDB
  1487.                     VtLock
  1488.                 }
  1489.                 system "rm -f $tmp1 $tmp1db $tmp2db"
  1490.                 return fail
  1491.             }
  1492.         }
  1493.         system "rm -f $tmp1 $tmp1db $tmp2db"
  1494.     }
  1495.     return ok
  1496. }
  1497. set versionNumber [SaGetSSOVersion]
  1498. set RESPATH /etc/mail/admin/px
  1499. set PID [pid]
  1500. set ME "/etc/mail/admin/multihome"
  1501. set MHOMEPATH /var/internet/ip
  1502. set MHOMELPATH /var/internet/ip/127.0.0.1
  1503. set MHOME /var/internet/ip/127.0.0.1/virtusers
  1504. set MHOMEDB /var/internet/ip/127.0.0.1/virtusers.db
  1505. set MHOMETMP /tmp/virtusers.$PID
  1506. set MHOMETMPDB /tmp/virtusers.$PID.db
  1507. set MHOMETMPODB /tmp/virtusers.$PID.odb
  1508. set MDOMAINPATH /var/internet/ip/127.0.0.1/mail
  1509. set MDOMAIN /var/internet/ip/127.0.0.1/mail/virtdomains
  1510. set MDOMAINDB /var/internet/ip/127.0.0.1/mail/virtdomains.db
  1511. set ALIAS mail.aliases
  1512. set ALIASDB mail.aliases.db
  1513. set ALIASTMP /tmp/alias.$PID
  1514. set ALIASTMPDB /tmp/alias.$PID.db
  1515. set ALIASTMPODB /tmp/alias.$PID.db
  1516. set ALIAS_EDITOR /etc/mail/admin/aliases
  1517. set MAKEMAP /etc/mail/makemap
  1518. set RESOLVER /usr/sbin/host
  1519. set VDOMAINS /etc/mail/vdomains
  1520. set mhm_host_name [mhm_host_local]
  1521. set mhm_local_host $mhm_host_name
  1522. proc \
  1523. mhm_display_mainlist {} \
  1524. {
  1525.     global main_list
  1526.     set domains [mhm_union_domains]
  1527.     set realdomains [mhm_remote_aliases]
  1528.     set length [llength $domains]
  1529.     VtDrawnListDeleteItem $main_list -all
  1530.     loop i 0 $length {
  1531.         set domain [lindex $domains $i]
  1532.         set icon 0
  1533.         if {[lsearch $realdomains $domain] == -1} {
  1534.             set icon 1
  1535.         }
  1536.         set fieldlist [list $icon $domain]
  1537.         set formatlist [list "ICON 1" "STRING 75"]
  1538.         set position [expr $i + 1]
  1539.         VtDrawnListAddItem $main_list \
  1540.             -position $position \
  1541.             -fieldList $fieldlist \
  1542.             -formatList $formatlist
  1543.     }
  1544.     VtDrawnListSelectItem $main_list -position 1
  1545. }
  1546. proc \
  1547. mhm_build_widgets { parent } \
  1548. {
  1549.     global RESPATH main_list status_line
  1550.     global btn_user btn_alias
  1551.     global menu_user menu_alias
  1552.     global mhm_host_name mhm_host_label
  1553.     # menubar
  1554.     set menuBar [VtMenuBar $parent.menubar \
  1555.         -helpMenuItemList [SaHelpGetOptionsList]]
  1556.     set hostMenu [VtPulldown $menuBar.hostMenu -label [mhm_msg MENU_HOST] \
  1557.         -mnemonic [mhm_msg MENU_HOST_MN]]
  1558.     VtPushButton $hostMenu.open -label [mhm_msg MENU_OPEN] \
  1559.         -mnemonic [mhm_msg MENU_OPEN_MN] \
  1560.         -callback mhm_open_host_cb \
  1561.         -shortHelpString [mhm_msg SHORT_OPEN] \
  1562.         -shortHelpCallback mhm_short_help
  1563.     VtPushButton $hostMenu.exit -label [mhm_msg MENU_EXIT] \
  1564.         -mnemonic [mhm_msg MENU_EXIT_MN] \
  1565.         -callback "quit_cb 1" \
  1566.         -shortHelpString [mhm_msg SHORT_EXIT] \
  1567.         -shortHelpCallback mhm_short_help
  1568.     set editMenu [VtPulldown $menuBar.editMenu -label [mhm_msg MENU_EDIT] \
  1569.         -mnemonic [mhm_msg MENU_EDIT_MN]]
  1570.     set menu_user [VtPushButton $editMenu.User -label [mhm_msg MENU_USER] \
  1571.         -mnemonic [mhm_msg MENU_USER_MN] \
  1572.         -callback mhm_user_cb \
  1573.         -shortHelpString [mhm_msg SHORT_USER] \
  1574.         -shortHelpCallback mhm_short_help]
  1575.     set menu_alias [VtPushButton $editMenu.Alias -label [mhm_msg MENU_ALIAS] \
  1576.         -mnemonic [mhm_msg MENU_ALIAS_MN] \
  1577.         -callback mhm_alias_cb \
  1578.         -shortHelpString [mhm_msg SHORT_ALIAS] \
  1579.         -shortHelpCallback mhm_short_help]
  1580.     set menu_retire [VtPushButton $editMenu.Retire -label [mhm_msg MENU_RETIRE] \
  1581.         -mnemonic [mhm_msg MENU_RETIRE_MN] \
  1582.         -callback mhm_retire_cb \
  1583.         -shortHelpString [mhm_msg SHORT_RETIRE] \
  1584.         -shortHelpCallback mhm_short_help]
  1585.     # toolbar widget
  1586.     if {[VtInfo -charm] == 0} {
  1587.         set frameBar [VtFrame $parent.framebar \
  1588.             -topSide $menuBar \
  1589.             -topOffset 1 \
  1590.             -leftSide FORM \
  1591.             -leftOffset 2 \
  1592.             -rightSide FORM \
  1593.             -rightOffset 2 \
  1594.             -marginWidth 0 \
  1595.             -marginHeight 0 \
  1596.             -horizontalSpacing 0 \
  1597.             -verticalSpacing 0 \
  1598.             -shadowType IN \
  1599.         ]
  1600.         set toolBar [VtForm $frameBar.toolbar \
  1601.             -leftSide FORM \
  1602.             -rightSide FORM \
  1603.             -borderWidth 0 \
  1604.             -marginHeight 0 \
  1605.             -marginWidth 0 \
  1606.             -horizontalSpacing 0 \
  1607.             -verticalSpacing 0 \
  1608.         ]
  1609.         set btn_user [VtPushButton $toolBar.user \
  1610.             -label [mhm_msg MENU_USER] \
  1611.             -leftSide FORM \
  1612.             -topSide FORM \
  1613.             -bottomSide FORM \
  1614.             -callback mhm_user_cb \
  1615.             -shortHelpString [mhm_msg SHORT_USER] \
  1616.             -shortHelpCallback mhm_short_help \
  1617.         ]
  1618.         set btn_alias [VtPushButton $toolBar.alias \
  1619.             -label [mhm_msg MENU_ALIAS] \
  1620.             -leftSide $btn_user \
  1621.             -topSide FORM \
  1622.             -bottomSide FORM \
  1623.             -callback mhm_alias_cb \
  1624.             -shortHelpString [mhm_msg SHORT_ALIAS] \
  1625.             -shortHelpCallback mhm_short_help \
  1626.         ]
  1627.     }
  1628.     # Top status line
  1629.     set mhm_host_label [VtLabel $parent.toplab \
  1630.         -leftSide FORM -rightSide FORM \
  1631.         -label [mhm_msg1 STATUS $mhm_host_name] \
  1632.     ]
  1633.     # list widget
  1634.     set main_list [VtDrawnList $parent.list -columns 78 -rows 8 \
  1635.         -autoSelect TRUE -selection BROWSE \
  1636.         -leftSide FORM -rightSide FORM \
  1637.         -horizontalScrollBar 1 \
  1638.         -defaultCallback mhm_user_cb \
  1639.         -iconList [list \
  1640.             $RESPATH/domain.px \
  1641.             $RESPATH/baddomain.px \
  1642.         ]]
  1643.     # status line
  1644.     set status_line [SaStatusBar $parent.status 1]
  1645.     SaStatusBarSet $status_line [mhm_msg LOADING]
  1646.     VtSetValues $main_list -bottomSide $status_line
  1647. }
  1648. proc \
  1649. mhm_open_host_cb { cbs } \
  1650. {
  1651.     VtLock
  1652.     mhm_open_host
  1653.     VtUnLock
  1654. }
  1655. proc \
  1656. mhm_user_cb { cbs } \
  1657. {
  1658.     global main_list
  1659.     VtLock
  1660.         set index [VtDrawnListGetSelectedItem $main_list]
  1661.         set index [expr $index - 1]
  1662.         set domains [mhm_union_domains]
  1663.         set domain [lindex $domains $index]
  1664.     mhm_edit_users $domain
  1665.     VtUnLock
  1666. }
  1667. proc \
  1668. mhm_alias_cb { cbs } \
  1669. {
  1670.     global main_list
  1671.     VtLock
  1672.         set index [VtDrawnListGetSelectedItem $main_list]
  1673.         set index [expr $index - 1]
  1674.         set domains [mhm_union_domains]
  1675.         set domain [lindex $domains $index]
  1676.     mhm_edit_aliases $domain
  1677.     VtUnLock
  1678. }
  1679. proc \
  1680. mhm_retire_cb { cbs } \
  1681. {
  1682.     VtLock
  1683.     mhm_retire_user
  1684.     VtUnLock
  1685. }
  1686. proc \
  1687. mhm_short_help { cbs } \
  1688. {
  1689.     global status_line
  1690.     set helpstring [keylget cbs helpString]
  1691.     SaStatusBarSet $status_line $helpstring
  1692. }
  1693. proc \
  1694. mhm_all_get {} \
  1695. {
  1696.     global DIRTY MHOME MHOMEDB MHOMETMP MHOMETMPDB MHOMETMPODB MDOMAINPATH
  1697.     system "rm -fr $MHOMETMP $MHOMETMPDB $MHOMETMPODB"
  1698.     set ret [mhm_remote_copyin $MHOME $MHOMETMP]
  1699.     if {$ret != "ok"} {
  1700.         VtUnLock
  1701.         set ret [mhm_query_eyn COPY_OUT $MHOME]
  1702.         VtLock
  1703.         if {$ret == "no"} {
  1704.             return no
  1705.         }
  1706.         # contine, ignoring errors.
  1707.         system "rm -fr $MHOMETMP; touch $MHOMETMP"
  1708.         # we do make the directory on the other end just in case.
  1709.         mhm_remote_mkdir $MDOMAINPATH
  1710.         set DIRTY 1
  1711.     }
  1712.     # if db file is missing it is not an error.
  1713.     mhm_remote_copyin $MHOMEDB $MHOMETMPODB
  1714.     # ready to attempt open.
  1715.     set ret start
  1716.     while {"$ret" != "ok"} {
  1717.         set ret [mh_open $MHOMETMP]
  1718.         switch $ret {
  1719.         "ok"    {
  1720.         }
  1721.         "fail"    {
  1722.             VtUnLock
  1723.             mhm_error1 OPEN_FAIL $MHOMETMP
  1724.             VtLock
  1725.             return fail
  1726.         }
  1727.         "parserr" {
  1728.             VtUnLock
  1729.             set ret [mhm_query_eyn PARSE $MHOME]
  1730.             VtLock
  1731.             if {$ret == "no"} {
  1732.                 return no
  1733.             }
  1734.             # continue, strip bad lines in file.
  1735.             set ret ok
  1736.             set DIRTY 1
  1737.         }
  1738.         }
  1739.     }
  1740.     set domains [mhm_union_domains]
  1741.     if {[llength $domains] == 0} {
  1742.         VtUnLock
  1743.         mhm_error NO_VDOMAINS
  1744.         VtLock
  1745.         return fail
  1746.     }
  1747.     return ok
  1748. }
  1749. proc \
  1750. mhm_all_put {} \
  1751. {
  1752.     global app DIRTY
  1753.     global MHOME MHOMEDB MHOMETMP MHOMETMPDB MHOMETMPODB MAKEMAP
  1754.     if {$DIRTY == 1} {
  1755.         VtUnLock
  1756.         set ret [mhm_query_qync DIRTY notused]
  1757.         VtLock
  1758.         if {"$ret" == "cancel"} {
  1759.             return cancel
  1760.         }
  1761.         if {"$ret" == "yes"} {
  1762.             set ret [mh_write]
  1763.             if {"$ret" != "ok"} {
  1764.                 VtUnLock
  1765.                 mhm_query_eok WRITE $MHOMETMP
  1766.                 VtLock
  1767.                 return fail
  1768.             }
  1769.             set ret [mhm_remote_copyout $MHOMETMP $MHOME]
  1770.             if {"$ret" != "ok"} {
  1771.                 VtUnLock
  1772.                 mhm_query_eok COPY_BACK $MHOME
  1773.                 VtLock
  1774.                 return fail
  1775.             }
  1776.             catch {system "$MAKEMAP hash $MHOMETMP < $MHOMETMP >/dev/null 2>&1"} ret
  1777.             if {$ret != 0} {
  1778.                 VtUnLock
  1779.                 mhm_error1 NO_MAP $MHOME
  1780.                 VtLock
  1781.                 return fail
  1782.             }
  1783.             # copy back db file
  1784.             if {[file exists $MHOMETMPODB]} {
  1785.                 catch {system "cmp $MHOMETMPDB $MHOMETMPODB > /dev/null 2>&1"} ret
  1786.             } else {
  1787.                 set ret 1
  1788.             }
  1789.             if {$ret == 1} {
  1790.                 set ret [mhm_remote_copyout $MHOMETMPDB $MHOMEDB]
  1791.                 if {"$ret" != "ok"} {
  1792.                     VtUnLock
  1793.                     mhm_query_eok COPY_BACK $MHOMEDB
  1794.                     VtLock
  1795.                     return fail
  1796.                 }
  1797.             }
  1798.         }
  1799.         set DIRTY 0
  1800.     }
  1801.     mhm_rebuild_domain_map yes
  1802.     return ok
  1803. }
  1804. proc \
  1805. mhm_remoteCommand {host cmd args errMsgId} \
  1806. {
  1807.     set class    [list sco remoteCommand]
  1808.     set instance [GetInstanceList NULL $host]
  1809.     set command [list ObjectAction $class $instance $cmd $args]
  1810.     set result [SaMakeObjectCall $command]
  1811.     set result [lindex $result 0]
  1812.     if { [BmipResponseErrorIsPresent result] } {
  1813.         set errorStack [BmipResponseErrorStack result]
  1814.         set topErrorCode [lindex [lindex $errorStack 0] 0]
  1815.         if { $topErrorCode != "SCO_SA_ERRHANDLER_ERR_CONNECT_FAIL" } {
  1816.             ErrorPush errorStack 1 $errMsgId
  1817.             return {}
  1818.         } else {
  1819.             ErrorThrow errorStack
  1820.             return
  1821.         }
  1822.     }
  1823.     set retVal [BmipResponseActionInfo result]
  1824.     return $retVal
  1825. }
  1826. proc \
  1827. mhm_authorized {host} \
  1828. {
  1829.     set uid [id effective userid]
  1830.     if {$uid != 0} {
  1831.         set cmd "/sbin/tfadmin"
  1832.         set args1 "-t multihome"
  1833.         set args2 "-t cpfile"
  1834.         if {[ErrorCatch errStack 0 {mhm_remoteCommand $host \
  1835.                         $cmd $args1 SCO_USER_MHOME_ERR_TFADMIN} ret1] || \
  1836.                     [ErrorCatch errStack 0 {mhm_remoteCommand $host \
  1837.                         $cmd $args2 SCO_USER_MHOME_ERR_TFADMIN} ret2]} {
  1838.                         return fail
  1839.         }
  1840.     }
  1841.     return ok
  1842. }
  1843. proc \
  1844. quit_cb { {save {}} cbs  } \
  1845. {
  1846.     global status_line
  1847.     set ret "ok"
  1848.     # save everything
  1849.     if {"$save" == "" || $save == 1} {
  1850.         VtLock
  1851.         SaStatusBarSet $status_line [mhm_msg SAVING]
  1852.         set ret [mhm_all_put]
  1853.         VtUnLock
  1854.     }
  1855.     switch $ret {
  1856.     "ok" {
  1857.         quit
  1858.     }
  1859.     "fail" {
  1860.         return
  1861.     }
  1862.     "cancel" {
  1863.         return
  1864.     }
  1865.     }
  1866.     error "unknown quit"
  1867. }
  1868. proc \
  1869. quit {} \
  1870. {
  1871.     VtClose
  1872.     cleanup
  1873.     exit
  1874. }
  1875. proc \
  1876. cleanup {} \
  1877. {
  1878.     global MHOMETMP MHOMETMPDB MHOMETMPODB
  1879.     system "rm -fr $MHOMETMP $MHOMETMPDB $MHOMETMPODB"
  1880. }
  1881. proc \
  1882. main {} \
  1883. {
  1884.     global app DIRTY status_line main_list outerMainForm mainscreen_db
  1885.     global mhm_host_name versionNumber
  1886.     # if command line mode, this routine does not return
  1887.     mhm_cmd_line_main
  1888.     mhm_setcat SCO_USER_MHOME
  1889.     set app [VtOpen multihome [mhm_msg HELPBOOK]]
  1890.     set versionString [mhm_msg APP_TITLE]
  1891.     set versionString "$versionString $versionNumber"
  1892.     VtSetAppValues $app -versionString $versionString
  1893.     set mhm_short_name [lindex [split $mhm_host_name "."] 0]
  1894.     set outerMainForm [ \
  1895.         VtFormDialog $app.main \
  1896.         -resizable FALSE \
  1897.         -wmCloseCallback "quit_cb 1" \
  1898.         -title [mhm_msg1 TITLE $mhm_short_name] \
  1899.         ]
  1900.     mhm_build_widgets $outerMainForm
  1901.     VtShow $outerMainForm
  1902.     VtLock
  1903.     # form is visible and we are locked, now init stuff
  1904.     set DIRTY 0
  1905.     # check if host if ok
  1906.     if {"[mhm_host_check $mhm_host_name]" != "ok"} {
  1907.         VtUnLock
  1908.         mhm_error1 BADHOST $mhm_host_name
  1909.         quit
  1910.     }    
  1911.     # check if authorized
  1912.     if {"[mhm_authorized $mhm_host_name]" == "fail"} {
  1913.         SaDisplayNoAuths $outerMainForm.noAuths [mhm_msg APP_TITLE] \
  1914.         "quit_cb 0" $mhm_short_name
  1915.         VtUnLock
  1916.         VtMainLoop
  1917.         return
  1918.     }
  1919.     # get virtual domain list and users file.
  1920.     if {"[mhm_all_get]" != "ok"} {
  1921.         quit
  1922.     }
  1923.     # display mainlist
  1924.     mhm_display_mainlist
  1925.     VtUnLock
  1926.     SaStatusBarClear $status_line
  1927.     VtMainLoop
  1928. }
  1929. ErrorTopLevelCatch {
  1930. if {"[lindex $argv 0]" == "-h"} {
  1931.     lvarpop argv
  1932.     set mhm_host_name [lvarpop argv]
  1933.     if {"$mhm_host_name" == ""} {
  1934.         echo "multihome: No host name"
  1935.         exit 1
  1936.     }
  1937. }
  1938. if {[lindex $argv 0] == "-mhm_stand_edit"} {
  1939.     mhm_stand_edit [lindex $argv 1] [lindex $argv 2]
  1940.     exit
  1941. }
  1942. if {[lindex $argv 0] == "-mhm_stand_host"} {
  1943.     mhm_stand_host [lindex $argv 1]
  1944.     exit
  1945. }
  1946. main} "multihome"
  1947.