home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March B / SCO_CASTOR4RRT.iso / scoadmin / root.3 / etc / mail / admin / mailadmin / mailadmin~
Text File  |  1998-08-19  |  222KB  |  8,484 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_MAIL_ADMIN_MSGS {} {}
  17. global SCO_MAIL_ADMIN_MSGS
  18. set SCO_MAIL_ADMIN_MSGS(@catalog@) {mag.cat@mail 1}
  19. set SCO_MAIL_ADMIN_MSGS(MSG_HELPBOOK) {1 mailadmin}
  20. set SCO_MAIL_ADMIN_MSGS(MSG_TITLE) {2 {Mail Settings on %1$s}}
  21. set SCO_MAIL_ADMIN_MSGS(MSG_APP_TITLE) {3 {Mail Manager}}
  22. set SCO_MAIL_ADMIN_MSGS(MSG_WIN_TITLE) {4 {Mail Manager on %1$s}}
  23. set SCO_MAIL_ADMIN_MSGS(ERR_CF_COPY_OUT) {5 {Unable to fetch %1$s\nIs it ok to restore the factory version?}}
  24. set SCO_MAIL_ADMIN_MSGS(ERR_CF_FACTORY_RESTORE) {6 {Unable to restore %1$s factory defaults.\nCheck /etc/mail/sendmail.factory.}}
  25. set SCO_MAIL_ADMIN_MSGS(ERR_CF_INVALID) {7 {%1$s appears to have been hand edited\nDo you wish to continue?}}
  26. set SCO_MAIL_ADMIN_MSGS(ERR_CF_OPEN_FAIL) {8 {Unable to open file: %1$s}}
  27. set SCO_MAIL_ADMIN_MSGS(ERR_CF_PARSE) {9 {Unable to parse %1$s\nIs it ok to restore the factory version?}}
  28. set SCO_MAIL_ADMIN_MSGS(ERR_MS1_PARSE) {10 {%1$s has parse errors.\nBad lines will be dropped.\nAlternatively you can restore the factory defaults file.\nDo you wish to restore the factory defaults file?}}
  29. set SCO_MAIL_ADMIN_MSGS(ERR_CF_WRITE) {11 {Unable to write %1$s.}}
  30. set SCO_MAIL_ADMIN_MSGS(ERR_COPY_BACK) {12 {Unable to copy back to %1$s.}}
  31. set SCO_MAIL_ADMIN_MSGS(ERR_FQDN) {13 {Must specify a fully qualified domain name.}}
  32. set SCO_MAIL_ADMIN_MSGS(ERR_INTEGER) {14 {Invalid numeric value (%1$s).}}
  33. set SCO_MAIL_ADMIN_MSGS(ERR_INVALID) {15 {Invalid entry (%1$s).}}
  34. set SCO_MAIL_ADMIN_MSGS(ERR_INVALID_TABLE) {16 {Invalid table type (%1$s).}}
  35. set SCO_MAIL_ADMIN_MSGS(ERR_INVALID_NAME) {17 {Invalid channel name (%1$s).}}
  36. set SCO_MAIL_ADMIN_MSGS(ERR_NULL) {18 {Entry cannot be empty.}}
  37. set SCO_MAIL_ADMIN_MSGS(ERR_AFILE_ONLY) {19 {Can only edit alias files.}}
  38. set SCO_MAIL_ADMIN_MSGS(ERR_USER_FIRST) {20 {Must set non-default user first.}}
  39. set SCO_MAIL_ADMIN_MSGS(ERR_CONFLICT) {21 {Name conflict or restricted name.}}
  40. set SCO_MAIL_ADMIN_MSGS(ERR_CH_NOT_LAST) {22 {Channel is not last.}}
  41. set SCO_MAIL_ADMIN_MSGS(ERR_BADUSER_ONLY) {23 {There can only be one baduser channel.}}
  42. set SCO_MAIL_ADMIN_MSGS(ERR_NOHOST) {24 {Host (%1$s) not found.}}
  43. set SCO_MAIL_ADMIN_MSGS(ERR_BADHOST) {25 {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}}
  44. set SCO_MAIL_ADMIN_MSGS(ERR_INVALID_CLASS) {26 {Classname (%1$s) is invalid, unable to edit.}}
  45. set SCO_MAIL_ADMIN_MSGS(ERR_EXEC) {27 {Unable to exec (%1$s).}}
  46. set SCO_MAIL_ADMIN_MSGS(ERR_NO_MAP) {28 {No map created for %1$s, file contents may be invalid.}}
  47. set SCO_MAIL_ADMIN_MSGS(ERR_FILE_ONLY) {29 {This item is only used for File Lookups.}}
  48. set SCO_MAIL_ADMIN_MSGS(ERR_TFADMIN) {30 {Failure in tfadmin authorization check}}
  49. set SCO_MAIL_ADMIN_MSGS(ERR_SENDMAIL_RESTART) {31 {Failed to restart sendmail}}
  50. set SCO_MAIL_ADMIN_MSGS(MSG_DIRTY) {32 {Do you wish to save your changes?}}
  51. set SCO_MAIL_ADMIN_MSGS(MSG_CONT_DEFAULT) {33 {This will reset all items in the folder to their default values\nDo you wish to continue?}}
  52. set SCO_MAIL_ADMIN_MSGS(MSG_ALIAS1) {34 {Alias File or NIS MAP}}
  53. set SCO_MAIL_ADMIN_MSGS(MSG_ALIAS2) {35 {Examples: btree:/etc/mail/aliases, nis:mail.aliases@domain}}
  54. set SCO_MAIL_ADMIN_MSGS(MSG_NOEXIST) {36 {%1$s does not exist.}}
  55. set SCO_MAIL_ADMIN_MSGS(MSG_NOEXIST_IGNORE) {37 {%1$s does not exist.\nContinue?}}
  56. set SCO_MAIL_ADMIN_MSGS(MSG_EDIT_DTABLE) {38 {Do you wish to edit the domain table?}}
  57. set SCO_MAIL_ADMIN_MSGS(MSG_GO_BACK) {39 {Do you wish to return to host (%1$s)?}}
  58. set SCO_MAIL_ADMIN_MSGS(MSG_UUCP_UPDATE) {40 {The UUCP Systems file map (%1$s) is out of date.\nDo you wish to rebuild it?}}
  59. set SCO_MAIL_ADMIN_MSGS(MSG_SAVING) {41 {Saving configuration...}}
  60. set SCO_MAIL_ADMIN_MSGS(MSG_STR_YES) {42 Yes}
  61. set SCO_MAIL_ADMIN_MSGS(MSG_STR_NO) {43 No}
  62. set SCO_MAIL_ADMIN_MSGS(MSG_STR_CANCEL) {44 Cancel}
  63. set SCO_MAIL_ADMIN_MSGS(MSG_STR_OK) {45 Ok}
  64. set SCO_MAIL_ADMIN_MSGS(MSG_STR_SELECT) {46 Select...}
  65. set SCO_MAIL_ADMIN_MSGS(MSG_STR_NONE) {47 None}
  66. set SCO_MAIL_ADMIN_MSGS(MSG_STR_NONE_DELAY) {48 None/Delay}
  67. set SCO_MAIL_ADMIN_MSGS(MSG_STR_EDIT_ALIAS) {49 {Edit Alias File...}}
  68. set SCO_MAIL_ADMIN_MSGS(MSG_STR_EDIT_CTABLE) {50 {Edit Channel Table File...}}
  69. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_HOST) {51 Host}
  70. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_HOST_MN) {52 t}
  71. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_OPEN) {53 {Open Host...}}
  72. set SCO_MAIL_ADMIN_MSGS(MSG_TITLE_OPEN) {54 {Open Host}}
  73. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_OPEN_MN) {55 O}
  74. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_EXIT) {56 Exit}
  75. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_EXIT_MN) {57 x}
  76. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_EDIT) {58 Edit}
  77. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_EDIT_MN) {59 E}
  78. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_ADD) {60 Add...}
  79. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_ADD_MN) {61 A}
  80. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_DEL) {62 Delete}
  81. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_DEL_MN) {63 D}
  82. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_MOD) {64 Modify...}
  83. set SCO_MAIL_ADMIN_MSGS(MSG_TITLE_MOD) {65 Modify}
  84. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_MOD_MN) {66 M}
  85. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_UP) {67 {Move Up}}
  86. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_UP_MN) {68 U}
  87. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_DN) {69 {Move Down}}
  88. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_DN_MN) {70 o}
  89. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_SET) {71 Settings}
  90. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_SET_MN) {72 S}
  91. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_DEF) {73 Defaults}
  92. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_DEF_MN) {74 D}
  93. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_BADHOST) {75 {Bad Host Forwarding/Delay}}
  94. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_BADHOST_MN) {76 H}
  95. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_BADUSER) {77 {Bad User Enable/Disable}}
  96. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_BADUSER_MN) {78 U}
  97. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_MHOME) {79 {Multihome Enable/Disable}}
  98. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_MHOME_MN) {80 M}
  99. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_UUCP) {81 {UUCP Enable/Disable}}
  100. set SCO_MAIL_ADMIN_MSGS(MSG_MENU_UUCP_MN) {82 C}
  101. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_OPEN) {83 {Manage mail on another host}}
  102. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_EXIT) {84 {Exit Mail Manager}}
  103. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_ADD) {85 {Add item to selected list}}
  104. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_DEL) {86 {Delete selected list-item}}
  105. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_MOD) {87 {Modify selected item}}
  106. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_UP) {88 {Move selected list-item up}}
  107. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_DN) {89 {Most selected list-item down}}
  108. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_DEF) {90 {Restore factory Defaults to selected item}}
  109. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_BADHOST) {91 {Forward mail from unknown hosts}}
  110. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_BADUSER) {92 {Forward mail from unknown users}}
  111. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_UUCP) {93 {Enable or disable the UUCP channel}}
  112. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_MHOME) {94 {Enable or disable the multihome channel}}
  113. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_FOLDER_DIR) {95 {If null, users' home directories are used}}
  114. set SCO_MAIL_ADMIN_MSGS(MSG_SHORT_FOLDER_NAME) {96 {If null, users' login names are used}}
  115. set SCO_MAIL_ADMIN_MSGS(MSG_HOST) {97 {Host Name}}
  116. set SCO_MAIL_ADMIN_MSGS(MSG_FROM) {98 {Mail Comes From}}
  117. set SCO_MAIL_ADMIN_MSGS(MSG_DTABLE) {99 {Domain Table Enabled}}
  118. set SCO_MAIL_ADMIN_MSGS(MSG_DTABLE_FILE) {100 {Domain Table File}}
  119. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_LOCATION) {101 {Users' INBOX Location}}
  120. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_SYSTEM) {102 {System Spool Directory}}
  121. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_HOME) {103 {User's Home Directory}}
  122. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_CUSTOM) {104 {Custom Location}}
  123. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_DIR) {105 {Folder Directory}}
  124. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_NAME) {106 {Folder Name}}
  125. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_FORMAT) {107 {Default Folder Format}}
  126. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_SENDMAIL) {108 Sendmail}
  127. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_MMDF) {109 MMDF}
  128. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_FSYNC) {110 {Folder Synchronize to Disk}}
  129. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_CCHECK) {111 {Folder Consistency Checking}}
  130. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_NORMAL) {112 Normal}
  131. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_EXT) {113 Extended}
  132. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_INCORE) {114 {Folders Cached in Memory}}
  133. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_THRESHOLD) {115 {Folder Garbage Collection Threshold}}
  134. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_TIMEOUT) {116 {Folder Lock Timeout}}
  135. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_FILELOCK) {117 {File Based Locking Enabled}}
  136. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER_UMASK) {118 {File/Directory Creation Umask}}
  137. set SCO_MAIL_ADMIN_MSGS(MSG_CH_NAME) {119 {Channel Name}}
  138. set SCO_MAIL_ADMIN_MSGS(MSG_CH_PROGRAM) {120 {Channel Program (P=)}}
  139. set SCO_MAIL_ADMIN_MSGS(MSG_CH_ARGS) {121 {Channel Program Arguments (A=)}}
  140. set SCO_MAIL_ADMIN_MSGS(MSG_CH_PROGDIR) {122 {Channel Program Run Directory (D=)}}
  141. set SCO_MAIL_ADMIN_MSGS(MSG_CH_TABLE) {123 {Channel Table Type}}
  142. set SCO_MAIL_ADMIN_MSGS(MSG_CH_FILE) {124 {Channel Table File}}
  143. set SCO_MAIL_ADMIN_MSGS(MSG_CH_HOST) {125 {Forward all Channel Mail to}}
  144. set SCO_MAIL_ADMIN_MSGS(MSG_CH_FLAGS) {126 {Channel Flags (F=)}}
  145. set SCO_MAIL_ADMIN_MSGS(MSG_CH_EOL) {127 {Channel End of Line Character (E=)}}
  146. set SCO_MAIL_ADMIN_MSGS(MSG_CH_MAXMSG) {128 {Channel Maximum Message Size (M=)}}
  147. set SCO_MAIL_ADMIN_MSGS(MSG_CH_MAXLINE) {129 {Channel Maximum Line Size (L=)}}
  148. set SCO_MAIL_ADMIN_MSGS(MSG_CH_NICE) {130 {Channel Program Nice Increment (N=)}}
  149. set SCO_MAIL_ADMIN_MSGS(MSG_CH_USER) {131 {Channel Program Runs as User (U=)}}
  150. set SCO_MAIL_ADMIN_MSGS(MSG_CH_GROUP) {132 {Channel Program Runs as Group (U=)}}
  151. set SCO_MAIL_ADMIN_MSGS(MSG_CH_RECIP) {133 {Recipient Envelope Ruleset (R=)}}
  152. set SCO_MAIL_ADMIN_MSGS(MSG_CH_HRECIP) {134 {Recipient Header Ruleset (R=)}}
  153. set SCO_MAIL_ADMIN_MSGS(MSG_CH_SENDER) {135 {Sender Envelope Ruleset (S=)}}
  154. set SCO_MAIL_ADMIN_MSGS(MSG_CH_HSENDER) {136 {Sender Header Ruleset (S=)}}
  155. set SCO_MAIL_ADMIN_MSGS(MSG_MAP) {137 {NIS Map}}
  156. set SCO_MAIL_ADMIN_MSGS(MSG_FILE) {138 File}
  157. set SCO_MAIL_ADMIN_MSGS(MSG_ALTERNATE) {139 {Alternate Name}}
  158. set SCO_MAIL_ADMIN_MSGS(MSG_BASIC) {140 {Basic Configuration}}
  159. set SCO_MAIL_ADMIN_MSGS(MSG_FOLDER) {141 {Folder Configuration}}
  160. set SCO_MAIL_ADMIN_MSGS(MSG_ALIAS) {142 {Alias Files and Maps}}
  161. set SCO_MAIL_ADMIN_MSGS(MSG_ALTNAME) {143 {Alternate Host Names}}
  162. set SCO_MAIL_ADMIN_MSGS(MSG_CHANNEL) {144 {Mail Delivery Channels}}
  163. set SCO_MAIL_ADMIN_MSGS(MSG_LOADING) {145 Loading...}
  164. set SCO_MAIL_ADMIN_MSGS(MSG_NEW_CHANNEL) {146 {New Channel}}
  165. set SCO_MAIL_ADMIN_MSGS(MSG_NONE) {147 <None>}
  166. set SCO_MAIL_ADMIN_MSGS(MSG_DEFAULT) {148 <Default>}
  167. set SCO_MAIL_ADMIN_MSGS(MSG_RULEDEF) {149 {<Same as Envelope>}}
  168. set SCO_MAIL_ADMIN_MSGS(MSG_LOCAL) {150 Local}
  169. set SCO_MAIL_ADMIN_MSGS(MSG_NEW) {151 New}
  170. set SCO_MAIL_ADMIN_MSGS(MSG_CLOCAL) {152 Local}
  171. set SCO_MAIL_ADMIN_MSGS(MSG_CBADHOST) {153 Badhost}
  172. set SCO_MAIL_ADMIN_MSGS(MSG_CBADUSER) {154 Baduser}
  173. set SCO_MAIL_ADMIN_MSGS(MSG_CMHOME) {155 Multihome}
  174. set SCO_MAIL_ADMIN_MSGS(MSG_TTBADUSER) {156 {Match Unknown Users}}
  175. set SCO_MAIL_ADMIN_MSGS(MSG_TTDNS) {157 {Look in Name Service}}
  176. set SCO_MAIL_ADMIN_MSGS(MSG_TTUUCP) {158 {Match UUCP Configuration (Systems file)}}
  177. set SCO_MAIL_ADMIN_MSGS(MSG_TTREMOTE) {159 {Match Non-Local Users}}
  178. set SCO_MAIL_ADMIN_MSGS(MSG_TTLOCAL) {160 {Match Local Users}}
  179. set SCO_MAIL_ADMIN_MSGS(MSG_TTFILE) {161 {File Lookup}}
  180. set SCO_MAIL_ADMIN_MSGS(MSG_FLAGS_LIST1) {162 {Flags Not Set}}
  181. set SCO_MAIL_ADMIN_MSGS(MSG_FLAGS_LIST2) {163 {Flags Set}}
  182. set SCO_MAIL_ADMIN_MSGS(MSG_F_UNKNOWN) {164 {Unknown User Specified Flag}}
  183. set SCO_MAIL_ADMIN_MSGS(MSG_F_a) {165 {Try ESMTP always instead of auto-sensing}}
  184. set SCO_MAIL_ADMIN_MSGS(MSG_F_A) {166 {Look up user in the alias database, usually local mailers only}}
  185. set SCO_MAIL_ADMIN_MSGS(MSG_F_b) {167 {Force blank line on end of a message}}
  186. set SCO_MAIL_ADMIN_MSGS(MSG_F_c) {168 {Do not include comments in addresses}}
  187. set SCO_MAIL_ADMIN_MSGS(MSG_F_C) {169 {Add @domain part for recipients that do not have it, the @domain part is taken from the sender address, it doesn't work reliably}}
  188. set SCO_MAIL_ADMIN_MSGS(MSG_F_d) {170 {Do not include angle brackets around route-syntax addresses, useful for shell script mailers}}
  189. set SCO_MAIL_ADMIN_MSGS(MSG_F_D) {171 {This mailer wants a date 'Date:' header line}}
  190. set SCO_MAIL_ADMIN_MSGS(MSG_F_e) {172 {Expensive mailer to connect to, connect only on queue runs}}
  191. set SCO_MAIL_ADMIN_MSGS(MSG_F_E) {173 {Escape lines beginning with 'From' in the message with a '>' sign}}
  192. set SCO_MAIL_ADMIN_MSGS(MSG_F_f) {174 {Pass -f from flag to mailer}}
  193. set SCO_MAIL_ADMIN_MSGS(MSG_F_F) {175 {This mailer wants a 'From:' header line}}
  194. set SCO_MAIL_ADMIN_MSGS(MSG_F_g) {176 {Internally generated messages are from 'MAILER_DAEMON' ($u), instead of null}}
  195. set SCO_MAIL_ADMIN_MSGS(MSG_F_h) {177 {Upper case should be preserved in host names for this mailer}}
  196. set SCO_MAIL_ADMIN_MSGS(MSG_F_I) {178 {This mailer will be speaking SMTP to another sendmail - use special protocol features of sendmail}}
  197. set SCO_MAIL_ADMIN_MSGS(MSG_F_j) {179 {Do User Database rewriting on recipients as well as senders}}
  198. set SCO_MAIL_ADMIN_MSGS(MSG_F_k) {180 {Disable SMTP loopback check}}
  199. set SCO_MAIL_ADMIN_MSGS(MSG_F_K) {181 {Currently unimplemented, reserved for chunking}}
  200. set SCO_MAIL_ADMIN_MSGS(MSG_F_l) {182 {This mailer is local, final delivery will be performed}}
  201. set SCO_MAIL_ADMIN_MSGS(MSG_F_L) {183 {Limit line lengths as specified in RFC821, L= should be used instead of this flag, this flag also sets the 7 flag}}
  202. set SCO_MAIL_ADMIN_MSGS(MSG_F_m) {184 {Mailer can handle multiple users, $u will be expanded as needed}}
  203. set SCO_MAIL_ADMIN_MSGS(MSG_F_M) {185 {This mailer wants a 'Message-Id:' header line}}
  204. set SCO_MAIL_ADMIN_MSGS(MSG_F_n) {186 {Do not insert a UNIX-style 'From' line on the front of the message}}
  205. set SCO_MAIL_ADMIN_MSGS(MSG_F_o) {187 {Always run as the user of the recipient mailbox, ignored if S is set}}
  206. set SCO_MAIL_ADMIN_MSGS(MSG_F_p) {188 {Use route-addr style reverese-path in the SMTP 'MAIL FROM:' command rather than just the return address}}
  207. set SCO_MAIL_ADMIN_MSGS(MSG_F_P) {189 {This mailer wants a 'Return-Path:' header line}}
  208. set SCO_MAIL_ADMIN_MSGS(MSG_F_q) {190 {Addresses for this mailer are verified as local by the SMTP verify command, i.e. 250 responses are generated instead of 252 responses}}
  209. set SCO_MAIL_ADMIN_MSGS(MSG_F_r) {191 {Same as f, but send -r flag}}
  210. set SCO_MAIL_ADMIN_MSGS(MSG_F_s) {192 {Strip quote characters (\" and \\) off of the address before calling the mailer}}
  211. set SCO_MAIL_ADMIN_MSGS(MSG_F_S) {193 {Don't reset the userid before calling the mailer, if U= is also specified, then that user and group is used}}
  212. set SCO_MAIL_ADMIN_MSGS(MSG_F_u) {194 {Upper case should be preserved in user names for this mailer}}
  213. set SCO_MAIL_ADMIN_MSGS(MSG_F_U) {195 {This mailer wants UUCP-style 'From' lines with the 'remote from host' on the end}}
  214. set SCO_MAIL_ADMIN_MSGS(MSG_F_w) {196 {The user must have a valid account on this machine or the mail will bounce, this is required to enable .forward capability}}
  215. set SCO_MAIL_ADMIN_MSGS(MSG_F_x) {197 {This mailer wants a 'Full-Name:' header line}}
  216. set SCO_MAIL_ADMIN_MSGS(MSG_F_X) {198 {This mailer wants to use the hidden dot algorithm described in RFC821}}
  217. set SCO_MAIL_ADMIN_MSGS(MSG_F_0) {199 {Don't look up MX records for hosts send via SMTP}}
  218. set SCO_MAIL_ADMIN_MSGS(MSG_F_3) {200 {When encoding quoted printable, include those characters that don't map cleanly between ASCII and EBCDIC}}
  219. set SCO_MAIL_ADMIN_MSGS(MSG_F_5) {201 {Enable ruleset 5 processing for this mailer, aliasing must be enabled (A flag)}}
  220. set SCO_MAIL_ADMIN_MSGS(MSG_F_7) {202 {Strip all output to seven bits, L flag sets this by default}}
  221. set SCO_MAIL_ADMIN_MSGS(MSG_F_8) {203 {Strip all output to seven bits, done after any 8 to 7 bit conversion}}
  222. set SCO_MAIL_ADMIN_MSGS(MSG_F_9) {204 {Do limited 7 to 8 bit MIME conversion, text/plain messages only}}
  223. set SCO_MAIL_ADMIN_MSGS(MSG_F_COLON) {205 {Check addresses to see if they begin with ':include:', if they do convert them to the '*include*' mailer}}
  224. set SCO_MAIL_ADMIN_MSGS(MSG_F_PIPE) {206 {Check addresses to see if they begin with a '|', if they do convert them to the 'prog' mailer}}
  225. set SCO_MAIL_ADMIN_MSGS(MSG_F_SLASH) {207 {Check addresses to see if they begin with a '/', if they do convert them to the '*file*' mailer}}
  226. set SCO_MAIL_ADMIN_MSGS(MSG_F_AT) {208 {Look up addresses in the user database}}
  227. proc \
  228. mag_setcat { catname } \
  229. {
  230.     global mag_catname
  231.     set mag_catname $catname
  232. }
  233. proc \
  234. mag_msg { msg } \
  235. {
  236.     global mag_catname
  237.     return [IntlLocalizeMsg ${mag_catname}_MSG_$msg]
  238. }
  239. proc \
  240. mag_msg1 { msg arg } \
  241. {
  242.     global mag_catname
  243.     return [IntlLocalizeMsg ${mag_catname}_MSG_$msg [list $arg]]
  244. }
  245. proc \
  246. mag_err { msg } \
  247. {
  248.     global mag_catname
  249.     return [IntlLocalizeMsg ${mag_catname}_ERR_$msg]
  250. }
  251. proc \
  252. mag_err1 { msg arg } \
  253. {
  254.     global mag_catname
  255.     return [IntlLocalizeMsg ${mag_catname}_ERR_$msg [list $arg]]
  256. }
  257. proc \
  258. mag_query_eyn { msg arg } \
  259. {
  260.     global app
  261.     set ret [VtErrorDialog $app.err -block \
  262.         -message [mag_err1 $msg $arg] \
  263.         -ok -okLabel [mag_msg STR_YES] \
  264.         -apply -applyLabel [mag_msg STR_NO]]
  265.     switch "$ret" {
  266.     "OK"     {
  267.         return yes
  268.     }
  269.     "APPLY"     {
  270.         return no
  271.     }
  272.     "CANCEL" {
  273.         return cancel
  274.     }
  275.     }
  276.     error "mag_query_eyn: Unknown result code: $ret"
  277. }
  278. proc \
  279. mag_query_eok { msg arg } \
  280. {
  281.     global app
  282.     set ret [VtErrorDialog $app.err -block \
  283.         -message [mag_err1 $msg $arg] \
  284.         -ok -okLabel [mag_msg STR_OK]]
  285.     if {"$ret" == "OK"} {
  286.         return yes
  287.     }
  288.     error "mag_query_eok: Unknown result code: $ret"
  289. }
  290. proc \
  291. mag_query_qync { msg arg } \
  292. {
  293.     global app
  294.     set ret [VtQuestionDialog $app.err -block \
  295.         -message [mag_msg1 $msg $arg] \
  296.         -ok -okLabel [mag_msg STR_YES] \
  297.         -apply -applyLabel [mag_msg STR_NO] \
  298.         -cancel -cancelLabel [mag_msg STR_CANCEL]]
  299.     switch "$ret" {
  300.      "OK"     {
  301.          return yes
  302.      }
  303.     "APPLY"     {
  304.         return no
  305.     }
  306.     "CANCEL" {
  307.         return cancel
  308.     }
  309.     }
  310.     error "mag_query_qync: Unknown result code: $ret"
  311. }
  312. proc \
  313. mag_query_qyn { msg arg } \
  314. {
  315.     global app
  316.     set ret [VtQuestionDialog $app.err -block \
  317.         -message [mag_msg1 $msg $arg] \
  318.         -ok -okLabel [mag_msg STR_YES] \
  319.         -apply -applyLabel [mag_msg STR_NO]]
  320.     switch "$ret" {
  321.      "OK"     {
  322.          return yes
  323.      }
  324.     "APPLY"     {
  325.         return no
  326.     }
  327.     }
  328.     error "mag_query_qyn: Unknown result code: $ret"
  329. }
  330. proc \
  331. mag_error { msg } \
  332. {
  333.     global app
  334.     VtErrorDialog $app.err -block -ok -message [mag_err $msg]
  335. }
  336. proc \
  337. mag_error1 { msg arg } \
  338. {
  339.     global app
  340.     VtErrorDialog $app.err -block -ok -message [mag_err1 $msg $arg]
  341. }
  342. proc \
  343. mag_warn1 { msg arg } \
  344. {
  345.     global app
  346.     VtWarningDialog $app.err -block -ok -message [mag_msg1 $msg $arg]
  347. }
  348. proc \
  349. mag_short_name_default {} \
  350. {
  351.     global mag_host_name
  352.     set fqdn $mag_host_name
  353.     set list [split $fqdn "."]
  354.     return [lindex $list 0]
  355. }
  356. proc \
  357. mag_num_to_bool num \
  358. {
  359.     if {$num == 0} {
  360.         return [mag_msg STR_NO]
  361.     }
  362.     if {$num == 1} {
  363.         return [mag_msg STR_YES]
  364.     }
  365.     error "Unknown boolean numeric $num"
  366. }
  367. proc \
  368. mag_bool_to_num bool \
  369. {
  370.     if {"$bool" == "[mag_msg STR_NO]"} {
  371.         return 0
  372.     }
  373.     if {"$bool" == "[mag_msg STR_YES]"} {
  374.         return 1
  375.     }
  376.     error "Unknown boolean string $bool"
  377. }
  378. proc \
  379. mag_string_to_bool str \
  380. {
  381.     set str [string toupper $str]
  382.     if {"$str" == "FALSE"} {
  383.         return [mag_msg STR_NO]
  384.     }
  385.     if {"$str" == "TRUE"} {
  386.         return [mag_msg STR_YES]
  387.     }
  388.     error "Unknown boolean string $str"
  389. }
  390. proc \
  391. mag_bool_to_string bool \
  392. {
  393.     if {"$bool" == "[mag_msg STR_NO]"} {
  394.         return FALSE
  395.     }
  396.     if {"$bool" == "[mag_msg STR_YES]"} {
  397.         return TRUE
  398.     }
  399.     error "Unknown boolean string $bool"
  400. }
  401. proc \
  402. mag_ms1_location {} \
  403. {
  404.     global MAILSPOOL
  405.     set inboxdir [ma_ms1_get MS1_INBOX_DIR]
  406.     set inboxname [ma_ms1_get MS1_INBOX_NAME]
  407.     # system spool directory
  408.     if {"$inboxdir" == "$MAILSPOOL" && "$inboxname" == ""} {
  409.         return [mag_msg FOLDER_SYSTEM]
  410.     }
  411.     if {"$inboxdir" == "" && "$inboxname" == ".mailbox"} {
  412.         return [mag_msg FOLDER_HOME]
  413.     }
  414.     return [mag_msg FOLDER_CUSTOM]
  415. }
  416. proc \
  417. mag_ms1_format {} \
  418. {
  419.     global MAILSPOOL
  420.     set format [ma_ms1_get MS1_FOLDER_FORMAT]
  421.     # case insensitive compares
  422.     set format [string toupper $format]
  423.     if {"$format" == "SENDMAIL"} {
  424.         return [mag_msg FOLDER_SENDMAIL]
  425.     }
  426.     if {"$format" == "MMDF"} {
  427.         return [mag_msg FOLDER_MMDF]
  428.     }
  429.     error "Unknown folder format: $format"
  430. }
  431. proc \
  432. mag_table_to_internal { ttype } \
  433. {
  434.     if {"$ttype" == "[mag_msg TTBADUSER]"} {
  435.         return baduser
  436.     }
  437.     if {"$ttype" == "[mag_msg TTDNS]"} {
  438.         return DNS
  439.     }
  440.     if {"$ttype" == "[mag_msg TTUUCP]"} {
  441.         return UUCP
  442.     }
  443.     if {"$ttype" == "[mag_msg TTREMOTE]"} {
  444.         return remote
  445.     }
  446.     if {"$ttype" == "[mag_msg TTLOCAL]"} {
  447.         return local
  448.     }
  449.     if {"$ttype" == "[mag_msg TTFILE]"} {
  450.         return file
  451.     }
  452.     error "Unknown table type $ttype."
  453. }
  454. proc \
  455. mag_table_enum {} \
  456. {
  457.     set list [list \
  458.         [mag_msg TTBADUSER] \
  459.         [mag_msg TTDNS] \
  460.         [mag_msg TTUUCP] \
  461.         [mag_msg TTREMOTE] \
  462.         [mag_msg TTLOCAL] \
  463.         [mag_msg TTFILE] \
  464.     ]
  465.     return $list
  466. }
  467. proc \
  468. mag_table_to_external { ttype } \
  469. {
  470.     if {"$ttype" == "baduser"} {
  471.         return [mag_msg TTBADUSER]
  472.     }
  473.     if {"$ttype" == "DNS"} {
  474.         return [mag_msg TTDNS]
  475.     }
  476.     if {"$ttype" == "UUCP"} {
  477.         return [mag_msg TTUUCP]
  478.     }
  479.     if {"$ttype" == "remote"} {
  480.         return [mag_msg TTREMOTE]
  481.     }
  482.     if {"$ttype" == "local"} {
  483.         return [mag_msg TTLOCAL]
  484.     }
  485.     if {"$ttype" == "file"} {
  486.         return [mag_msg TTFILE]
  487.     }
  488.     error "Unknown table type $ttype."
  489. }
  490. proc \
  491. mag_channel_to_alias { chname } \
  492. {
  493.     switch "$chname" {
  494.     "local" {
  495.         return [mag_msg CLOCAL]
  496.     }
  497.     "badhost" {
  498.         return [mag_msg CBADHOST]
  499.     }
  500.     "baduser" {
  501.         return [mag_msg CBADUSER]
  502.     }
  503.     "multihome" {
  504.         return [mag_msg CMHOME]
  505.     }
  506.     }
  507.     # no change
  508.     return $chname
  509. }
  510. proc \
  511. mag_channel_to_internal { chname } \
  512. {
  513.     if {"$chname" == "[mag_msg CLOCAL]"} {
  514.         return local
  515.     }
  516.     if {"$chname" == "[mag_msg CBADHOST]"} {
  517.         return badhost
  518.     }
  519.     if {"$chname" == "[mag_msg CBADUSER]"} {
  520.         return baduser
  521.     }
  522.     if {"$chname" == "[mag_msg CMHOME]"} {
  523.         return multihome
  524.     }
  525.     # no change
  526.     return $chname
  527. }
  528. proc \
  529. mag_rebuild_uucp_map { prompt } \
  530. {
  531.     global PID UUCP UUCPDB MAKEMAP
  532.     # check if any UUCP channels
  533.     set channels [mai_ch_names_get]
  534.     set found no
  535.     foreach chname $channels {
  536.         set type [ma_ch_table_type_get $chname]
  537.         if {"$type" == "UUCP"} {
  538.             set found yes
  539.             break
  540.         }
  541.     }
  542.     if {"$found" == "no"} {
  543.         return ok
  544.     }
  545.     # yes, check if UUCP map is out of date.
  546.     set tmp1 "/tmp/systems.$PID"
  547.     set tmp1db "/tmp/systems.$PID.db"
  548.     set tmp2db "/tmp/systems.1.$PID.db"
  549.     system "rm -f $tmp1 $tmp1db $tmp2db"
  550.     set ret [mag_remote_copyin $UUCP $tmp1]
  551.     set ret [mag_remote_copyin $UUCPDB $tmp2db]
  552.     # now make a map
  553.     if {[file exists $tmp1] == 1} {
  554.         set copy no
  555.         catch {system "$MAKEMAP hash $tmp1 < $tmp1 >/dev/null 2>&1"} ret
  556.         if {$ret != 0} {
  557.             if {"$prompt" == "yes"} {
  558.                 VtUnLock
  559.                 mag_error1 NO_MAP $UUCP
  560.                 VtLock
  561.             }
  562.             system "rm -f $tmp1 $tmp1db $tmp2db"
  563.             return fail
  564.         }
  565.         # no previous map, always copy back
  566.         if {[file exists $tmp2db] == 0} {
  567.             set copy yes
  568.         } else {
  569.             catch {system "cmp $tmp1db $tmp2db > /dev/null 2>&1"} tmp
  570.             # files are different
  571.             if {$tmp == 1} {
  572.                 set copy yes
  573.             }
  574.         }
  575.         if {"$prompt" == "no"} {
  576.             set copy yes
  577.         }
  578.         if {"$copy" == "no"} {
  579.             system "rm -f $tmp1 $tmp1db $tmp2db"
  580.             return ok
  581.         }
  582.         # prompt if copy is ok.
  583.         set ret yes
  584.         if {"$prompt" == "yes"} {
  585.             VtUnLock
  586.             set ret [mag_query_qyn UUCP_UPDATE $UUCPDB]
  587.             VtLock
  588.         }
  589.         if {"$ret" == "yes"} {
  590.             set ret [mag_remote_copyout $tmp1db $UUCPDB]
  591.             if {"$ret" == "fail"} {
  592.                 if {"$prompt" == "yes"} {
  593.                     VtUnLock
  594.                     mag_error1 COPY_BACK $UUCPDB
  595.                     VtLock
  596.                 }
  597.                 system "rm -f $tmp1 $tmp1db $tmp2db"
  598.                 return fail
  599.             }
  600.         }
  601.         system "rm -f $tmp1 $tmp1db $tmp2db"
  602.     }
  603.     return ok
  604. }
  605. proc \
  606. mag_build_ruleset { env hdr } \
  607. {
  608.     if {"$hdr" == ""} {
  609.         set value "$env"
  610.     } else {
  611.         if {"$env" != ""} {
  612.             set value "$env/$hdr"
  613.         } else {
  614.             set value "0/$hdr"
  615.         }
  616.     }
  617.     return $value
  618. }
  619. proc \
  620. mag_escape { string } \
  621. {
  622.     set list [split $string "$$"]
  623.     set newlist [join $list "\\$"]
  624.     return $newlist
  625. }
  626. proc \
  627. mag_trim_zero { value } \
  628. {
  629.     set sign ""
  630.     set test $value
  631.     if {"[csubstr $value 0 1]" == "-"} {
  632.         set sign "-"
  633.         set test [csubstr $value 1 end]
  634.     }
  635.     set test [string trimleft $test "0"]
  636.     if {"$test" == ""} {
  637.         set test "0"
  638.     }
  639.     set value "$sign$test"
  640.     return $value
  641. }
  642. proc \
  643. mao_init {} \
  644. {
  645.     global mainscreen_db
  646.     set db ""
  647.     set list [list container "" config 0 "" [mag_msg BASIC] closed]
  648.     lappend db $list
  649.     set list [list container "" folder 0 "" [mag_msg FOLDER] closed]
  650.     lappend db $list
  651.     set list [list container "" alias 0 add [mag_msg ALIAS] closed]
  652.     lappend db $list
  653.     set list [list container "" altname 0 add [mag_msg ALTNAME] closed]
  654.     lappend db $list
  655.     set list [list container "" channels 0 add [mag_msg CHANNEL] closed]
  656.     lappend db $list
  657.     set mainscreen_db $db
  658. }
  659. proc \
  660. mao_activate { index } \
  661. {
  662.     global mainscreen_db MS
  663.     set list [lindex $mainscreen_db $index]
  664.     set class [lindex $list $MS(class)]
  665.     if {"$class" == "property"} {
  666.         set action [lindex $list $MS(action)]
  667.         mai_modify $index
  668.         return
  669.     }
  670.     set state [lindex $list $MS(state)]
  671.     if {"$state" == "closed"} {
  672.         mai_expand $index
  673.         return
  674.     }
  675.     if {"$state" == "open"} {
  676.         mai_collapse $index
  677.         return
  678.     }
  679.     error "unknown state $state"
  680. }
  681. proc \
  682. mao_default { index prompt } \
  683. {
  684.     global mainscreen_db MS MAILALIASES DIRTY SLOCAL
  685.     set list [lindex $mainscreen_db $index]
  686.     set class [lindex $list $MS(class)]
  687.     if {"$class" == "property"} {
  688.         set newlist [mai_prop_def $list]
  689.         if {"$newlist" != "$list"} {
  690.             set DIRTY 1
  691.             set newlist [mai_prop_set $list $newlist]
  692.             set mainscreen_db [lreplace $mainscreen_db \
  693.                 $index $index $newlist]
  694.             # check other state changes
  695.             mai_state $list $newlist $index
  696.             # redraw main screen
  697.             set stop [expr $index + 1]
  698.             mag_display_mainlist $index $stop $index
  699.         }
  700.         return
  701.     }
  702.     set type [lindex $list $MS(type)]
  703.     set state [lindex $list $MS(state)]
  704.     if {"$prompt" == "yes"} {
  705.         VtUnLock
  706.         set ret [mag_query_qyn CONT_DEFAULT ""]
  707.         VtLock
  708.         if {"$ret" == "no"} {
  709.             return
  710.         }
  711.     }
  712.     set DIRTY 1
  713.     # default all elements inside a container
  714.     switch $type {
  715.     "config" {
  716.         if {"$state" == "open"} {
  717.             mai_collapse $index
  718.         }
  719.         set children [mai_get_children $list]
  720.         foreach child $children {
  721.             set list [mai_prop_def $child]
  722.             mai_prop_set $child $list
  723.         }
  724.         if {"$state" == "open"} {
  725.             mai_expand $index
  726.             return
  727.         }
  728.         return
  729.     }
  730.     "folder" {
  731.         # same code as "config"
  732.         if {"$state" == "open"} {
  733.             mai_collapse $index
  734.         }
  735.         set children [mai_get_children $list]
  736.         foreach child $children {
  737.             set list [mai_prop_def $child]
  738.             mai_prop_set $child $list
  739.         }
  740.         if {"$state" == "open"} {
  741.             mai_expand $index
  742.             return
  743.         }
  744.         return
  745.     }
  746.     "alias" {
  747.         # the list of alias names must change
  748.         # collapse if needed
  749.         if {"$state" == "open"} {
  750.             mai_collapse $index
  751.         }
  752.         ma_aliases_set $MAILALIASES
  753.         if {"$state" == "open"} {
  754.             mai_expand $index
  755.         }
  756.         return
  757.     }
  758.     "altname" {
  759.         # the list of alternate names must change
  760.         # collapse if needed
  761.         if {"$state" == "open"} {
  762.             mai_collapse $index
  763.         }
  764.         ma_alternate_names_set ""
  765.         if {"$state" == "open"} {
  766.             mai_expand $index
  767.         }
  768.         return
  769.     }
  770.     "channels" {
  771.         # delete all channels and add back in the default ones.
  772.         # collapse if needed
  773.         if {"$state" == "open"} {
  774.             mai_collapse $index
  775.         }
  776.         set children [mai_get_children $list]
  777.         foreach child $children {
  778.             set chname [lindex $child $MS(name)]
  779.             ma_ch_delete $chname
  780.         }
  781.         ma_ch_create local
  782.             ma_ch_sequence_set local 0
  783.             ma_ch_equate_set local P $SLOCAL
  784.             ma_ch_table_type_set local local
  785.         ma_ch_create SMTP
  786.             ma_ch_sequence_set SMTP 1
  787.             ma_ch_equate_set SMTP P "\[IPC\]"
  788.             ma_ch_table_type_set SMTP DNS
  789.         ma_ch_create badhost
  790.             ma_ch_sequence_set badhost 2
  791.             ma_ch_equate_set badhost P "\[IPC\]"
  792.             ma_ch_table_type_set badhost remote
  793.         # set the channel props to defaults for new children
  794.         set children [mai_get_children $list]
  795.         foreach child $children {
  796.             # get props for this channel
  797.             set tmpchildren [mai_get_children $child]
  798.             foreach tmpchild $tmpchildren {
  799.                 set tmplist [mai_prop_def $tmpchild]
  800.                 mai_prop_set $tmpchild $tmplist
  801.             }
  802.         }
  803.         # don't preserve individual channel expansions as they might
  804.         # not be there any more.
  805.         if {"$state" == "open"} {
  806.             mai_expand $index
  807.         }
  808.         return
  809.     }
  810.     "channel" {
  811.         if {"$state" == "open"} {
  812.             mai_collapse $index
  813.         }
  814.         # get props for this channel
  815.         set children [mai_get_children $list]
  816.         foreach child $children {
  817.             set tmplist [mai_prop_def $child]
  818.             mai_prop_set $child $tmplist
  819.         }
  820.         if {"$state" == "open"} {
  821.             mai_expand $index
  822.         }
  823.         return
  824.     }
  825.     }
  826. }
  827. proc \
  828. mao_select { index } \
  829. {
  830.     global mainscreen_db MS
  831.     global btn_mod btn_add btn_del btn_up btn_dn
  832.     global menu_mod menu_add menu_del menu_up menu_dn
  833.     set list [lindex $mainscreen_db $index]
  834.     set actions [lindex $list $MS(action)]
  835.     set add FALSE
  836.     set del FALSE
  837.     set mod FALSE
  838.     set mov FALSE
  839.     foreach i $actions {
  840.         if {"$i" == "mod"} {
  841.             set mod TRUE
  842.             continue
  843.         }
  844.         if {"$i" == "add"} {
  845.             set add TRUE
  846.             continue
  847.         }
  848.         if {"$i" == "mov"} {
  849.             set mov TRUE
  850.             continue
  851.         }
  852.         if {"$i" == "del"} {
  853.             set del TRUE
  854.             continue
  855.         }
  856.         error "unknown action $i"
  857.     }
  858.     if {[VtInfo -charm] == 0} {
  859.         VtSetSensitive $btn_mod $mod
  860.         VtSetSensitive $btn_add $add
  861.         VtSetSensitive $btn_up $mov
  862.         VtSetSensitive $btn_dn $mov
  863.         VtSetSensitive $btn_del $del
  864.     }
  865.     VtSetSensitive $menu_mod $mod
  866.     VtSetSensitive $menu_add $add
  867.     VtSetSensitive $menu_up $mov
  868.     VtSetSensitive $menu_dn $mov
  869.     VtSetSensitive $menu_del $del
  870. }
  871. proc \
  872. mao_move { index direction } \
  873. {
  874.     global mainscreen_db MS DIRTY
  875.     # find number of children of current object
  876.     set childcount [mai_child_length $index]
  877.     # total length of current object
  878.     set length [expr $childcount + 1]
  879.     # length of mainlist
  880.     set mainlen [llength $mainscreen_db]
  881.     # our current object
  882.     set list [lindex $mainscreen_db $index]
  883.     set level [lindex $list $MS(level)]
  884.     # index of last predecessor - 1
  885.     set start [expr $index - 1]
  886.     set stop 0
  887.     set newlevel 0
  888.     while {$start >= $stop} {
  889.         set newlist [lindex $mainscreen_db $start]
  890.         set newlevel [lindex $newlist $MS(level)]
  891.         if {$newlevel <= $level} {
  892.             break
  893.         }
  894.         set start [expr $start - 1]
  895.     }
  896.     if {$newlevel == $level} {
  897.         set prev $start
  898.     } else {
  899.         set prev $index
  900.     }
  901.     # index of successor + 1
  902.     set start [expr $index + 1]
  903.     set stop $mainlen
  904.     set newlevel 0
  905.     while {$start < $stop} {
  906.         set newlist [lindex $mainscreen_db $start]
  907.         set newlevel [lindex $newlist $MS(level)]
  908.         if {$newlevel <= $level} {
  909.             break
  910.         }
  911.         set start [expr $start + 1]
  912.     }
  913.     if {$newlevel == $level} {
  914.         set nextobj $start
  915.         set next $start
  916.         # open object check
  917.         set class [lindex $newlist $MS(class)]
  918.         if {"$class" == "container"} {
  919.             set state [lindex $newlist $MS(state)]
  920.             if {"$state" == "open"} {
  921.                 set tmpchildren [mai_get_children $newlist]
  922.                 set tmplength [llength $tmpchildren]
  923.                 set next [expr $next + $tmplength]
  924.             }
  925.         }
  926.     } else {
  927.         set next $index
  928.     }
  929.     # check if no-op
  930.     if {"$direction" == "up" && $prev == $index} {
  931.         return
  932.     }
  933.     if {"$direction" == "down"} {
  934.         if {$next == $index} {
  935.             return
  936.         }
  937.         # now check if next cannot be moved (baduser check)
  938.         set action [lindex $newlist $MS(action)]
  939.         if {[lsearch $action mov] == -1} {
  940.             return
  941.         }
  942.     }
  943.     set DIRTY 1
  944.     # now fix internal database
  945.     # can move three types, alias maps, alternate names, and channels
  946.     set class [lindex $list $MS(class)]
  947.     if {"$class" == "container"} {
  948.         set type channel
  949.     } else {
  950.         set type [lindex $list $MS(name)]
  951.     }
  952.     # swap list with other
  953.     if {"$direction" == "up"} {
  954.         set other [lindex $mainscreen_db $prev]
  955.     } else {
  956.         set other [lindex $mainscreen_db $nextobj]
  957.     }
  958.     switch "$type" {
  959.     "channel" {
  960.         set chname1 [lindex $list $MS(name)]
  961.         set chname2 [lindex $other $MS(name)]
  962.         set order1 [ma_ch_sequence_get $chname1]
  963.         set order2 [ma_ch_sequence_get $chname2]
  964.         ma_ch_sequence_set $chname1 $order2
  965.         ma_ch_sequence_set $chname2 $order1
  966.     }
  967.     "altname" {
  968.         set alts [ma_alternate_names_get]
  969.         set alt1 [lindex $list $MS(value)]
  970.         set alt2 [lindex $other $MS(value)]
  971.         set order1 [lsearch $alts $alt1]
  972.         set order2 [lsearch $alts $alt2]
  973.         set alts [lreplace $alts $order1 $order1 $alt2]
  974.         set alts [lreplace $alts $order2 $order2 $alt1]
  975.         ma_alternate_names_set $alts
  976.     }
  977.     "alias" {
  978.         set aliases [ma_aliases_get]
  979.         set alias1 [lindex $list $MS(value)]
  980.         set alias2 [lindex $other $MS(value)]
  981.         set order1 [lsearch $aliases $alias1]
  982.         set order2 [lsearch $aliases $alias2]
  983.         set aliases [lreplace $aliases $order1 $order1 $alias2]
  984.         set aliases [lreplace $aliases $order2 $order2 $alias1]
  985.         ma_aliases_set $aliases
  986.     }
  987.     }
  988.     # ready to do mainscreen_db and main_list
  989.     # first delete this item, both from mainscreen_db and main_list.
  990.     set start $index
  991.     set stop [expr $index + $childcount]
  992.     set tmplist [lrange $mainscreen_db $start $stop]
  993.     set mainscreen_db [lreplace $mainscreen_db $start $stop]
  994.     set minus1 [expr $index - 1]
  995.     mag_delete_mainlist $minus1 $length
  996.     mag_display_mainlist $minus1 $index -1
  997.     # update next index
  998.     set next [expr $next - $length]
  999.     # ready to insert at the appropriate location
  1000.     if {"$direction" == "up"} {
  1001.         # insert mainscreen_db before this index
  1002.         set insert $prev
  1003.     }
  1004.     if {"$direction" == "down"} {
  1005.         # insert mainscreen_db before this index
  1006.         set insert [expr $next + 1]
  1007.     }
  1008.     set pos $insert
  1009.     loop i 0 $length {
  1010.         set insertlist [lindex $tmplist $i]
  1011.         set mainscreen_db [linsert $mainscreen_db $pos $insertlist]
  1012.         set pos [expr $pos + 1]
  1013.     }
  1014.     # put new inserted data on screen
  1015.     set newstart [expr $insert - 1]
  1016.     mag_insert_mainlist $newstart $length
  1017.     # must redraw previous object through end of mainlist to get lines right
  1018.     mag_display_mainlist $start $mainlen $insert
  1019. }
  1020. proc \
  1021. mao_add { index } \
  1022. {
  1023.     global mainscreen_db DIRTY MS
  1024.     # we can add three types, alias maps, alternate names, and channels
  1025.     #
  1026.     # for maps and alt names our strategy is to create an empty
  1027.     # object onscreen named "new" and call mai_modify.  If mai_modify
  1028.     # returns yes, we keep the object otherwise we delete it.
  1029.     #
  1030.     # alias and altname are similar enough to share code,
  1031.     # channels are special.
  1032.     set container [lindex $mainscreen_db $index]
  1033.     set type [lindex $container $MS(type)]
  1034.     # new channel
  1035.     if {"$type" == "channels"} {
  1036.         mag_channel_create $index
  1037.         return
  1038.     }
  1039.     # common code for new alias or altername name
  1040.     # collapse onscreen container
  1041.     mai_collapse $index
  1042.     # add new item to top of list
  1043.     if {"$type" == "alias"} {
  1044.         set list [ma_aliases_get]
  1045.         set list "[mag_msg NEW] $list"
  1046.         ma_aliases_set $list
  1047.     }
  1048.     if {"$type" == "altname"} {
  1049.         set list [ma_alternate_names_get]
  1050.         set list "[mag_msg NEW] $list"
  1051.         ma_alternate_names_set $list
  1052.     }
  1053.     # make it visible
  1054.     mai_expand $index
  1055.     # select it
  1056.     set start [expr $index + 1]
  1057.     mag_display_mainlist $start $start $start
  1058.     # call mai_modify
  1059.     set ret [mai_modify $start]
  1060.     # keep the new entry
  1061.     if {"$ret" == "yes"} {
  1062.         set DIRTY 1
  1063.         return
  1064.     }
  1065.     # delete the new entry
  1066.     mao_delete $start
  1067.     # select the container
  1068.     mag_display_mainlist $index $index $index
  1069. }
  1070. proc \
  1071. mao_delete { index } \
  1072. {
  1073.     global mainscreen_db MS DIRTY
  1074.     set DIRTY 1
  1075.     # can delete three types, alias maps, alternate names, and channels
  1076.     set list [lindex $mainscreen_db $index]
  1077.     set class [lindex $list $MS(class)]
  1078.     set childcount 0
  1079.     if {"$class" == "container"} {
  1080.         set state [lindex $list $MS(state)]
  1081.         if {"$state" == "open"} {
  1082.             set children [mai_get_children $list]
  1083.             set childcount [llength $children]
  1084.         }
  1085.     }
  1086.     # first delete from the database
  1087.     if {"$class" == "container"} {
  1088.         set type channel
  1089.     } else {
  1090.         set type [lindex $list $MS(name)]
  1091.     }
  1092.     switch "$type" {
  1093.     "channel" {
  1094.         set chname [lindex $list $MS(name)]
  1095.         set channels [mai_ch_names_get]
  1096.         set order 0
  1097.         # resequence channels
  1098.         foreach i $channels {
  1099.             if {"$i" == "$chname"} {
  1100.                 ma_ch_delete $chname
  1101.                 continue
  1102.             }
  1103.             ma_ch_sequence_set $i $order
  1104.             set order [expr $order + 1]
  1105.         }
  1106.     }
  1107.     "altname" {
  1108.         set alts [ma_alternate_names_get]
  1109.         set alt [lindex $list $MS(value)]
  1110.         set order [lsearch $alts $alt]
  1111.         set alts [lreplace $alts $order $order]
  1112.         ma_alternate_names_set $alts
  1113.     }
  1114.     "alias" {
  1115.         set aliases [ma_aliases_get]
  1116.         set alias [lindex $list $MS(value)]
  1117.         set order [lsearch $aliases $alias]
  1118.         set aliases [lreplace $aliases $order $order]
  1119.         ma_aliases_set $aliases
  1120.     }
  1121.     }
  1122.     # now delete from the screen
  1123.     set length [expr $childcount + 1]
  1124.     set stop [expr $index + $childcount]
  1125.     set mainscreen_db [lreplace $mainscreen_db $index $stop]
  1126.     set start [expr $index - 1]
  1127.     mag_delete_mainlist $start $length
  1128.     # just reset current selected item
  1129.     set length [llength $mainscreen_db]
  1130.     if {$length == $index} {
  1131.         set select $start
  1132.     } else {
  1133.         set select $index
  1134.     }
  1135.     mag_display_mainlist $start [expr $start + 1] $select
  1136.     # check if current container needs to be redrawn,
  1137.     # last item is channel attribute
  1138.     set list [lindex $mainscreen_db $select]
  1139.     if {$select == $start && [lindex $list $MS(level)] == 2} {
  1140.         set start [mai_ch_find $select]
  1141.         mag_display_mainlist $start [expr $select + 1] -1
  1142.     }
  1143. }
  1144. proc \
  1145. mai_expand { index } \
  1146. {
  1147.     global mainscreen_db MS
  1148.     set list [lindex $mainscreen_db $index]
  1149.     set children [mai_get_children $list]
  1150.     # set open state
  1151.     set list [lreplace $list $MS(state) $MS(state) open]
  1152.     set mainscreen_db [lreplace $mainscreen_db $index $index $list]
  1153.     # redraw open folder before insert for appropriate visual effect
  1154.     set stop [expr $index + 1]
  1155.     mag_display_mainlist $index $stop -1
  1156.     # add to mainscreen_db
  1157.     set length [llength $mainscreen_db]
  1158.     set insert [expr $index + 1]
  1159.     # yes we can "insert" after the end of a list
  1160.     set length [llength $children]
  1161.     loop i 0 $length {
  1162.         set tmplist [lindex $children $i]
  1163.         set mainscreen_db [linsert $mainscreen_db $insert $tmplist]
  1164.         set insert [expr $insert + 1]
  1165.         if {$i == 0} {
  1166.             # redraw container to add line
  1167.             set stop [expr $index + 1]
  1168.             mag_display_mainlist $index $stop -1
  1169.         }
  1170.     }
  1171.     # update screen
  1172.     mag_insert_mainlist $index $length
  1173.     # reset selected item
  1174.     mag_display_mainlist $index $index $index
  1175. }
  1176. proc \
  1177. mai_collapse { index } \
  1178. {
  1179.     global mainscreen_db MS
  1180.     # find length of collapse operation
  1181.     set length [mai_child_length $index]
  1182.     if {$length > 0} {
  1183.         set start [expr $index + 1]
  1184.         set stop [expr $start + $length - 1]
  1185.         set mainscreen_db [lreplace $mainscreen_db $start $stop]
  1186.         mag_delete_mainlist $index $length
  1187.     }
  1188.     # set closed state
  1189.     set list [lindex $mainscreen_db $index]
  1190.     set list [lreplace $list $MS(state) $MS(state) closed]
  1191.     set mainscreen_db [lreplace $mainscreen_db $index $index $list]
  1192.     # redraw container
  1193.     set stop [expr $index + 1]
  1194.     mag_display_mainlist $index $stop $index
  1195. }
  1196. proc \
  1197. mai_child_length { index } \
  1198. {
  1199.     global mainscreen_db MS
  1200.     set list [lindex $mainscreen_db $index]
  1201.     set length 0
  1202.     set level [lindex $list $MS(level)]
  1203.     set start [expr $index + 1]
  1204.     set stop [llength $mainscreen_db]
  1205.     while {$start < $stop} {
  1206.         set list [lindex $mainscreen_db $start]
  1207.         set newlevel [lindex $list $MS(level)]
  1208.         if {$newlevel <= $level} {
  1209.             break
  1210.         }
  1211.         set start [expr $start + 1]
  1212.         set length [expr $length + 1]
  1213.     }
  1214.     return $length
  1215. }
  1216. proc \
  1217. mai_get_children { object } \
  1218. {
  1219.     global mainscreen_db MS
  1220.     global MAILSPOOL INBOXNAME
  1221.     set list $object
  1222.     set class [lindex $list $MS(class)]
  1223.     set type [lindex $list $MS(type)]
  1224.     set children ""
  1225.     switch $type {
  1226.     "config" {
  1227.         set child [list property host fqdn 1 mod [mag_msg HOST] ""]
  1228.         set child [mai_prop_get $child]
  1229.         lappend children $child
  1230.         set child [list property from fromdom 1 mod [mag_msg FROM] "" ""]
  1231.         set child [mai_prop_get $child]
  1232.         lappend children $child
  1233.         set child [list property domain boolean 1 mod \
  1234.             [mag_msg DTABLE] ""]
  1235.         set child [mai_prop_get $child]
  1236.         lappend children $child
  1237.         set child [list property dtable domtable 1 mod \
  1238.             [mag_msg DTABLE_FILE] ""]
  1239.         set child [mai_prop_get $child]
  1240.         lappend children $child
  1241.     }
  1242.     "folder" {
  1243.         # folder location
  1244.         set enum [list [mag_msg FOLDER_SYSTEM] [mag_msg FOLDER_HOME] \
  1245.             [mag_msg FOLDER_CUSTOM]]
  1246.         set child [list property flocation enum 1 mod \
  1247.             [mag_msg FOLDER_LOCATION] "" $enum ""]
  1248.         set child [mai_prop_get $child]
  1249.         lappend children $child
  1250.         # folder format
  1251.         set enum [list [mag_msg FOLDER_SENDMAIL] [mag_msg FOLDER_MMDF]]
  1252.         set child [list property fformat enum 1 mod \
  1253.             [mag_msg FOLDER_FORMAT] "" $enum]
  1254.         set child [mai_prop_get $child]
  1255.         lappend children $child
  1256.         # folder sync
  1257.         set child [list property fsync boolean 1 mod \
  1258.             [mag_msg FOLDER_FSYNC] ""]
  1259.         set child [mai_prop_get $child]
  1260.         lappend children $child
  1261.         # folder checks
  1262.         set child [list property fccheck boolean 1 mod \
  1263.             [mag_msg FOLDER_CCHECK] ""]
  1264.         set child [mai_prop_get $child]
  1265.         lappend children $child
  1266.         # folders incore
  1267.         set child [list property fincore boolean 1 mod \
  1268.             [mag_msg FOLDER_INCORE] ""]
  1269.         set child [mai_prop_get $child]
  1270.         lappend children $child
  1271.         # expunge threshold
  1272.         set range [list 0 100]
  1273.         set child [list property fthreshold intrange 1 mod \
  1274.             [mag_msg FOLDER_THRESHOLD] "" $range]
  1275.         set child [mai_prop_get $child]
  1276.         lappend children $child
  1277.         # lock timeout
  1278.         set range [list 1 999]
  1279.         set child [list property ftimeout intrange 1 mod \
  1280.             [mag_msg FOLDER_TIMEOUT] "" $range]
  1281.         set child [mai_prop_get $child]
  1282.         lappend children $child
  1283.         # file based locking
  1284.         set child [list property ffilelock boolean 1 mod \
  1285.             [mag_msg FOLDER_FILELOCK] ""]
  1286.         set child [mai_prop_get $child]
  1287.         lappend children $child
  1288.         # umask
  1289.         set child [list property fumask umask 1 mod \
  1290.             [mag_msg FOLDER_UMASK] ""]
  1291.         set child [mai_prop_get $child]
  1292.         lappend children $child
  1293.     }
  1294.     "alias" {
  1295.         set aliases [ma_aliases_get]
  1296.         set action [list mov del mod]
  1297.         foreach i $aliases {
  1298.             set test [csubstr $i 0 4]
  1299.             if {"$test" == "nis:"} {
  1300.                 set label [mag_msg MAP]
  1301.             } else {
  1302.                 set label [mag_msg FILE]
  1303.             }
  1304.             set child [list property alias alias 1 $action \
  1305.                 $label $i]
  1306.             lappend children $child
  1307.         }
  1308.     }
  1309.     "altname" {
  1310.         set alternates [ma_alternate_names_get]
  1311.         set action [list mov del mod]
  1312.         foreach i $alternates {
  1313.             set child [list property altname fqdn 1 $action \
  1314.                 [mag_msg ALTERNATE] $i]
  1315.             lappend children $child
  1316.         }
  1317.     }
  1318.     "channels" {
  1319.         set channels [mai_ch_names_get]
  1320.         # default action list
  1321.         set action1 [list mov del]
  1322.         # bad user channel does not have "mov" action
  1323.         set action2 [list del]
  1324.         foreach i $channels {
  1325.             set chtable [ma_ch_table_type_get $i]
  1326.             if {"$chtable" != "baduser"} {
  1327.                 set action $action1
  1328.             } else {
  1329.                 set action $action2
  1330.             }
  1331.             set child [list container $i channel 1 $action \
  1332.                 "" closed]
  1333.             set child [mai_prop_get $child]
  1334.             lappend children $child
  1335.         }
  1336.     }
  1337.     "channel" {
  1338.         set chname [lindex $list $MS(name)]
  1339.         # channel name
  1340.         set child [list property cname rstring 2 mod \
  1341.             [mag_msg CH_NAME] "" "" $chname]
  1342.         set child [mai_prop_get $child]
  1343.         lappend children $child
  1344.         # program name
  1345.         set child [list property cprogram chpath 2 mod \
  1346.             [mag_msg CH_PROGRAM] "" "" $chname]
  1347.         set child [mai_prop_get $child]
  1348.         lappend children $child
  1349.         # program arguments
  1350.         set child [list property cargs string 2 mod \
  1351.             [mag_msg CH_ARGS] "" "" $chname]
  1352.         set child [mai_prop_get $child]
  1353.         lappend children $child
  1354.         # channel program directory
  1355.         set child [list property cdir path 2 mod \
  1356.             [mag_msg CH_PROGDIR] "" "" $chname]
  1357.         set child [mai_prop_get $child]
  1358.         lappend children $child
  1359.         # channel table type
  1360.         set enum [mag_table_enum]
  1361.         set child [list property ctable enum 2 mod \
  1362.             [mag_msg CH_TABLE] "" $enum $chname]
  1363.         set child [mai_prop_get $child]
  1364.         lappend children $child
  1365.         # channel file
  1366.         set child [list property cfile chtable 2 mod \
  1367.             [mag_msg CH_FILE] "" "" $chname]
  1368.         set child [mai_prop_get $child]
  1369.         lappend children $child
  1370.         # channel host
  1371.         set child [list property chost ofqdn 2 mod \
  1372.             [mag_msg CH_HOST] "" "" $chname]
  1373.         set child [mai_prop_get $child]
  1374.         lappend children $child
  1375.         # channel flags
  1376.         set child [list property cflags flags 2 mod \
  1377.             [mag_msg CH_FLAGS] "" "" $chname]
  1378.         set child [mai_prop_get $child]
  1379.         lappend children $child
  1380.         # channel EOL
  1381.         set child [list property ceol rstring 2 mod \
  1382.             [mag_msg CH_EOL] "" "" $chname]
  1383.         set child [mai_prop_get $child]
  1384.         lappend children $child
  1385.         # channel max msg size
  1386.         set range [list 0 2000000000]
  1387.         set child [list property cmaxmsg ointrange 2 mod \
  1388.             [mag_msg CH_MAXMSG] "" $range $chname]
  1389.         set child [mai_prop_get $child]
  1390.         lappend children $child
  1391.         # channel max line size
  1392.         set range [list 0 10000]
  1393.         set child [list property cmaxline ointrange 2 mod \
  1394.             [mag_msg CH_MAXLINE] "" $range $chname]
  1395.         set child [mai_prop_get $child]
  1396.         lappend children $child
  1397.         # channel program nice value
  1398.         set range [list -20 20]
  1399.         set child [list property cnice intrange 2 mod \
  1400.             [mag_msg CH_NICE] "" $range $chname]
  1401.         set child [mai_prop_get $child]
  1402.         lappend children $child
  1403.         # channel user
  1404.         set child [list property cuser user 2 mod \
  1405.             [mag_msg CH_USER] "" "" $chname]
  1406.         set child [mai_prop_get $child]
  1407.         lappend children $child
  1408.         # channel group
  1409.         set child [list property cgroup group 2 mod \
  1410.             [mag_msg CH_GROUP] "" "" $chname]
  1411.         set child [mai_prop_get $child]
  1412.         lappend children $child
  1413.         # recipient envelope ruleset
  1414.         set child [list property crecip ruleset 2 mod \
  1415.             [mag_msg CH_RECIP] "" "" $chname]
  1416.         set child [mai_prop_get $child]
  1417.         lappend children $child
  1418.         # recipient header ruleset
  1419.         set child [list property chrecip ruleset 2 mod \
  1420.             [mag_msg CH_HRECIP] "" "" $chname]
  1421.         set child [mai_prop_get $child]
  1422.         lappend children $child
  1423.         # sender envelope ruleset
  1424.         set child [list property csender ruleset 2 mod \
  1425.             [mag_msg CH_SENDER] "" "" $chname]
  1426.         set child [mai_prop_get $child]
  1427.         lappend children $child
  1428.         # sender header ruleset
  1429.         set child [list property chsender ruleset 2 mod \
  1430.             [mag_msg CH_HSENDER] "" "" $chname]
  1431.         set child [mai_prop_get $child]
  1432.         lappend children $child
  1433.     }
  1434.     }
  1435.     return $children
  1436. }
  1437. proc \
  1438. mai_ch_names_get {} \
  1439. {
  1440.     set list [ma_ch_names_get]
  1441.     set order ""
  1442.     foreach i $list {
  1443.         lappend order [ma_ch_sequence_get $i]
  1444.     }
  1445.     set sorted ""
  1446.     set length [llength $list]
  1447.     loop i 0 $length {
  1448.         # find the appropriate one in order
  1449.         loop j 0 $length {
  1450.             set item [lindex $order $j]
  1451.             if {$item == $i} {
  1452.                 lappend sorted [lindex $list $j]
  1453.                 break
  1454.             }
  1455.         }
  1456.     }
  1457.     return $sorted
  1458. }
  1459. proc \
  1460. mai_prop_def { object } \
  1461. {
  1462.     global mainscreen_db MS
  1463.     global MAILSPOOL INBOXNAME MAILTABLE MQUEUE UUX
  1464.     global MDOMAINDB
  1465.     global mag_host_name
  1466.     set list $object
  1467.     set class [lindex $list $MS(class)]
  1468.     set name [lindex $list $MS(name)]
  1469.     switch $name {
  1470.     "host" {
  1471.         set value $mag_host_name
  1472.     }
  1473.     "from" {
  1474.         set value $mag_host_name
  1475.     }
  1476.     "domain" {
  1477.         set value [mag_num_to_bool 0]
  1478.     }
  1479.     "dtable" {
  1480.         # does nothing, keep original value
  1481.         set value [lindex $list $MS(value)]
  1482.     }
  1483.     }
  1484.     # folder properties
  1485.     switch $name {
  1486.     "flocation" {
  1487.         set value [mag_msg FOLDER_SYSTEM]
  1488.         set custom [list $MAILSPOOL ""]
  1489.         set list [lreplace $list $MS(custom) $MS(custom) $custom]
  1490.     }
  1491.     "fformat" {
  1492.         set value [mag_msg FOLDER_SENDMAIL]
  1493.     }
  1494.     "fsync" {
  1495.         set value [mag_num_to_bool 0]
  1496.     }
  1497.     "fccheck" {
  1498.         set value [mag_num_to_bool 0]
  1499.     }
  1500.     "fincore" {
  1501.         set value [mag_num_to_bool 0]
  1502.     }
  1503.     "fthreshold" {
  1504.         set value 50
  1505.     }
  1506.     "ftimeout" {
  1507.         set value 10
  1508.     }
  1509.     "ffilelock" {
  1510.         set value [mag_num_to_bool 0]
  1511.     }
  1512.     "fumask" {
  1513.         set value "077"
  1514.     }
  1515.     }
  1516.     # alias and altname properties
  1517.     switch $name {
  1518.     "alias" {
  1519.         set value [lindex $list $MS(value)]
  1520.     }
  1521.     "altname" {
  1522.         set value [lindex $list $MS(value)]
  1523.     }
  1524.     }
  1525.     # if a channel property, get channel name from backlink
  1526.     if {[catch {set tmp $value}] != 0} {
  1527.         set chname [lindex $list $MS(chname)]
  1528.         set chprogram [ma_ch_equate_get $chname P]
  1529.         if {"$chprogram" == "\[IPC\]"} {
  1530.             set chprogram SMTP
  1531.         }
  1532.         set chtable [ma_ch_table_type_get $chname]
  1533.     }
  1534.     # channel properties with no defaults
  1535.     switch $name {
  1536.     "cname" {
  1537.         set value [lindex $list $MS(value)]
  1538.     }
  1539.     "cprogram" {
  1540.         set value $chprogram
  1541.     }
  1542.     "ctable" {
  1543.         set value [mag_table_to_external $chtable]
  1544.     }
  1545.     }
  1546.     # channel properties with defaults based upon the above values
  1547.     switch $name {
  1548.     "cargs" {
  1549.         set prog $chprogram
  1550.         # default value
  1551.         set base [exec basename $prog]
  1552.         set value "$base \$u"
  1553.         # special cases
  1554.         switch $base {
  1555.         "SMTP" {
  1556.             set value "IPC \$h"
  1557.         }
  1558.         "uux" {
  1559.             set value "uux - -r -a\$f -gmedium \$h!rmail (\$u)"
  1560.         }
  1561.         "slocal" {
  1562.             set value "slocal \$u"
  1563.         }
  1564.         }
  1565.     }
  1566.     "cdir" {
  1567.         set value $MQUEUE
  1568.     }
  1569.     "cfile" {
  1570.         # note that the file is not renamed
  1571.         if {"[exec basename $chprogram]" == "multihome"} {
  1572.             set value $MDOMAINDB
  1573.         } elseif {"$chtable" == "file"} {
  1574.             set value "$MAILTABLE/$chname"
  1575.         } else {
  1576.             set value ""
  1577.         }
  1578.     }
  1579.     "chost" {
  1580.         set value [mag_msg NONE]
  1581.     }
  1582.     "cflags" {
  1583.         # custom same as SMTP
  1584.         set value "mlsDFMPeu8"
  1585.         switch [exec basename $chprogram] {
  1586.         "SMTP" {
  1587.             set value "mlsDFMPeu8"
  1588.         }
  1589.         "uux" {
  1590.             set value "mDFMhuU8"
  1591.         }
  1592.         "slocal" {
  1593.             set value "lsDFMPhoAw5:|/@8"
  1594.         }
  1595.         }
  1596.     }
  1597.     "ceol" {
  1598.         if {"$chprogram" == "SMTP"} {
  1599.             set value "\\r\\n"
  1600.         } else {
  1601.             set value "\\n"
  1602.         }
  1603.     }
  1604.     "cmaxmsg" {
  1605.         if {"[exec basename $chprogram]" == "uux"} {
  1606.             set value 100000
  1607.         } else {
  1608.             #set value [mag_msg NONE]
  1609.             set value 20000000
  1610.         }
  1611.     }
  1612.     "cmaxline" {
  1613.         if {"$chprogram" == "SMTP"} {
  1614.             set value 990
  1615.         } else {
  1616.             set value [mag_msg NONE]
  1617.         }
  1618.     }
  1619.     "cnice" {
  1620.         set value 0
  1621.     }
  1622.     "cuser" {
  1623.         set value [mag_msg DEFAULT]
  1624.     }
  1625.     "cgroup" {
  1626.         set value [mag_msg DEFAULT]
  1627.     }
  1628.     "crecip" {
  1629.         set value ap822_re
  1630.         switch [exec basename $chprogram] {
  1631.         "SMTP" {
  1632.             set value ap822_re
  1633.         }
  1634.         "uux" {
  1635.             set value ap976_re
  1636.         }
  1637.         "slocal" {
  1638.             set value aplocal_re
  1639.         }
  1640.         }
  1641.     }
  1642.     "chrecip" {
  1643.         set value ap822_rh
  1644.         switch [exec basename $chprogram] {
  1645.         "SMTP" {
  1646.             set value ap822_rh
  1647.         }
  1648.         "uux" {
  1649.             set value ap976_rh
  1650.         }
  1651.         "slocal" {
  1652.             set value aplocal_rh
  1653.         }
  1654.         }
  1655.     }
  1656.     "csender" {
  1657.         set value ap822_se
  1658.         switch [exec basename $chprogram] {
  1659.         "SMTP" {
  1660.             set value ap822_se
  1661.         }
  1662.         "uux" {
  1663.             set value ap976_se
  1664.         }
  1665.         "slocal" {
  1666.             set value aplocal_se
  1667.         }
  1668.         }
  1669.     }
  1670.     "chsender" {
  1671.         set value ap822_sh
  1672.         switch [exec basename $chprogram] {
  1673.         "SMTP" {
  1674.             set value ap822_sh
  1675.         }
  1676.         "uux" {
  1677.             set value ap976_sh
  1678.         }
  1679.         "slocal" {
  1680.             set value aplocal_sh
  1681.         }
  1682.         }
  1683.     }
  1684.     }
  1685.     set list [lreplace $list $MS(value) $MS(value) $value]
  1686.     return $list
  1687. }
  1688. proc \
  1689. mai_prop_get { object } \
  1690. {
  1691.     global mainscreen_db MS mag_host_name
  1692.     global MAILSPOOL INBOXNAME MAILTABLE MQUEUE
  1693.     set list $object
  1694.     set class [lindex $list $MS(class)]
  1695.     set name [lindex $list $MS(name)]
  1696.     set type [lindex $list $MS(type)]
  1697.     switch $name {
  1698.     "host" {
  1699.         set value [ma_machine_name_get]
  1700.         if {"$value" == ""} {
  1701.             set value $mag_host_name
  1702.         }
  1703.     }
  1704.     "from" {
  1705.         set value [ma_from_domain_get]
  1706.         if {"$value" == ""} {
  1707.             set value $mag_host_name
  1708.         }
  1709.     }
  1710.     "domain" {
  1711.         set value [mag_num_to_bool [ma_domain_table_enabled_get]]
  1712.     }
  1713.     "dtable" {
  1714.         set value [ma_domain_table_file_get]
  1715.     }
  1716.     }
  1717.     # folder properties
  1718.     switch $name {
  1719.     "flocation" {
  1720.         set dir [ma_ms1_get MS1_INBOX_DIR]
  1721.         set name [ma_ms1_get MS1_INBOX_NAME]
  1722.         set value [mag_msg FOLDER_CUSTOM]
  1723.         if {"$dir" == "$MAILSPOOL" && "$name" == ""} {
  1724.             set value [mag_msg FOLDER_SYSTEM]
  1725.         }
  1726.         if {"$dir" == "" && "$name" == "$INBOXNAME"} {
  1727.             set value [mag_msg FOLDER_HOME]
  1728.         }
  1729.         set tmplist [list $dir $name]
  1730.         set list [lreplace $list \
  1731.             $MS(custom) $MS(custom) $tmplist]
  1732.     }
  1733.     "fformat" {
  1734.         set tmp [ma_ms1_get MS1_FOLDER_FORMAT]
  1735.         if {"$tmp" == "Sendmail"} {
  1736.             set value [mag_msg FOLDER_SENDMAIL]
  1737.         }
  1738.         if {"$tmp" == "MMDF"} {
  1739.             set value [mag_msg FOLDER_MMDF]
  1740.         }
  1741.     }
  1742.     "fsync" {
  1743.         set value [mag_string_to_bool [ma_ms1_get MS1_FSYNC]]
  1744.     }
  1745.     "fccheck" {
  1746.         set value [mag_string_to_bool [ma_ms1_get MS1_EXTENDED_CHECKS]]
  1747.     }
  1748.     "fincore" {
  1749.         set value [mag_string_to_bool [ma_ms1_get MS1_FOLDERS_INCORE]]
  1750.     }
  1751.     "fthreshold" {
  1752.         set value [ma_ms1_get MS1_EXPUNGE_THRESHOLD]
  1753.     }
  1754.     "ftimeout" {
  1755.         set value [ma_ms1_get MS1_LOCK_TIMEOUT]
  1756.     }
  1757.     "ffilelock" {
  1758.         set value [mag_string_to_bool [ma_ms1_get MS1_FILE_LOCKING]]
  1759.     }
  1760.     "fumask" {
  1761.         set value [ma_ms1_get MS1_UMASK]
  1762.     }
  1763.     }
  1764.     if {"$type" == "channel"} {
  1765.         # a channel container, special work here
  1766.         # here the label rather than the value is changed
  1767.         set chname [lindex $list $MS(name)]
  1768.         set label [mag_channel_to_alias $chname]
  1769.         set list [lreplace $list $MS(label) $MS(label) $label]
  1770.         return $list
  1771.     }
  1772.     # is a channel property, get chname
  1773.     set chname [lindex $list $MS(chname)]
  1774.     switch $name {
  1775.     "cname" {
  1776.         set value [mag_channel_to_alias $chname]
  1777.     }
  1778.     "cprogram" {
  1779.         set value [ma_ch_equate_get $chname P]
  1780.         if {"$value" == "\[IPC\]"} {
  1781.             set value SMTP
  1782.         }
  1783.     }
  1784.     "cargs" {
  1785.         set value [ma_ch_equate_get $chname A]
  1786.     }
  1787.     "cdir" {
  1788.         set value [ma_ch_equate_get $chname D]
  1789.         if {"$value" == ""} {
  1790.             set value $MQUEUE
  1791.         }
  1792.     }
  1793.     "ctable" {
  1794.         set value [ma_ch_table_type_get $chname]
  1795.         set value [mag_table_to_external $value]
  1796.     }
  1797.     "cfile" {
  1798.         set value [ma_ch_table_file_get $chname]
  1799.     }
  1800.     "chost" {
  1801.         set value [ma_ch_host_get $chname]
  1802.         if {"$value" == ""} {
  1803.             set value [mag_msg NONE]
  1804.         }
  1805.     }
  1806.     "cflags" {
  1807.         set value [ma_ch_equate_get $chname F]
  1808.     }
  1809.     "ceol" {
  1810.         set value [ma_ch_equate_get $chname E]
  1811.         if {"$value" == ""} {
  1812.             set value "\\n"
  1813.         }
  1814.     }
  1815.     "cmaxmsg" {
  1816.         set value [ma_ch_equate_get $chname M]
  1817.         if {"$value" == ""} {
  1818.             set value [mag_msg NONE]
  1819.         }
  1820.     }
  1821.     "cmaxline" {
  1822.         set value [ma_ch_equate_get $chname L]
  1823.         if {"$value" == ""} {
  1824.             set value [mag_msg NONE]
  1825.         }
  1826.     }
  1827.     "cnice" {
  1828.         set value [ma_ch_equate_get $chname N]
  1829.         if {"$value" == ""} {
  1830.             set value 0
  1831.         }
  1832.     }
  1833.     "cuser" {
  1834.         set both [ma_ch_equate_get $chname U]
  1835.         if {"$both" == ""} {
  1836.             set value [mag_msg DEFAULT]
  1837.         } else {
  1838.             set tmplist [split $both ":"]
  1839.             set value [lindex $tmplist 0]
  1840.         }
  1841.     }
  1842.     "cgroup" {
  1843.         set both [ma_ch_equate_get $chname U]
  1844.         if {"$both" == ""} {
  1845.             set value [mag_msg DEFAULT]
  1846.         } else {
  1847.             set tmplist [split $both ":"]
  1848.             set value [lindex $tmplist 1]
  1849.             if {"$value" == ""} {
  1850.                 set value [mag_msg DEFAULT]
  1851.             }
  1852.         }
  1853.     }
  1854.     "crecip" {
  1855.         set recip [ma_ch_equate_get $chname R]
  1856.         set reciplist [split $recip "/"]
  1857.         set value [lindex $reciplist 0]
  1858.         if {"$value" == "" || "$value" == "0"} {
  1859.             set value [mag_msg NONE]
  1860.         }
  1861.     }
  1862.     "chrecip" {
  1863.         set recip [ma_ch_equate_get $chname R]
  1864.         set reciplist [split $recip "/"]
  1865.         set value [lindex $reciplist 1]
  1866.         if {"$value" == "" || "$value" == "0"} {
  1867.             set value [mag_msg RULEDEF]
  1868.         }
  1869.     }
  1870.     "csender" {
  1871.         set sender [ma_ch_equate_get $chname S]
  1872.         set senderlist [split $sender "/"]
  1873.         set value [lindex $senderlist 0]
  1874.         if {"$value" == "" || "$value" == "0"} {
  1875.             set value [mag_msg NONE]
  1876.         }
  1877.     }
  1878.     "chsender" {
  1879.         set sender [ma_ch_equate_get $chname S]
  1880.         set senderlist [split $sender "/"]
  1881.         set value [lindex $senderlist 1]
  1882.         if {"$value" == "" || "$value" == "0"} {
  1883.             set value [mag_msg RULEDEF]
  1884.         }
  1885.     }
  1886.     }
  1887.     set list [lreplace $list $MS(value) $MS(value) $value]
  1888.     return $list
  1889. }
  1890. proc \
  1891. mai_prop_set { oldobject newobject } \
  1892. {
  1893.     global mainscreen_db MS mag_host_name
  1894.     global MAILSPOOL INBOXNAME MAILTABLE MQUEUE
  1895.     set list $newobject
  1896.     set class [lindex $list $MS(class)]
  1897.     set name [lindex $list $MS(name)]
  1898.     set value [lindex $list $MS(value)]
  1899.     switch $name {
  1900.     "host" {
  1901.         if {"$value" == "$mag_host_name"} {
  1902.             set value ""
  1903.         }
  1904.         ma_machine_name_set $value
  1905.         set set ok
  1906.     }
  1907.     "from" {
  1908.         if {"$value" == "$mag_host_name"} {
  1909.             set value ""
  1910.         }
  1911.         ma_from_domain_set $value
  1912.         set set ok
  1913.     }
  1914.     "domain" {
  1915.         ma_domain_table_enabled_set [mag_bool_to_num $value]
  1916.         set set ok
  1917.     }
  1918.     "dtable" {
  1919.         # does nothing
  1920.         set set ok
  1921.     }
  1922.     }
  1923.     # have to remove old name, put in new name, preserve order
  1924.     # no check for name conflicts yet
  1925.     if {"$name" == "alias" || "$name" == "altname"} {
  1926.         set oldname [lindex $oldobject $MS(value)]
  1927.         set newname $value
  1928.         # get old list
  1929.         switch "$name" {
  1930.         "alias" {
  1931.             set tmplist [ma_aliases_get]
  1932.         }
  1933.         "altname" {
  1934.             set tmplist [ma_alternate_names_get]
  1935.         }
  1936.         }
  1937.         # replace item
  1938.         set index [lsearch $tmplist $oldname]
  1939.         set tmplist [lreplace $tmplist $index $index $newname]
  1940.         switch "$name" {
  1941.         "alias" {
  1942.             set tmplist [ma_aliases_set $tmplist]
  1943.         }
  1944.         "altname" {
  1945.             set tmplist [ma_alternate_names_set $tmplist]
  1946.         }
  1947.         }
  1948.         set set ok
  1949.     }
  1950.     # folder properties
  1951.     switch $name {
  1952.     "flocation" {
  1953.         if {"$value" == "[mag_msg FOLDER_SYSTEM]"} {
  1954.             ma_ms1_set MS1_INBOX_DIR $MAILSPOOL
  1955.             ma_ms1_set MS1_INBOX_NAME ""
  1956.             set set ok
  1957.         }
  1958.         if {"$value" == "[mag_msg FOLDER_HOME]"} {
  1959.             ma_ms1_set MS1_INBOX_DIR ""
  1960.             ma_ms1_set MS1_INBOX_NAME $INBOXNAME
  1961.             set set ok
  1962.         }
  1963.         # use custom spot for custom values
  1964.         if {"$value" == "[mag_msg FOLDER_CUSTOM]"} {
  1965.             set tmplist [lindex $list $MS(custom)]
  1966.             ma_ms1_set MS1_INBOX_DIR [lindex $tmplist 0]
  1967.             ma_ms1_set MS1_INBOX_NAME [lindex $tmplist 1]
  1968.             set set ok
  1969.         }
  1970.     }
  1971.     "fformat" {
  1972.         if {"$value" == "[mag_msg FOLDER_SENDMAIL]"} {
  1973.             ma_ms1_set MS1_FOLDER_FORMAT Sendmail
  1974.             set set ok
  1975.         }
  1976.         if {"$value" == "[mag_msg FOLDER_MMDF]"} {
  1977.             ma_ms1_set MS1_FOLDER_FORMAT MMDF
  1978.             set set ok
  1979.         }
  1980.     }
  1981.     "fsync" {
  1982.         ma_ms1_set MS1_FSYNC [mag_bool_to_string $value]
  1983.         set set ok
  1984.     }
  1985.     "fccheck" {
  1986.         ma_ms1_set MS1_EXTENDED_CHECKS [mag_bool_to_string $value]
  1987.         set set ok
  1988.     }
  1989.     "fincore" {
  1990.         ma_ms1_set MS1_FOLDERS_INCORE [mag_bool_to_string $value]
  1991.         set set ok
  1992.     }
  1993.     "fthreshold" {
  1994.         ma_ms1_set MS1_EXPUNGE_THRESHOLD $value
  1995.         set set ok
  1996.     }
  1997.     "ftimeout" {
  1998.         ma_ms1_set MS1_LOCK_TIMEOUT $value
  1999.         set set ok
  2000.     }
  2001.     "ffilelock" {
  2002.         ma_ms1_set MS1_FILE_LOCKING [mag_bool_to_string $value]
  2003.         set set ok
  2004.     }
  2005.     "fumask" {
  2006.         ma_ms1_set MS1_UMASK $value
  2007.         set set ok
  2008.     }
  2009.     }
  2010.     # is a channel property, get chname
  2011.     set chname [lindex $list $MS(chname)]
  2012.     switch $name {
  2013.     "cname" {
  2014.         set newvalue [mag_channel_to_internal $value]
  2015.         set oldvalue [lindex $oldobject $MS(chname)]
  2016.         # rename channel
  2017.         set set [ma_ch_rename $oldvalue $newvalue]
  2018.         if {"$set" != "ok"} {
  2019.             # return error code if one.
  2020.             set newobject $set
  2021.         } else {
  2022.             # set new name in channel-name object
  2023.             # the alias has already been set
  2024.             set newobject [lreplace $newobject \
  2025.                 $MS(chname) $MS(chname) $newvalue]
  2026.         }
  2027.     }
  2028.     "cprogram" {
  2029.         if {"$value" == "SMTP"} {
  2030.             set value "\[IPC\]"
  2031.         }
  2032.         ma_ch_equate_set $chname P $value
  2033.         set set ok
  2034.     }
  2035.     "cargs" {
  2036.         ma_ch_equate_set $chname A $value
  2037.         set set ok
  2038.     }
  2039.     "cdir" {
  2040.         if {"$value" == "$MQUEUE"} {
  2041.             set value ""
  2042.         }
  2043.         ma_ch_equate_set $chname D $value
  2044.         set set ok
  2045.     }
  2046.     "ctable" {
  2047.         ma_ch_table_type_set $chname [mag_table_to_internal $value]
  2048.         set set ok
  2049.     }
  2050.     "cfile" {
  2051.         ma_ch_table_file_set $chname $value
  2052.         set set ok
  2053.     }
  2054.     "chost" {
  2055.         if {"$value" == "[mag_msg NONE]"} {
  2056.             set value ""
  2057.         }
  2058.         ma_ch_host_set $chname $value
  2059.         set set ok
  2060.     }
  2061.     "cflags" {
  2062.         ma_ch_equate_set $chname F $value
  2063.         set set ok
  2064.     }
  2065.     "ceol" {
  2066.         if {"$value" == "\\n"} {
  2067.             set value ""
  2068.         }
  2069.         ma_ch_equate_set $chname E $value
  2070.         set set ok
  2071.     }
  2072.     "cmaxmsg" {
  2073.         if {"$value" == "[mag_msg NONE]"} {
  2074.             set value ""
  2075.         }
  2076.         ma_ch_equate_set $chname M $value
  2077.         set set ok
  2078.     }
  2079.     "cmaxline" {
  2080.         if {"$value" == "[mag_msg NONE]"} {
  2081.             set value ""
  2082.         }
  2083.         ma_ch_equate_set $chname L $value
  2084.         set set ok
  2085.     }
  2086.     "cnice" {
  2087.         if {$value == 0} {
  2088.             set value ""
  2089.         }
  2090.         ma_ch_equate_set $chname N $value
  2091.         set set ok
  2092.     }
  2093.     "cuser" {
  2094.         if {"$value" == "[mag_msg DEFAULT]"} {
  2095.             set value ""
  2096.         }
  2097.         set both [ma_ch_equate_get $chname U]
  2098.         set tmplist [split $both ":"]
  2099.         set user [lindex $tmplist 0]
  2100.         set group [lindex $tmplist 1]
  2101.         if {"$value" == ""} {
  2102.             set group ""
  2103.         }
  2104.         if {"$group" != ""} {
  2105.             set both "$value:$group"
  2106.         } else {
  2107.             set both $value
  2108.         }
  2109.         ma_ch_equate_set $chname U $both
  2110.         set set ok
  2111.     }
  2112.     "cgroup" {
  2113.         if {"$value" == "[mag_msg DEFAULT]"} {
  2114.             set value ""
  2115.         }
  2116.         set both [ma_ch_equate_get $chname U]
  2117.         set tmplist [split $both ":"]
  2118.         set user [lindex $tmplist 0]
  2119.         set group [lindex $tmplist 1]
  2120.         # assume user is set first
  2121.         if {"$value" != ""} {
  2122.             set both "$user:$value"
  2123.         } else {
  2124.             set both $user
  2125.         }
  2126.         ma_ch_equate_set $chname U $both
  2127.         set set ok
  2128.     }
  2129.     "crecip" {
  2130.         set recip [ma_ch_equate_get $chname R]
  2131.         set reciplist [split $recip "/"]
  2132.         set env [lindex $reciplist 0]
  2133.         set hdr [lindex $reciplist 1]
  2134.         set env $value
  2135.         if {"$value" == "[mag_msg NONE]"} {
  2136.             set env ""
  2137.         }
  2138.         set value [mag_build_ruleset $env $hdr]
  2139.         ma_ch_equate_set $chname R $value
  2140.         set set ok
  2141.     }
  2142.     "chrecip" {
  2143.         set recip [ma_ch_equate_get $chname R]
  2144.         set reciplist [split $recip "/"]
  2145.         set env [lindex $reciplist 0]
  2146.         set hdr [lindex $reciplist 1]
  2147.         set hdr $value
  2148.         if {"$value" == "[mag_msg RULEDEF]"} {
  2149.             set hdr ""
  2150.         }
  2151.         set value [mag_build_ruleset $env $hdr]
  2152.         ma_ch_equate_set $chname R $value
  2153.         set set ok
  2154.     }
  2155.     "csender" {
  2156.         set sender [ma_ch_equate_get $chname S]
  2157.         set senderlist [split $sender "/"]
  2158.         set env [lindex $senderlist 0]
  2159.         set hdr [lindex $senderlist 1]
  2160.         set env $value
  2161.         if {"$value" == "[mag_msg NONE]"} {
  2162.             set env ""
  2163.         }
  2164.         set value [mag_build_ruleset $env $hdr]
  2165.         ma_ch_equate_set $chname S $value
  2166.         set set ok
  2167.     }
  2168.     "chsender" {
  2169.         set sender [ma_ch_equate_get $chname S]
  2170.         set senderlist [split $sender "/"]
  2171.         set env [lindex $senderlist 0]
  2172.         set hdr [lindex $senderlist 1]
  2173.         set hdr $value
  2174.         if {"$value" == "[mag_msg RULEDEF]"} {
  2175.             set hdr ""
  2176.         }
  2177.         set value [mag_build_ruleset $env $hdr]
  2178.         ma_ch_equate_set $chname S $value
  2179.         set set ok
  2180.     }
  2181.     }
  2182.     return $newobject
  2183. }
  2184. proc \
  2185. mai_ch_find { index } \
  2186. {
  2187.     global mainscreen_db MS
  2188.     loop i $index 0 -1 {
  2189.         set list [lindex $mainscreen_db $i]
  2190.         set class [lindex $list $MS(class)]
  2191.         if {"$class" == "container"} {
  2192.             return $i
  2193.         }
  2194.     }
  2195. }
  2196. proc \
  2197. mai_prop_find { index name } \
  2198. {
  2199.     global mainscreen_db MS
  2200.     set start [expr $index + 1]
  2201.     set stop [llength $mainscreen_db]
  2202.     loop i $start $stop {
  2203.         set list [lindex $mainscreen_db $i]
  2204.         set class [lindex $list $MS(class)]
  2205.         set tmpname [lindex $list $MS(name)]
  2206.         if {"$tmpname" == "$name"} {
  2207.             return $i
  2208.         }
  2209.     }
  2210. }
  2211. proc \
  2212. mai_modify { index } \
  2213. {
  2214.     global mainscreen_db DIRTY MS
  2215.     set object [lindex $mainscreen_db $index]
  2216.     set newobject [mai_pre $object $index]
  2217.     if {"$newobject" == ""} {
  2218.         return no
  2219.     }
  2220.     set newobject [mai_edit $newobject]
  2221.     if {"$newobject" == ""} {
  2222.         return no
  2223.     }
  2224.     set newobject [mai_post $newobject $index]
  2225.     if {"$newobject" == ""} {
  2226.         return no
  2227.     }
  2228.     if {"$object" != "$newobject"} {
  2229.         set DIRTY 1
  2230.         set value [lindex $newobject $MS(value)]
  2231.         set newobject [mai_prop_set $object $newobject]
  2232.         switch "$newobject" {
  2233.         "conflict" {
  2234.             VtUnLock
  2235.             mag_error CONFLICT
  2236.             VtLock
  2237.             return no
  2238.         }
  2239.         "badname" {
  2240.             VtUnLock
  2241.             mag_error1 INVALID $value
  2242.             VtLock
  2243.             return no
  2244.         }
  2245.         }
  2246.         set mainscreen_db [lreplace $mainscreen_db $index $index $newobject]
  2247.         # redraw main screen
  2248.         set stop [expr $index + 1]
  2249.         mag_display_mainlist $index $stop $index
  2250.         mai_state $object $newobject $index
  2251.     }
  2252.     return yes
  2253. }
  2254. proc \
  2255. mai_pre { object index } \
  2256. {
  2257.     global mainscreen_db MS
  2258.     set type [lindex $object $MS(type)]
  2259.     set value [lindex $object $MS(value)]
  2260.     set name [lindex $object $MS(name)]
  2261.     switch "$type" {
  2262.     "chtable" {
  2263.         # cannot edit if channel not of type table.
  2264.         set chindex [mai_ch_find $index]
  2265.         # find channel table type
  2266.         set ctindex [mai_prop_find $chindex ctable]
  2267.         set tmpobject [lindex $mainscreen_db $ctindex]
  2268.         set ctable [lindex $tmpobject $MS(value)]
  2269.         if {"$ctable" != "[mag_msg TTFILE]"} {
  2270.             VtUnLock
  2271.             mag_error FILE_ONLY
  2272.             VtLock
  2273.             return ""
  2274.         }
  2275.     }
  2276.     "group" {
  2277.         # user must be set before group can be set
  2278.         set chindex [mai_ch_find $index]
  2279.         # find channel user setting
  2280.         set ctindex [mai_prop_find $chindex cuser]
  2281.         set tmpobject [lindex $mainscreen_db $ctindex]
  2282.         set cuser [lindex $tmpobject $MS(value)]
  2283.         if {"$cuser" == "[mag_msg DEFAULT]"} {
  2284.             VtUnLock
  2285.             mag_error USER_FIRST
  2286.             VtLock
  2287.             return ""
  2288.         }
  2289.     }
  2290.     "fromdom" {
  2291.         # build enumerated list from host name
  2292.         # find host name
  2293.         set length [llength $mainscreen_db]
  2294.         loop i 0 $length {
  2295.             set tmplist [lindex $mainscreen_db $i]
  2296.             set tmpclass [lindex $tmplist $MS(class)]
  2297.             if {"$tmpclass" == "container"} {
  2298.                 continue
  2299.             }
  2300.             set tmpname  [lindex $tmplist $MS(name)]
  2301.             if {"$tmpname" == "host"} {
  2302.                 set hindex $i
  2303.                 break
  2304.             }
  2305.         }
  2306.         # build enumerated list
  2307.         set host [lindex $tmplist $MS(value)]
  2308.         set tokens [split $host "."]
  2309.         set base [lindex $tokens 0]
  2310.         set enum ""
  2311.         set length [llength $tokens]
  2312.         set length [expr $length - 1]
  2313.         loop i 0 $length {
  2314.             set itemlist "[lrange $tokens $i end]"
  2315.             set item [join $itemlist "."]
  2316.             lappend enum $item
  2317.         }
  2318.         lappend enum $base
  2319.         set object [lreplace $object $MS(criteria) $MS(criteria) $enum]
  2320.     }
  2321.     }
  2322.     return $object
  2323. }
  2324. proc \
  2325. mai_edit { object } \
  2326. {
  2327.     global ME PID mag_host_name
  2328.     # file is used to pass results to preserve stdout for child process.
  2329.     set file "/tmp/mag.$PID"
  2330.     system "rm -f $file"
  2331.     VtControl -suspend
  2332.     set escape [mag_escape $object]
  2333.     system "$ME -h $mag_host_name -mag_stand_edit \"$escape\" $file"
  2334.     VtControl -resume
  2335.     if {[file exists $file] == 1} {
  2336.         set newobject [exec cat $file]
  2337.         system "rm -f $file"
  2338.     } else {
  2339.         set newobject ""
  2340.     }
  2341.     return $newobject
  2342. }
  2343. proc \
  2344. mai_post { object index } \
  2345. {
  2346.     global mainscreen_db MS
  2347.     set oldobject [lindex $mainscreen_db $index]
  2348.     set type [lindex $object $MS(type)]
  2349.     set name [lindex $object $MS(name)]
  2350.     set value [lindex $object $MS(value)]
  2351.     set criteria [lindex $object $MS(criteria)]
  2352.     set error ""
  2353.     set arg $value
  2354.     # type checking
  2355.     switch "$type" {
  2356.     "fqdn" {
  2357.         if {"$value" == ""} {
  2358.             set error FQDN
  2359.         }
  2360.         # no blanks allowed
  2361.         if {[string first " " $value] >= 0} {
  2362.             set error FQDN
  2363.         }
  2364.     }
  2365.     "ofqdn" {
  2366.         if {"$value" == ""} {
  2367.             set value [mag_msg NONE]
  2368.             set object [lreplace $object \
  2369.                 $MS(value) $MS(value) $value]
  2370.         }
  2371.         # no blanks allowed
  2372.         if {[string first " " $value] >= 0} {
  2373.             set error FQDN
  2374.         }
  2375.     }
  2376.     "fromdom" {
  2377.         # no blanks allowed
  2378.         if {[string first " " $value] >= 0} {
  2379.             set error FQDN
  2380.         }
  2381.     }
  2382.     "intrange" {
  2383.         if {[catch {expr $value}] != 0} {
  2384.             set value "1"
  2385.             set error INTEGER
  2386.         }
  2387.         if {"$value" == ""} {
  2388.             set error NULL
  2389.             set value 1
  2390.         }
  2391.         set test [mag_trim_zero $value]
  2392.         if {"$test" != "$value"} {
  2393.             set value $test
  2394.             set arg $test
  2395.             set object [lreplace $object $MS(value) $MS(value) $value]
  2396.         }
  2397.         if {"[csubstr $value 0 1]" == "-"} {
  2398.             set test [csubstr $value 1 end]
  2399.         }
  2400.         if {[ctype digit $test] == 0} {
  2401.             set error INTEGER
  2402.         } else {
  2403.             set t1 [lindex $criteria 0]
  2404.             set t2 [lindex $criteria 1]
  2405.             if {$value < $t1 || $value > $t2} {
  2406.                 set error INTEGER
  2407.             }
  2408.         }
  2409.     }
  2410.     "ointrange" {
  2411.         if {"$value" == ""} {
  2412.             set value [mag_msg NONE]
  2413.             set object [lreplace $object $MS(value) $MS(value) $value]
  2414.         }
  2415.         if {"$value" != "[mag_msg NONE]"} {
  2416.             if {[catch {expr $value}] != 0} {
  2417.                 set value [lindex $criteria 0]
  2418.                 set error INTEGER
  2419.             }
  2420.             set test [mag_trim_zero $value]
  2421.             if {"$test" != "$value"} {
  2422.                 set value $test
  2423.                 set arg $test
  2424.                 set object [lreplace $object $MS(value) $MS(value) $value]
  2425.             }
  2426.             if {"[csubstr $value 0 1]" == "-"} {
  2427.                 set test [csubstr $value 1 end]
  2428.             }
  2429.             if {[ctype digit $test] == 0} {
  2430.                 set error INTEGER
  2431.             } else {
  2432.                 set t1 [lindex $criteria 0]
  2433.                 set t2 [lindex $criteria 1]
  2434.                 if {$value < $t1 || $value > $t2} {
  2435.                     set error INTEGER
  2436.                 }
  2437.             }
  2438.         }
  2439.     }
  2440.     "enum" {
  2441.         # check is one of the list
  2442.         if {"$value" == ""} {
  2443.             set error NULL
  2444.         } else {
  2445.             set error INVALID
  2446.             foreach i $criteria {
  2447.                 if {"$i" == "$value"} {
  2448.                     set error ""
  2449.                     break
  2450.                 }
  2451.             }
  2452.         }
  2453.     }
  2454.     "umask" {
  2455.         if {"$value" == ""} {
  2456.             set error NULL
  2457.             set value "01"
  2458.         }
  2459.         if {[ctype digit $value] == 0} {
  2460.             set error INVALID
  2461.         }
  2462.                 if {[string first 8 $value] >= 0} {
  2463.             set error INVALID
  2464.         }
  2465.         if {[string first 9 $value] >= 0} {
  2466.             set error INVALID
  2467.         }
  2468.         if {"[cindex $value 0]" != "0"} {
  2469.             set value "0$value"
  2470.             set object [lreplace $object \
  2471.                 $MS(value) $MS(value) $value]
  2472.         }
  2473.         if {"$error" == ""} {
  2474.             if {$value > 0777} {
  2475.                 set error INVALID
  2476.             }
  2477.         }
  2478.     }
  2479.     "alias" {
  2480.         if {"$value" == ""} {
  2481.             set error NULL
  2482.         } else {
  2483.             # have to modify label
  2484.             set test [csubstr $value 0 4]
  2485.             if {"$test" == "nis:"} {
  2486.                 set label [mag_msg MAP]
  2487.             } else {
  2488.                 set label [mag_msg FILE]
  2489.             }
  2490.             set object [lreplace $object \
  2491.                 $MS(label) $MS(label) $label]
  2492.         }
  2493.     }
  2494.     "rstring" {
  2495.         if {"$value" == ""} {
  2496.             set error NULL
  2497.         }
  2498.         # no blanks allowed
  2499.         if {[string first " " $value] >=0} {
  2500.             set error INVALID
  2501.         }
  2502.     }
  2503.     "string" {
  2504.     }
  2505.     "path" {
  2506.         if {"$value" == ""} {
  2507.             set error NULL
  2508.         }
  2509.         # no blanks allowed
  2510.         if {[string first " " $value] >=0} {
  2511.             set error INVALID
  2512.         }
  2513.         # warning if path does not exist
  2514.         if {"$error" == ""} {
  2515.             if {[mag_remote_file_exists $value] == 0} {
  2516.                 VtUnLock
  2517.                 mag_warn1 NOEXIST $value
  2518.                 VtLock
  2519.             }
  2520.         }
  2521.     }
  2522.     "chpath" {
  2523.         # warn if path not exist, same as path
  2524.         if {"$value" == ""} {
  2525.             set error NULL
  2526.         }
  2527.         # no blanks allowed
  2528.         if {[string first " " $value] >=0} {
  2529.             set error INVALID
  2530.         }
  2531.         # warning if path does not exist
  2532.         if {"$error" == "" && "$value" != "SMTP"} {
  2533.             if {[mag_remote_file_exists $value] == 0} {
  2534.                 VtUnLock
  2535.                 mag_warn1 NOEXIST $value
  2536.                 VtLock
  2537.             }
  2538.         }
  2539.     }
  2540.     "chtable" {
  2541.         if {"$value" == ""} {
  2542.             set error NULL
  2543.         }
  2544.         # no blanks allowed
  2545.         if {[string first " " $value] >=0} {
  2546.             set error INVALID
  2547.         }
  2548.         # warning if path does not exist
  2549.         if {"$error" == ""} {
  2550.             if {[mag_remote_file_exists $value] == 0} {
  2551.                 VtUnLock
  2552.                 mag_warn1 NOEXIST $value
  2553.                 VtLock
  2554.             }
  2555.         }
  2556.     }
  2557.     "flags" {
  2558.         # no blanks allowed
  2559.         if {[string first " " $value] >=0} {
  2560.             set error INVALID
  2561.         }
  2562.     }
  2563.     "user" {
  2564.         # must be in list if not a number
  2565.         if {[ctype digit $value] == 0} {
  2566.             set users "[mag_msg DEFAULT] [mag_list_users]"
  2567.             if {[lsearch $users $value] == -1} {
  2568.                 set error INVALID
  2569.             }
  2570.         }
  2571.     }
  2572.     "group" {
  2573.         # must be in list if not a number
  2574.         if {[ctype digit $value] == 0} {
  2575.             set groups "[mag_msg DEFAULT] [mag_list_groups]"
  2576.             if {[lsearch $groups $value] == -1} {
  2577.                 set error INVALID
  2578.             }
  2579.         }
  2580.     }
  2581.     }
  2582.     switch $name {
  2583.     "ctable" {
  2584.         # validate channel table type
  2585.         set list [mag_table_enum]
  2586.         if {[lsearch $list $value] == -1} {
  2587.             VtUnLock
  2588.             mag_error1 INVALID $value
  2589.             VtLock
  2590.             return ""
  2591.         }
  2592.         # cannot switch to baduser if not last channel.
  2593.         set old [mag_table_to_internal [lindex $oldobject $MS(value)]]
  2594.         set new [mag_table_to_internal $value]
  2595.         if {"$old" != "baduser" && "$new" == "baduser"} {
  2596.             set chname [lindex $object $MS(chname)]
  2597.             set chlist [mai_ch_names_get]
  2598.             set chindex [lsearch $chlist $chname]
  2599.             set chlen [llength $chlist]
  2600.             set expect [expr $chlen - 1]
  2601.             # channel not last
  2602.             if {$chindex != $expect} {
  2603.                 VtUnLock
  2604.                 mag_error CH_NOT_LAST
  2605.                 VtLock
  2606.                 return ""
  2607.             }
  2608.             # now remove "mov" action from our channel object
  2609.             set chindex [mai_ch_find $index]
  2610.             set channel [lindex $mainscreen_db $chindex]
  2611.             set action [lindex $channel $MS(action)]
  2612.             set mov [lsearch $action mov]
  2613.             if {$mov >= 0} {
  2614.                 set action [lreplace $action $mov $mov]
  2615.             }
  2616.             set channel [lreplace $channel \
  2617.                 $MS(action) $MS(action) $action]
  2618.             set mainscreen_db [lreplace $mainscreen_db \
  2619.                 $chindex $chindex $channel]
  2620.         }
  2621.         if {"$old" == "baduser" && "$new" != "baduser"} {
  2622.             # restore "mov" action to our channel object
  2623.             set chindex [mai_ch_find $index]
  2624.             set channel [lindex $mainscreen_db $chindex]
  2625.             set action [lindex $channel $MS(action)]
  2626.             set mov [lsearch $action mov]
  2627.             if {$mov == -1} {
  2628.                 lappend action mov
  2629.             }
  2630.             set channel [lreplace $channel \
  2631.                 $MS(action) $MS(action) $action]
  2632.             set mainscreen_db [lreplace $mainscreen_db \
  2633.                 $chindex $chindex $channel]
  2634.         }
  2635.     }
  2636.     "cargs" {
  2637.         # channel program arguments cannot be null
  2638.         if {"$value" == ""} {
  2639.             set error NULL
  2640.         }
  2641.     }
  2642.     }
  2643.     if {"$error" != ""} {
  2644.         VtUnLock
  2645.         mag_error1 $error "$arg"
  2646.         VtLock
  2647.         return ""
  2648.     }
  2649.     return $object
  2650. }
  2651. proc \
  2652. mai_state { oldobject object index } \
  2653. {
  2654.     global mainscreen_db MS
  2655.     set type [lindex $object $MS(type)]
  2656.     set name [lindex $object $MS(name)]
  2657.     set value [lindex $object $MS(value)]
  2658.     set criteria [lindex $object $MS(criteria)]
  2659.     # Now do state changes where changing one property affects another.
  2660.     # This switch is on name, not type like the others in this file
  2661.     switch $name {
  2662.     "ctable" {
  2663.         set old [mag_table_to_internal [lindex $oldobject $MS(value)]]
  2664.         set new [mag_table_to_internal $value]
  2665.         # if switching to file type and filename is empty, default it.
  2666.         if {"$old" != "file" && "$new" == "file"} {
  2667.             set chindex [mai_ch_find $index]
  2668.             # find channel table file
  2669.             set ctindex [mai_prop_find $chindex cfile]
  2670.             set tmpobject [lindex $mainscreen_db $ctindex]
  2671.             set cfile [lindex $tmpobject $MS(value)]
  2672.             if {"$cfile" == ""} {
  2673.                 set tmpnewobject [mai_prop_def $tmpobject]
  2674.                 set tmpnewobject [mai_prop_set $tmpobject $tmpnewobject]
  2675.                 set mainscreen_db [lreplace $mainscreen_db \
  2676.                     $ctindex $ctindex $tmpnewobject]
  2677.                 # redraw line item
  2678.                 set stop [expr $ctindex + 1]
  2679.                 mag_display_mainlist $ctindex $stop -1
  2680.             }
  2681.         }
  2682.         # if switching to non-file type, blank out the filename.
  2683.         if {"$old" == "file" && "$new" != "file"} {
  2684.             set chindex [mai_ch_find $index]
  2685.             # find channel table file
  2686.             set ctindex [mai_prop_find $chindex cfile]
  2687.             set tmpobject [lindex $mainscreen_db $ctindex]
  2688.             set cfile [lindex $tmpobject $MS(value)]
  2689.             if {"$cfile" != ""} {
  2690.                 set tmpnewobject [lreplace $tmpobject $MS(value) $MS(value) ""]
  2691.                 set tmpnewobject [mai_prop_set $tmpobject $tmpnewobject]
  2692.                 set mainscreen_db [lreplace $mainscreen_db \
  2693.                     $ctindex $ctindex $tmpnewobject]
  2694.                 # redraw line item
  2695.                 set stop [expr $ctindex + 1]
  2696.                 mag_display_mainlist $ctindex $stop -1
  2697.             }
  2698.         }
  2699.     }
  2700.     "cuser" {
  2701.         # if user is changed to default, we must default the group too
  2702.         set old [lindex $oldobject $MS(value)]
  2703.         set new $value
  2704.         set default [mag_msg DEFAULT]
  2705.         if {"$old" != "$default" && "$new" == "$default"} {
  2706.             set chindex [mai_ch_find $index]
  2707.             # find channel table group
  2708.             set ctindex [mai_prop_find $chindex cgroup]
  2709.             set tmpobject [lindex $mainscreen_db $ctindex]
  2710.             set cgroup [lindex $tmpobject $MS(value)]
  2711.             if {"$cgroup" != "$default"} {
  2712.                 set tmpnewobject [mai_prop_def $tmpobject]
  2713.                 set tmpnewobject [mai_prop_set $tmpobject $tmpnewobject]
  2714.                 set mainscreen_db [lreplace $mainscreen_db \
  2715.                     $ctindex $ctindex $tmpnewobject]
  2716.                 # redraw line item
  2717.                 set stop [expr $ctindex + 1]
  2718.                 mag_display_mainlist $ctindex $stop -1
  2719.             }
  2720.         }
  2721.     }
  2722.     "cname" {
  2723.         # channel name must change all back links and folder name
  2724.         set calias $value
  2725.         set chname [mag_channel_to_internal $calias]
  2726.         # update channel container
  2727.         set chindex [mai_ch_find $index]
  2728.         set tmpobject [lindex $mainscreen_db $chindex]
  2729.         set tmpobject [lreplace $tmpobject \
  2730.             $MS(name) $MS(name) $chname]
  2731.         set tmpobject [lreplace $tmpobject \
  2732.             $MS(label) $MS(label) $calias]
  2733.         set mainscreen_db [lreplace $mainscreen_db \
  2734.             $chindex $chindex $tmpobject]
  2735.         # update all children
  2736.         set start [expr $chindex + 1]
  2737.         set length [llength $mainscreen_db]
  2738.         loop i $start $length {
  2739.             set tmpobject [lindex $mainscreen_db $i]
  2740.             set indent [lindex $tmpobject $MS(level)]
  2741.             if {$indent != 2} {
  2742.                 break
  2743.             }
  2744.             set tmpobject [lreplace $tmpobject \
  2745.                 $MS(chname) $MS(chname) $chname]
  2746.             set mainscreen_db [lreplace $mainscreen_db \
  2747.                 $i $i $tmpobject]
  2748.         }
  2749.         # redraw channel container item
  2750.         set chindex [mai_ch_find $index]
  2751.         set stop [expr $chindex + 1]
  2752.         mag_display_mainlist $chindex $stop -1
  2753.     }
  2754.     "host" {
  2755.         # setting host to a non-default name and v.v. affects altnames
  2756.         # the back end takes care of this, all we do is close and
  2757.         # reopen altnames if it is open.
  2758.         set length [llength $mainscreen_db]
  2759.         loop i 0 $length {
  2760.             set item [lindex $mainscreen_db $i]
  2761.             if {"[lindex $item $MS(type)]" == "altname"} {
  2762.                 break
  2763.             }
  2764.         }
  2765.         # have altname in item and it's index in i.
  2766.         set state [lindex $item $MS(state)]
  2767.         if {"$state" == "open"} {
  2768.             mai_collapse $i
  2769.             mai_expand $i
  2770.             # reselect hostname
  2771.             mag_display_mainlist $index $index $index
  2772.         }
  2773.     }
  2774.     }
  2775. }
  2776. proc \
  2777. mag_stand_edit { object file } \
  2778. {
  2779.     global app MS
  2780.     global UUX SLOCAL MULTIHOME
  2781.     global mag_stand_object mag_stand_form
  2782.     global mag_stand_toggle mag_stand_text mag_stand_combo
  2783.     global mag_stand_fdir mag_stand_fname mag_stand_outfile
  2784.     set type [lindex $object $MS(type)]
  2785.     set name [lindex $object $MS(name)]
  2786.     set label [lindex $object $MS(label)]
  2787.     set value [lindex $object $MS(value)]
  2788.     set criteria [lindex $object $MS(criteria)]
  2789.     set custom [lindex $object $MS(custom)]
  2790.     # globals for callbacks
  2791.     set mag_stand_object $object
  2792.     set mag_stand_outfile $file
  2793.     # init widget server
  2794.     set app [VtOpen mailchild "mailadmin"]
  2795.     mag_setcat SCO_MAIL_ADMIN
  2796.     # std dialog box
  2797.     set mag_stand_form [ \
  2798.         VtFormDialog $app.mailchild \
  2799.         -title [mag_msg TITLE_MOD] \
  2800.         -resizable FALSE \
  2801.         -ok -okCallback mag_stand_ok \
  2802.         -cancel -cancelCallback mag_stand_quit \
  2803.         -wmCloseCallback mag_stand_quit \
  2804.     ]
  2805.     set ok [VtGetValues $mag_stand_form -ok]
  2806.     # setup dialog box
  2807.     switch "$type" {
  2808.     "boolean" {
  2809.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2810.         set mag_stand_toggle [ \
  2811.             VtToggleButton $mag_stand_form.toggle \
  2812.             -label $label \
  2813.             -value [mag_bool_to_num $value] \
  2814.         ]
  2815.         set focus $mag_stand_toggle
  2816.     }
  2817.     "fqdn" {
  2818.         set parms ""
  2819.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2820.         set mag_stand_text [ \
  2821.             VtText $mag_stand_form.text \
  2822.             -topSide $tmplabel \
  2823.             -columns 40 \
  2824.             -callback "mag_stand_jump $ok" \
  2825.         ]
  2826.         VtSetValues $mag_stand_text -value $value
  2827.         VtPushButton $mag_stand_form.browse \
  2828.             -leftSide $mag_stand_text \
  2829.             -topSide $tmplabel \
  2830.             -callback mag_stand_fqdn_browse \
  2831.             -label [mag_msg STR_SELECT]
  2832.         set focus $mag_stand_text
  2833.     }
  2834.     "ofqdn" {
  2835.         set parms ""
  2836.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2837.         set mag_stand_text [ \
  2838.             VtText $mag_stand_form.text \
  2839.             -topSide $tmplabel \
  2840.             -columns 40 \
  2841.             -callback "mag_stand_jump $ok" \
  2842.         ]
  2843.         VtSetValues $mag_stand_text -value $value
  2844.         VtPushButton $mag_stand_form.browse \
  2845.             -leftSide $mag_stand_text \
  2846.             -topSide $tmplabel \
  2847.             -callback mag_stand_fqdn_browse \
  2848.             -label [mag_msg STR_SELECT]
  2849.         if {"$name" == "chost" && \
  2850.             "[lindex $object $MS(chname)]" == "badhost" } {
  2851.             set nonelabel [mag_msg STR_NONE_DELAY]
  2852.         } else {
  2853.             set nonelabel [mag_msg STR_NONE]
  2854.         }
  2855.         VtPushButton $mag_stand_form.btn \
  2856.             -topSide $mag_stand_text \
  2857.             -leftSide FORM -rightSide FORM \
  2858.             -label "$nonelabel" \
  2859.             -callback mag_stand_none
  2860.         set focus $mag_stand_text
  2861.     }
  2862.     "fromdom" {
  2863.         VtLabel $mag_stand_form.label -label $label
  2864.         set mag_stand_combo [ \
  2865.             VtComboBox $mag_stand_form.combo \
  2866.             -itemList $criteria \
  2867.             -leftSide FORM -rightSide FORM \
  2868.             -value $value \
  2869.             -callback "mag_stand_jump $ok" \
  2870.         ]
  2871.         set focus $mag_stand_combo
  2872.     }
  2873.     "intrange" {
  2874.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2875.         set mag_stand_text [ \
  2876.             VtText $mag_stand_form.text \
  2877.             -columns 10 \
  2878.             -callback "mag_stand_jump $ok" \
  2879.         ]
  2880.         set t1 [lindex $criteria 0]
  2881.         set t2 [lindex $criteria 1]
  2882.         VtLabel $mag_stand_form.range \
  2883.             -label "($t1-$t2)" \
  2884.             -leftSide $mag_stand_text \
  2885.             -topSide $tmplabel
  2886.         VtSetValues $mag_stand_text -value $value
  2887.         set focus $mag_stand_text
  2888.     }
  2889.     "ointrange" {
  2890.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2891.         set mag_stand_text [ \
  2892.             VtText $mag_stand_form.text \
  2893.             -columns 10 \
  2894.             -callback "mag_stand_jump $ok" \
  2895.         ]
  2896.         set t1 [lindex $criteria 0]
  2897.         set t2 [lindex $criteria 1]
  2898.         VtLabel $mag_stand_form.range \
  2899.             -label "($t1-$t2)" \
  2900.             -leftSide $mag_stand_text \
  2901.             -topSide $tmplabel
  2902.         VtSetValues $mag_stand_text -value $value
  2903.         VtPushButton $mag_stand_form.btn \
  2904.             -topSide $mag_stand_text \
  2905.             -leftSide FORM -rightSide FORM \
  2906.             -label [mag_msg STR_NONE] \
  2907.             -callback mag_stand_none
  2908.         set focus $mag_stand_text
  2909.     }
  2910.     "enum" {
  2911.         VtLabel $mag_stand_form.label -label $label
  2912.         set mag_stand_combo [ \
  2913.             VtComboBox $mag_stand_form.combo \
  2914.             -itemList $criteria \
  2915.             -leftSide FORM -rightSide FORM \
  2916.             -value $value \
  2917.             -callback "mag_stand_jump $ok" \
  2918.         ]
  2919.         if {"$name" == "flocation"} {
  2920.             # add custom folder location callback
  2921.             VtSetValues $mag_stand_combo \
  2922.                 -valueChangedCallback mag_stand_custom
  2923.             # add custom folder location text widgets
  2924.             VtLabel $mag_stand_form.label1 \
  2925.                 -label [mag_msg FOLDER_DIR]
  2926.             VtLabel $mag_stand_form.label2 \
  2927.                 -label [mag_msg SHORT_FOLDER_DIR]
  2928.             set mag_stand_fdir [ \
  2929.                 VtText $mag_stand_form.fdir \
  2930.                 -columns 50 \
  2931.             ]
  2932.             VtLabel $mag_stand_form.label3 \
  2933.                 -label [mag_msg FOLDER_NAME]
  2934.             VtLabel $mag_stand_form.label4 \
  2935.                 -label [mag_msg SHORT_FOLDER_NAME]
  2936.             set mag_stand_fname [ \
  2937.                 VtText $mag_stand_form.fname \
  2938.                 -columns 50 \
  2939.             ]
  2940.             VtSetValues $mag_stand_fdir \
  2941.                 -value [lindex $custom 0] \
  2942.                 -callback "mag_stand_jump $mag_stand_fname"
  2943.             VtSetValues $mag_stand_fname \
  2944.                 -value [lindex $custom 1] \
  2945.                 -callback "mag_stand_jump $ok"
  2946.             mag_stand_custom cbs
  2947.         }
  2948.         set focus $mag_stand_combo
  2949.     }
  2950.     "umask" {
  2951.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2952.         set mag_stand_text [ \
  2953.             VtText $mag_stand_form.text \
  2954.             -columns 6 \
  2955.             -callback "mag_stand_jump $ok" \
  2956.         ]
  2957.         VtLabel $mag_stand_form.range \
  2958.             -label "(0-0777)" \
  2959.             -leftSide $mag_stand_text \
  2960.             -topSide $tmplabel
  2961.         VtSetValues $mag_stand_text -value $value
  2962.         set focus $mag_stand_text
  2963.     }
  2964.     "alias" {
  2965.         VtLabel $mag_stand_form.label -label [mag_msg ALIAS1]
  2966.         set mag_stand_text [ \
  2967.             VtText $mag_stand_form.text \
  2968.             -columns 50 \
  2969.             -callback "mag_stand_jump $ok" \
  2970.         ]
  2971.         set tmp [VtLabel $mag_stand_form.label2 -label [mag_msg ALIAS2]]
  2972.         VtSetValues $mag_stand_text -value $value
  2973.         VtPushButton $mag_stand_form.btn \
  2974.             -topSide $tmp \
  2975.             -leftSide FORM -rightSide FORM \
  2976.             -label [mag_msg STR_EDIT_ALIAS] \
  2977.             -callback mag_stand_alias_edit
  2978.         set focus $mag_stand_text
  2979.     }
  2980.     "rstring" {
  2981.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2982.         set mag_stand_text [ \
  2983.             VtText $mag_stand_form.text \
  2984.             -columns 50 \
  2985.             -callback "mag_stand_jump $ok" \
  2986.         ]
  2987.         VtSetValues $mag_stand_text -value $value
  2988.         set focus $mag_stand_text
  2989.     }
  2990.     "string" {
  2991.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  2992.         set mag_stand_text [ \
  2993.             VtText $mag_stand_form.text \
  2994.             -columns 50 \
  2995.             -callback "mag_stand_jump $ok" \
  2996.         ]
  2997.         VtSetValues $mag_stand_text -value $value
  2998.         set focus $mag_stand_text
  2999.     }
  3000.     "path" {
  3001.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  3002.         set mag_stand_text [ \
  3003.             VtText $mag_stand_form.text \
  3004.             -columns 50 \
  3005.             -callback "mag_stand_jump $ok" \
  3006.         ]
  3007.         VtSetValues $mag_stand_text -value $value
  3008.         set focus $mag_stand_text
  3009.     }
  3010.     "chpath" {
  3011.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  3012.         set programs [list $SLOCAL SMTP $UUX $MULTIHOME]
  3013.         set mag_stand_combo [ \
  3014.             VtComboBox $mag_stand_form.combo \
  3015.             -itemList $programs \
  3016.             -leftSide FORM -rightSide FORM \
  3017.             -value $value \
  3018.             -callback "mag_stand_jump $ok" \
  3019.         ]
  3020.         set focus $mag_stand_combo
  3021.     }
  3022.     "chtable" {
  3023.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  3024.         set mag_stand_text [ \
  3025.             VtText $mag_stand_form.text \
  3026.             -columns 50 \
  3027.             -callback "mag_stand_jump $ok" \
  3028.         ]
  3029.         VtSetValues $mag_stand_text -value $value
  3030.         VtPushButton $mag_stand_form.btn \
  3031.             -topSide $mag_stand_text \
  3032.             -leftSide FORM -rightSide FORM \
  3033.             -label [mag_msg STR_EDIT_CTABLE] \
  3034.             -callback mag_stand_ctable_edit
  3035.         set focus $mag_stand_text
  3036.     }
  3037.     "domtable" {
  3038.         set ret [mag_query_qyn EDIT_DTABLE ""]
  3039.         if {"$ret" == "yes"} {
  3040.             mag_stand_dtable_edit
  3041.         }
  3042.         mag_stand_quit cbs
  3043.     }
  3044.     "flags" {
  3045.         set tmplabel [VtLabel $mag_stand_form.label -label $label]
  3046.         set mag_stand_text [ \
  3047.             VtText $mag_stand_form.text \
  3048.             -columns 40 \
  3049.             -callback "mag_stand_jump $ok" \
  3050.         ]
  3051.         VtPushButton $mag_stand_form.btn \
  3052.             -topSide $tmplabel \
  3053.             -leftSide $mag_stand_text -rightSide FORM \
  3054.             -label [mag_msg STR_SELECT] \
  3055.             -callback mag_stand_flags
  3056.         VtSetValues $mag_stand_text -value $value
  3057.         set focus $mag_stand_text
  3058.     }
  3059.     "user" {
  3060.         VtLabel $mag_stand_form.label -label $label
  3061.         set users "[mag_list_users]"
  3062.         set users [lsort $users]
  3063.         set users "[mag_msg DEFAULT] $users"
  3064.         set mag_stand_combo [ \
  3065.             VtComboBox $mag_stand_form.combo \
  3066.             -itemList $users \
  3067.             -leftSide FORM -rightSide FORM \
  3068.             -value $value \
  3069.             -callback "mag_stand_jump $ok" \
  3070.         ]
  3071.         set focus $mag_stand_combo
  3072.     }
  3073.     "group" {
  3074.         VtLabel $mag_stand_form.label -label $label
  3075.         set groups "[mag_list_groups]"
  3076.         set groups [lsort $groups]
  3077.         set groups "[mag_msg DEFAULT] $groups"
  3078.         set mag_stand_combo [ \
  3079.             VtComboBox $mag_stand_form.combo \
  3080.             -itemList $groups \
  3081.             -leftSide FORM -rightSide FORM \
  3082.             -value $value \
  3083.             -callback "mag_stand_jump $ok" \
  3084.         ]
  3085.         set focus $mag_stand_combo
  3086.     }
  3087.     "ruleset" {
  3088.         VtLabel $mag_stand_form.label -label $label
  3089.         set none [mag_msg NONE]
  3090.         switch $name {
  3091.         "crecip" {
  3092.             set suffix re
  3093.         }
  3094.         "chrecip" {
  3095.             set suffix rh
  3096.             set none [mag_msg RULEDEF]
  3097.         }
  3098.         "csender" {
  3099.             set suffix se
  3100.         }
  3101.         "chsender" {
  3102.             set suffix sh
  3103.             set none [mag_msg RULEDEF]
  3104.         }
  3105.         }
  3106.         set items [list \
  3107.             $none \
  3108.             ap822_$suffix \
  3109.             aplocal_$suffix \
  3110.             ap976_$suffix \
  3111.         ]
  3112.         set mag_stand_combo [ \
  3113.             VtComboBox $mag_stand_form.combo \
  3114.             -itemList $items \
  3115.             -leftSide FORM -rightSide FORM \
  3116.             -value $value \
  3117.             -callback "mag_stand_jump $ok" \
  3118.         ]
  3119.         set focus $mag_stand_combo
  3120.     }
  3121.     }
  3122.     VtShow $mag_stand_form
  3123.     VtSetFocus $focus
  3124.     VtMainLoop
  3125. }
  3126. proc \
  3127. mag_stand_ok { cbs } \
  3128. {
  3129.     global mag_stand_object MS
  3130.     global mag_stand_toggle mag_stand_text mag_stand_combo
  3131.     global mag_stand_fdir mag_stand_fname mag_stand_outfile
  3132.     set object $mag_stand_object
  3133.     set type [lindex $object $MS(type)]
  3134.     set name [lindex $object $MS(name)]
  3135.     # extract value and type check it if needed.
  3136.     switch "$type" {
  3137.     "boolean" {
  3138.         set value [VtGetValues $mag_stand_toggle -value]
  3139.         set value [mag_num_to_bool $value]
  3140.     }
  3141.     "fqdn" {
  3142.         set value [VtGetValues $mag_stand_text -value]
  3143.     }
  3144.     "ofqdn" {
  3145.         set value [VtGetValues $mag_stand_text -value]
  3146.     }
  3147.     "fromdom" {
  3148.         set value [VtGetValues $mag_stand_combo -value]
  3149.     }
  3150.     "intrange" {
  3151.         set value [VtGetValues $mag_stand_text -value]
  3152.     }
  3153.     "ointrange" {
  3154.         set value [VtGetValues $mag_stand_text -value]
  3155.     }
  3156.     "enum" {
  3157.         set value [VtGetValues $mag_stand_combo -value]
  3158.         if {"$name" == "flocation"} {
  3159.             set fdir [VtGetValues $mag_stand_fdir -value]
  3160.             set fname [VtGetValues $mag_stand_fname -value]
  3161.             set custom [list $fdir $fname]
  3162.             set object [lreplace $object $MS(custom) $MS(custom) $custom]
  3163.         }
  3164.     }
  3165.     "umask" {
  3166.         set value [VtGetValues $mag_stand_text -value]
  3167.     }
  3168.     "alias" {
  3169.         set value [VtGetValues $mag_stand_text -value]
  3170.     }
  3171.     "rstring" {
  3172.         set value [VtGetValues $mag_stand_text -value]
  3173.     }
  3174.     "string" {
  3175.         set value [VtGetValues $mag_stand_text -value]
  3176.     }
  3177.     "path" {
  3178.         set value [VtGetValues $mag_stand_text -value]
  3179.     }
  3180.     "chpath" {
  3181.         set value [VtGetValues $mag_stand_combo -value]
  3182.     }
  3183.     "chtable" {
  3184.         set value [VtGetValues $mag_stand_text -value]
  3185.     }
  3186.     "flags" {
  3187.         set value [VtGetValues $mag_stand_text -value]
  3188.     }
  3189.     "user" {
  3190.         set value [VtGetValues $mag_stand_combo -value]
  3191.     }
  3192.     "group" {
  3193.         set value [VtGetValues $mag_stand_combo -value]
  3194.     }
  3195.     "ruleset" {
  3196.         set value [VtGetValues $mag_stand_combo -value]
  3197.     }
  3198.     }
  3199.     set object [lreplace $object $MS(value) $MS(value) $value]
  3200.     # our return value is sent to outfile
  3201.     if {[catch {open $mag_stand_outfile w} fd] == 0} {
  3202.         puts $fd $object
  3203.         close $fd
  3204.     }
  3205.     VtClose
  3206.     exit 0
  3207. }
  3208. proc \
  3209. mag_stand_quit { cbs } \
  3210. {
  3211.     VtClose
  3212.     exit 0
  3213. }
  3214. proc \
  3215. mag_stand_jump { widget cbs } \
  3216. {
  3217.     VtSetFocus $widget
  3218. }
  3219. proc \
  3220. mag_stand_fqdn_browse { cbs } \
  3221. {
  3222.     global mag_stand_object MS
  3223.     global mag_stand_form
  3224.     keylset parms parent $mag_stand_form
  3225.     keylset parms instance abc
  3226.     keylset parms labeltext [lindex $mag_stand_object $MS(label)]
  3227.     keylset parms buttontext [mag_msg STR_SELECT]
  3228.     keylset parms userproc mag_stand_fqdn_browse_done
  3229.     SaSelectHostDialog $parms $cbs
  3230. }
  3231. proc \
  3232. mag_stand_fqdn_browse_done { cbs } \
  3233. {
  3234.     global mag_stand_text mag_stand_form
  3235.     set value [SaSelectHostGetSelection abc]
  3236.     VtSetValues $mag_stand_text -value $value
  3237.     set ok [VtGetValues $mag_stand_form -ok]
  3238.     mag_stand_jump $ok $cbs
  3239. }
  3240. proc \
  3241. mag_stand_none { cbs } \
  3242. {
  3243.     global mag_stand_text
  3244.     VtSetValues $mag_stand_text -value [mag_msg NONE]
  3245. }
  3246. proc \
  3247. mag_stand_alias_edit { cbs } \
  3248. {
  3249.     global mag_stand_text
  3250.     global MS app
  3251.     global ALIAS_EDITOR
  3252.     set value [VtGetValues $mag_stand_text -value]
  3253.     set test [csubstr $value 0 4]
  3254.     if {"$test" == "nis:"} {
  3255.         VtErrorDialog $app.err -block -ok -message [mag_err AFILE_ONLY]
  3256.         return
  3257.     }
  3258.     mag_stand_call_editor $ALIAS_EDITOR $value
  3259. }
  3260. proc \
  3261. mag_stand_ctable_edit { cbs } \
  3262. {
  3263.     global mag_stand_object MS app
  3264.     global CTABLE_EDITOR
  3265.     set object $mag_stand_object
  3266.     set value [lindex $object $MS(value)]
  3267.     # call channel table editor
  3268.     mag_stand_call_editor $CTABLE_EDITOR $value
  3269. }
  3270. proc \
  3271. mag_stand_dtable_edit {} \
  3272. {
  3273.     global mag_stand_object MS app
  3274.     global DTABLE_EDITOR
  3275.     set object $mag_stand_object
  3276.     set value [lindex $object $MS(value)]
  3277.     mag_stand_call_editor $DTABLE_EDITOR $value
  3278. }
  3279. proc \
  3280. mag_stand_custom { cbs } \
  3281. {
  3282.     global mag_stand_object
  3283.     global mag_stand_combo
  3284.     global mag_stand_fdir mag_stand_fname mag_stand_form
  3285.     global MAILSPOOL INBOXNAME
  3286.     set value [VtGetValues $mag_stand_combo -value]
  3287.     # update sensitivity and fields
  3288.     if {"$value" != "[mag_msg FOLDER_CUSTOM]"} {
  3289.         VtSetValues $mag_stand_fdir -sensitive 0
  3290.         VtSetValues $mag_stand_fname -sensitive 0
  3291.         if {"$value" == "[mag_msg FOLDER_SYSTEM]"} {
  3292.             VtSetValues $mag_stand_fdir -value $MAILSPOOL
  3293.             VtSetValues $mag_stand_fname -value ""
  3294.         } else {
  3295.             VtSetValues $mag_stand_fdir -value ""
  3296.             VtSetValues $mag_stand_fname -value "$INBOXNAME"
  3297.         }
  3298.         set ok [VtGetValues $mag_stand_form -ok]
  3299.         VtSetValues $mag_stand_combo \
  3300.             -callback "mag_stand_jump $ok"
  3301.     } else {
  3302.         VtSetValues $mag_stand_fdir -sensitive 1
  3303.         VtSetValues $mag_stand_fname -sensitive 1
  3304.         VtSetValues $mag_stand_combo \
  3305.             -callback "mag_stand_jump $mag_stand_fdir"
  3306.     }
  3307. }
  3308. proc \
  3309. mag_stand_call_editor { editor file } \
  3310. {
  3311.     global PID mag_host_name mag_local_host
  3312.     VtLock
  3313.     # first strip off class if there
  3314.     set class ""
  3315.     set fname $file
  3316.     set pos [string first ":" $file]
  3317.     if {$pos >= 0} {
  3318.         set class [csubstr $file 0 $pos]
  3319.         set start [expr $pos + 1]
  3320.         set fname [csubstr $file $start end]
  3321.         set class [string trim $class]
  3322.         set fname [string trim $fname]
  3323.         if {"$class" != "dbm" && "$class" != "hash" &&
  3324.             "$class" != "btree" && "$class" != "implicit" } {
  3325.             VtUnLock
  3326.             mag_error1 INVALID_CLASS $class
  3327.             return
  3328.         }
  3329.     }
  3330.     # tmp file names
  3331.     set fnamedb "$fname.db"
  3332.     set base [exec basename $editor]
  3333.     set tmp1 "/tmp/$base.$PID"
  3334.     set tmp1db "/tmp/$base.$PID.db"
  3335.     set tmp2 "/tmp/$base.1.$PID"
  3336.     set tmp2db "/tmp/$base.1.$PID.db"
  3337.     # copy in files
  3338.     system "rm -fr $tmp1 $tmp1db $tmp2 $tmp2db"
  3339.     set ret [mag_remote_copyin $fname $tmp1]
  3340.     set ret [mag_remote_copyin $fname $tmp2]
  3341.     set ret [mag_remote_copyin $fnamedb $tmp1db]
  3342.     set host ""
  3343.     if {"$mag_host_name" != "$mag_local_host"} {
  3344.         set host "-h $mag_host_name"
  3345.     }
  3346.     if {"$class" != ""} {
  3347.         set cmd "$editor $host -f $class:$tmp2"
  3348.     } else {
  3349.         set cmd "$editor $host -f $tmp2"
  3350.     }
  3351.     VtControl -suspend
  3352.     catch {system "$cmd"} ret
  3353.     VtControl -resume
  3354.     if {$ret != 0} {
  3355.         VtUnLock
  3356.         mag_error1 EXEC $editor
  3357.         system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  3358.         return
  3359.     }
  3360.     # copy back main file
  3361.     set ret ok
  3362.     if {[file exists $tmp2] == 1} {
  3363.         if {[file exists $tmp1] == 1} {
  3364.             catch {system "cmp $tmp2 $tmp1 > /dev/null 2>&1"} tmp
  3365.             # files are different
  3366.             if {$tmp == 1} {
  3367.                 set ret [mag_remote_copyout $tmp2 $fname]
  3368.             }
  3369.         } else {
  3370.             set ret [mag_remote_copyout $tmp2 $fname]
  3371.         }
  3372.     }
  3373.     if {"$ret" != "ok"} {
  3374.         VtUnLock
  3375.         mag_error1 COPY_BACK $fname
  3376.         system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  3377.         return
  3378.     }
  3379.     # copy back db file
  3380.     set ret ok
  3381.     if {[file exists $tmp2db] == 1} {
  3382.         if {[file exists $tmp1db] == 1} {
  3383.             catch {system "cmp $tmp2db $tmp1db > /dev/null 2>&1"} tmp
  3384.             # files are different
  3385.             if {$tmp == 1} {
  3386.                 set ret [mag_remote_copyout $tmp2db $fnamedb]
  3387.             }
  3388.         } else {
  3389.             set ret [mag_remote_copyout $tmp2db $fnamedb]
  3390.         }
  3391.     }
  3392.     if {"$ret" != "ok"} {
  3393.         VtUnLock
  3394.         mag_error1 COPY_BACK $fnamedb
  3395.         system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  3396.         return
  3397.     }
  3398.     system "rm -f $tmp1 $tmp1db $tmp2 $tmp2db"
  3399.     VtUnLock
  3400. }
  3401. proc \
  3402. mag_stand_flags { cbs } \
  3403. {
  3404.     global app RESPATH MS
  3405.     global mag_stand_text
  3406.     global mag_stand_text mag_two_form mag_two_list1 mag_two_list2
  3407.     # get flags from text widget
  3408.     set value [VtGetValues $mag_stand_text -value]
  3409.     set isCharm [VtInfo -charm]
  3410.     set mag_two_form [ \
  3411.         VtFormDialog $app.mailchild.flags \
  3412.         -title [mag_msg CH_FLAGS] \
  3413.         -ok -okCallback mag_stand_flags_ok \
  3414.         -wmCloseCallback mag_stand_flags_quit \
  3415.     ]
  3416.     VtLabel $mag_two_form.label1 -label [mag_msg FLAGS_LIST1]
  3417.     set lists [mag_stand_flags_to_lists $value]
  3418.     set fieldlist1 [lindex $lists 0]
  3419.     set fieldlist2 [lindex $lists 1]
  3420.     # get longest entry
  3421.     set max [mag_stand_two_max $fieldlist1 $fieldlist2]
  3422.     set formatlist [list [list STRING 3] [list STRING $max]]
  3423.     set mag_two_list1 [ \
  3424.         VtDrawnList $mag_two_form.list1 \
  3425.         -leftSide FORM -rightSide FORM \
  3426.         -columns 75 \
  3427.         -rows 8 \
  3428.         -selection MULTIPLE \
  3429.         -formatList $formatlist \
  3430.         -recordList $fieldlist1 \
  3431.         -horizontalScrollBar 1 \
  3432.     ]
  3433.     set tmp [VtLabel $mag_two_form.label2 -label [mag_msg FLAGS_LIST2]]
  3434.     set tmp1 [VtPushButton $mag_two_form.btndn \
  3435.         -leftSide 44 \
  3436.         -topSide $mag_two_list1 \
  3437.         -callback mag_stand_two_dn \
  3438.     ]
  3439.     set tmp2 [VtPushButton $mag_two_form.btnup \
  3440.         -leftSide $tmp1 \
  3441.         -topSide $mag_two_list1 \
  3442.         -callback mag_stand_two_up]
  3443.     if {$isCharm} {
  3444.         VtSetValues $tmp1 \
  3445.             -label [mag_msg MENU_DN] \
  3446.             -labelCenter
  3447.         VtSetValues $tmp2 \
  3448.             -label [mag_msg MENU_UP] \
  3449.             -labelCenter
  3450.     } else {
  3451.         VtSetValues $tmp1 \
  3452.             -pixmap $RESPATH/next.px
  3453.         VtSetValues $tmp2 \
  3454.             -pixmap $RESPATH/prev.px
  3455.     }
  3456.     set mag_two_list2 [ \
  3457.         VtDrawnList $mag_two_form.list2 \
  3458.         -leftSide FORM -rightSide FORM \
  3459.         -bottomSide FORM \
  3460.         -columns 75 \
  3461.         -rows 7 \
  3462.         -selection MULTIPLE \
  3463.         -formatList $formatlist \
  3464.         -recordList $fieldlist2 \
  3465.         -horizontalScrollBar 1 \
  3466.     ]
  3467.     mag_stand_two_drawnlist_bug $mag_two_list1
  3468.     mag_stand_two_drawnlist_bug $mag_two_list2
  3469.     VtShow $mag_two_form
  3470. }
  3471. proc \
  3472. mag_stand_flags_ok { cbs } \
  3473. {
  3474.     global mag_stand_text
  3475.     global mag_two_list1 mag_two_list2 mag_two_form
  3476.     # get flags from drawn list
  3477.     set items [VtDrawnListGetItem $mag_two_list2 -all]
  3478.     set flags ""
  3479.     foreach item $items {
  3480.         set flag [lindex $item 0]
  3481.         set flags "$flags$flag"
  3482.     }
  3483.     # put value back into text widget
  3484.     VtSetValues $mag_stand_text -value $flags
  3485.     VtDestroy $mag_two_form
  3486. }
  3487. proc \
  3488. mag_stand_flags_quit { cbs } \
  3489. {
  3490.     global mag_two_form
  3491.     VtDestroy $mag_two_form
  3492. }
  3493. proc \
  3494. mag_stand_flags_to_lists { flags } \
  3495. {
  3496.     # build master list of characters and description strings
  3497.     set allflags "aAbcCdDeEfFghIjkKlLmMnopPqrsSuUwxX035789:|/@"
  3498.     set regularflags aAbcCdDeEfFghIjkKlLmMnopPqrsSuUwxX035789
  3499.     set specialflags [list ": COLON" "| PIPE" "/ SLASH" "@ AT"]
  3500.     set length [clength $regularflags]
  3501.     set list1 ""
  3502.     set list2 ""
  3503.     # regular flags
  3504.     loop i 0 $length {
  3505.         set flag [cindex $regularflags $i]
  3506.         set which [string first $flag $flags]
  3507.         eval "set mname F_$flag"
  3508.         set msg [mag_msg $mname]
  3509.         set item [list $flag $msg]
  3510.         if {$which < 0} {
  3511.             lappend list1 $item
  3512.         } else {
  3513.             lappend list2 $item
  3514.         }
  3515.     }
  3516.     # special flags, characters that aren't valid in a msg cat name
  3517.     foreach i $specialflags {
  3518.         set flag [lindex $i 0]
  3519.         set name [lindex $i 1]
  3520.         set which [string first $flag $flags]
  3521.         eval "set mname F_$name"
  3522.         set msg [mag_msg $mname]
  3523.         set item [list $flag $msg]
  3524.         if {$which < 0} {
  3525.             lappend list1 $item
  3526.         } else {
  3527.             lappend list2 $item
  3528.         }
  3529.     }
  3530.     # now check for unknown flags
  3531.     set length [clength $flags]
  3532.     loop i 0 $length {
  3533.         set flag [cindex $flags $i]
  3534.         set found [string first $flag $allflags]
  3535.         if {$found >= 0} {
  3536.             continue
  3537.         }
  3538.         set item [list $flag [mag_msg F_UNKNOWN]]
  3539.         lappend list2 $item
  3540.     }
  3541.     set list1 [lsort $list1]
  3542.     set list2 [lsort $list2]
  3543.     return [list $list1 $list2]
  3544. }
  3545. proc \
  3546. mag_stand_two_up { cbs } \
  3547. {
  3548.     global mag_two_list1 mag_two_list2
  3549.     set newitems [VtDrawnListGetSelectedItem $mag_two_list2 -byRecordList]
  3550.     if {"$newitems" == ""} {
  3551.         return
  3552.     }
  3553.     set positions [VtDrawnListGetSelectedItem $mag_two_list2 -byPositionList]
  3554.     VtDrawnListDeleteItem $mag_two_list2 -positionList $positions
  3555.     set items [VtDrawnListGetItem $mag_two_list1 -all]
  3556.     # merge two lists
  3557.     set list "$items $newitems"
  3558.     set list [lsort $list]
  3559.     VtDrawnListDeleteItem $mag_two_list1 -all
  3560.     VtDrawnListAddItem $mag_two_list1 -recordList $list
  3561.     # now select the items that were moved so that undo is possible
  3562.     VtDrawnListDeselectItem $mag_two_list1 -all
  3563.     set positionlist ""
  3564.     foreach item $newitems {
  3565.         set pos [lsearch $list $item]
  3566.         set pos [expr $pos + 1]
  3567.         lappend positionlist $pos
  3568.     }
  3569.     VtDrawnListSelectItem $mag_two_list1 -positionList $positionlist
  3570.     mag_stand_two_drawnlist_bug $mag_two_list1
  3571. }
  3572. proc \
  3573. mag_stand_two_dn { cbs } \
  3574. {
  3575.     global mag_two_list1 mag_two_list2
  3576.     set newitems [VtDrawnListGetSelectedItem $mag_two_list1 -byRecordList]
  3577.     if {"$newitems" == ""} {
  3578.         return
  3579.     }
  3580.     set positions [VtDrawnListGetSelectedItem $mag_two_list1 -byPositionList]
  3581.     VtDrawnListDeleteItem $mag_two_list1 -positionList $positions
  3582.     set items [VtDrawnListGetItem $mag_two_list2 -all]
  3583.     # merge two lists
  3584.     set list "$items $newitems"
  3585.     set list [lsort $list]
  3586.     VtDrawnListDeleteItem $mag_two_list2 -all
  3587.     VtDrawnListAddItem $mag_two_list2 -recordList $list
  3588.     # now select the items that were moved so that undo is possible
  3589.     VtDrawnListDeselectItem $mag_two_list2 -all
  3590.     set positionlist ""
  3591.     foreach item $newitems {
  3592.         set pos [lsearch $list $item]
  3593.         set pos [expr $pos + 1]
  3594.         lappend positionlist $pos
  3595.     }
  3596.     VtDrawnListSelectItem $mag_two_list2 -positionList $positionlist
  3597.     mag_stand_two_drawnlist_bug $mag_two_list2
  3598. }
  3599. proc \
  3600. mag_stand_two_max { l1 l2 } \
  3601. {
  3602.     set max 0
  3603.     foreach item $l1 {
  3604.         set str [lindex $item 1]
  3605.         set len [clength $item]
  3606.         if {$max < $len} {
  3607.             set max $len
  3608.         }
  3609.     }
  3610.     foreach item $l2 {
  3611.         set str [lindex $item 1]
  3612.         set len [clength $item]
  3613.         if {$max < $len} {
  3614.             set max $len
  3615.         }
  3616.     }
  3617.     return $max
  3618. }
  3619. proc \
  3620. mag_stand_two_drawnlist_bug { widget } \
  3621. {
  3622.     # add and delete a dummy (blank) item
  3623.     set list [list "dum" "dum"]
  3624.     VtDrawnListAddItem $widget -fieldList $list
  3625.     VtDrawnListDeleteItem $widget -field 0 "dum"
  3626. }
  3627. proc \
  3628. mao_badhost {} \
  3629. {
  3630.     mai_badchan badhost
  3631. }
  3632. proc \
  3633. mao_baduser {} \
  3634. {
  3635.     mai_badchan baduser
  3636. }
  3637. proc \
  3638. mai_badchan { badchan } \
  3639. {
  3640.     global mainscreen_db MS main_list DIRTY
  3641.     # find channels container
  3642.     set length [llength $mainscreen_db]
  3643.     loop i 0 $length {
  3644.         set channels [lindex $mainscreen_db $i]
  3645.         set type [lindex $channels $MS(type)]
  3646.         if {"$type" == "channels"} {
  3647.             break
  3648.         }
  3649.     }
  3650.     # have channels container
  3651.     set chs_index $i
  3652.     set chs_state [lindex $channels $MS(state)]
  3653.     if {"$chs_state" == "open"} {
  3654.         mai_collapse $chs_index
  3655.     }
  3656.     # setup for search
  3657.     set chans [mai_ch_names_get]
  3658.     set found [lsearch $chans $badchan]
  3659.     # check that baduser channel does not already exist under another name.
  3660.     # We always need to know this for channel ordering later as
  3661.     # the baduser channel must always go last.
  3662.     set baduserfound -1
  3663.     set last [llength $chans]
  3664.     set badalias $badchan
  3665.     if {$last > 0} {
  3666.         set last [expr $last - 1]
  3667.         set lastname [lindex $chans $last]
  3668.         set lasttype [ma_ch_table_type_get $lastname]
  3669.         # found it
  3670.         if {"$lasttype" == "baduser"} {
  3671.             set baduserfound $last
  3672.             if {"$badchan" == "baduser"} {
  3673.                 set found $last
  3674.                 set badalias $lastname
  3675.             }
  3676.         }
  3677.     }
  3678.     # create channel if needed
  3679.     if {$found == -1} {
  3680.         set ret [ma_ch_create $badchan]
  3681.         ma_ch_equate_set $badchan P "\[IPC\]"
  3682.         if {"$badchan" == "badhost"} {
  3683.             ma_ch_table_type_set $badchan remote
  3684.         }
  3685.         if {"$badchan" == "baduser"} {
  3686.             ma_ch_table_type_set $badchan baduser
  3687.         }
  3688.         # have channel name, need to get channel object
  3689.         set children [mai_get_children $channels]
  3690.         foreach child $children {
  3691.             # default for our new channel
  3692.             set tmpname [lindex $child $MS(name)]
  3693.             if {"$tmpname" != "$badchan"} {
  3694.                 continue
  3695.             }
  3696.             set tmpchildren [mai_get_children $child]
  3697.             foreach tmpchild $tmpchildren {
  3698.                 set tmplist [mai_prop_def $tmpchild]
  3699.                 mai_prop_set $tmpchild $tmplist
  3700.             }
  3701.             break
  3702.         }
  3703.         # now set ordering
  3704.         mai_channel_order_set $badchan
  3705.     }
  3706.     # now expand the channels container and $badchan channel.
  3707.     # and select the host field and call mai_modify on it.
  3708.     mai_expand $chs_index
  3709.     # looking for badalias now
  3710.     set length [llength $mainscreen_db]
  3711.     loop i 0 $length {
  3712.         set channel [lindex $mainscreen_db $i]
  3713.         set type [lindex $channel $MS(type)]
  3714.         if {"$type" != "channel"} {
  3715.             continue
  3716.         }
  3717.         set name [lindex $channel $MS(name)]
  3718.         if {"$name" == "$badalias"} {
  3719.             set badchanindex $i
  3720.             break
  3721.         }
  3722.     }
  3723.     # have our $badchan index, find host field
  3724.     mai_expand $badchanindex
  3725.     set length [llength $mainscreen_db]
  3726.     loop i $badchanindex $length {
  3727.         set prop [lindex $mainscreen_db $i]
  3728.         set class [lindex $prop $MS(class)]
  3729.         if {"$class" != "property"} {
  3730.             continue
  3731.         }
  3732.         set name [lindex $prop $MS(name)]
  3733.         if {"$name" == "chost"} {
  3734.             set hostindex $i
  3735.             break
  3736.         }
  3737.     }
  3738.     # have our host index, select in onscreen
  3739.     mag_display_mainlist $hostindex $hostindex $hostindex
  3740.     # now scroll if necessary to get selected item on screen
  3741.     set rows [VtGetValues $main_list -rows]
  3742.     set pos [VtGetValues $main_list -topItemPosition]
  3743.     set spos [expr $hostindex - $pos + 2]
  3744.     # if offscreen then fix up so host is last line on screen
  3745.     if {$spos >= $rows || $spos < 0} {
  3746.         set mpos [expr $hostindex - $rows + 2]
  3747.         VtSetValues $main_list -topItemPosition $mpos
  3748.     }
  3749.     # call mai_modify
  3750.     set modret [mai_modify $hostindex]
  3751.     # get host property's value:
  3752.     #       - if NONE, and this is baduser channel then we must always
  3753.     #         delete this channel
  3754.     #       - if this is badhost channel, host can be either NONE or
  3755.     #         a hostname-- so we delete only if the user had pressed
  3756.     #         Cancel, and the channel did not already exist!
  3757.     set object [lindex $mainscreen_db $hostindex]
  3758.     set value [lindex $object $MS(value)]
  3759.     if {"$badchan" == "baduser" && "$value" == "[mag_msg NONE]" || \
  3760.         "$badchan" == "badhost" && "$modret" == "no" && $found == -1} {
  3761.         # select our $badchan container
  3762.         mao_delete $badchanindex
  3763.     }
  3764.     if {"$badchan" == "badhost" && "$modret" == "yes"} {
  3765.         set DIRTY 1
  3766.     }
  3767. }
  3768. proc \
  3769. mao_mhome {} \
  3770. {
  3771.     global mainscreen_db MS main_list MULTIHOME MDOMAINDB DIRTY
  3772.     # find channels container
  3773.     set length [llength $mainscreen_db]
  3774.     loop i 0 $length {
  3775.         set channels [lindex $mainscreen_db $i]
  3776.         set type [lindex $channels $MS(type)]
  3777.         if {"$type" == "channels"} {
  3778.             break
  3779.         }
  3780.     }
  3781.     # have channels container
  3782.     set chs_index $i
  3783.     set chs_state [lindex $channels $MS(state)]
  3784.     if {"$chs_state" == "open"} {
  3785.         mai_collapse $chs_index
  3786.     }
  3787.     # setup for search
  3788.     set chans [mai_ch_names_get]
  3789.     # check if a multihome channel exists, we depend on the name
  3790.     set mhomefound 0
  3791.     set mhomeindex [lsearch -exact $chans multihome]
  3792.     if {$mhomeindex >= 0} {
  3793.         set mhomefound 1
  3794.     }
  3795.     if {$mhomefound == 0} {
  3796.         # create multihome channel
  3797.         set ret [ma_ch_create multihome]
  3798.         ma_ch_equate_set multihome P $MULTIHOME
  3799.         ma_ch_table_type_set multihome file
  3800.         set children [mai_get_children $channels]
  3801.         foreach child $children {
  3802.             # default for our new channel
  3803.             set tmpname [lindex $child $MS(name)]
  3804.             if {"$tmpname" != "multihome"} {
  3805.                 continue
  3806.             }
  3807.             set tmpchildren [mai_get_children $child]
  3808.             foreach tmpchild $tmpchildren {
  3809.                 set tmplist [mai_prop_def $tmpchild]
  3810.                 mai_prop_set $tmpchild $tmplist
  3811.             }
  3812.             break
  3813.         }
  3814.         ma_ch_table_file_set multihome $MDOMAINDB
  3815.         # set the V macro-- check_rcpt depends upon this to
  3816.         # know whether virtual domains map exists, and it should
  3817.         # check hosts in the map
  3818.         ma_multihome_macro_set 1
  3819.         # now set ordering
  3820.         ma_ch_sequence_set multihome 0
  3821.         set order 1
  3822.         foreach i $chans {
  3823.             ma_ch_sequence_set $i $order
  3824.             set order [expr $order + 1]
  3825.         }
  3826.     } else {
  3827.         # delete multihome channel
  3828.         set order 0
  3829.         foreach i $chans {
  3830.             if {"$i" == "multihome"} {
  3831.                 ma_ch_delete multihome
  3832.                 continue
  3833.             }
  3834.             ma_ch_sequence_set $i $order
  3835.             set order [expr $order + 1]
  3836.         }
  3837.         # unset the V macro-- check_rcpt depends upon this to
  3838.         # know whether virtual domains map exists and it should
  3839.         # check hosts in the map
  3840.         ma_multihome_macro_set 0
  3841.     }
  3842.     # now expand the channels container
  3843.     mai_expand $chs_index
  3844.     # now scroll if necessary to make all channels visible
  3845.     set rows [VtGetValues $main_list -rows]
  3846.     set pos [VtGetValues $main_list -topItemPosition]
  3847.     set last [llength $mainscreen_db]
  3848.     set spos [expr $last - $pos + 2]
  3849.     # if offscreen then fix up so last channel is last line on screen
  3850.     if {$spos >= $rows || $spos < 0} {
  3851.         set mpos [expr $last - $rows + 2]
  3852.         VtSetValues $main_list -topItemPosition $mpos
  3853.     }
  3854.     set DIRTY 1
  3855. }
  3856. proc \
  3857. mao_uucp {} \
  3858. {
  3859.     global mainscreen_db MS main_list UUX UUCPDB DIRTY
  3860.     # find channels container
  3861.     set length [llength $mainscreen_db]
  3862.     loop i 0 $length {
  3863.         set channels [lindex $mainscreen_db $i]
  3864.         set type [lindex $channels $MS(type)]
  3865.         if {"$type" == "channels"} {
  3866.             break
  3867.         }
  3868.     }
  3869.     # have channels container
  3870.     set chs_index $i
  3871.     set chs_state [lindex $channels $MS(state)]
  3872.     if {"$chs_state" == "open"} {
  3873.         mai_collapse $chs_index
  3874.     }
  3875.     # setup for search
  3876.     set chans [mai_ch_names_get]
  3877.     # check if a UUCP channel exists, we depend on the name
  3878.     set uucpfound 0
  3879.     set uucpindex [lsearch -exact $chans UUCP]
  3880.     if {$uucpindex >= 0} {
  3881.         set uucpfound 1
  3882.     }
  3883.     if {$uucpfound == 0} {
  3884.         # create UUCP channel
  3885.         set ret [ma_ch_create UUCP]
  3886.         ma_ch_equate_set UUCP P $UUX
  3887.         ma_ch_table_type_set UUCP UUCP
  3888.         set children [mai_get_children $channels]
  3889.         foreach child $children {
  3890.             # default for our new channel
  3891.             set tmpname [lindex $child $MS(name)]
  3892.             if {"$tmpname" != "UUCP"} {
  3893.                 continue
  3894.             }
  3895.             set tmpchildren [mai_get_children $child]
  3896.             foreach tmpchild $tmpchildren {
  3897.                 set tmplist [mai_prop_def $tmpchild]
  3898.                 mai_prop_set $tmpchild $tmplist
  3899.             }
  3900.             break
  3901.         }
  3902.         # now set ordering
  3903.         ma_ch_sequence_set UUCP 0
  3904.         set order 1
  3905.         foreach i $chans {
  3906.             ma_ch_sequence_set $i $order
  3907.             set order [expr $order + 1]
  3908.         }
  3909.     } else {
  3910.         # delete UUCP channel
  3911.         set order 0
  3912.         foreach i $chans {
  3913.             if {"$i" == "UUCP"} {
  3914.                 ma_ch_delete UUCP
  3915.                 continue
  3916.             }
  3917.             ma_ch_sequence_set $i $order
  3918.             set order [expr $order + 1]
  3919.         }
  3920.     }
  3921.     # now expand the channels container
  3922.     mai_expand $chs_index
  3923.     # now scroll if necessary to make all channels visible
  3924.     set rows [VtGetValues $main_list -rows]
  3925.     set pos [VtGetValues $main_list -topItemPosition]
  3926.     set last [llength $mainscreen_db]
  3927.     set spos [expr $last - $pos + 2]
  3928.     # if offscreen then fix up so last channel is last line on screen
  3929.     if {$spos >= $rows || $spos < 0} {
  3930.         set mpos [expr $last - $rows + 2]
  3931.         VtSetValues $main_list -topItemPosition $mpos
  3932.     }
  3933.     set DIRTY 1
  3934. }
  3935. proc \
  3936. mag_channel_create { index } \
  3937. {
  3938.     global mainscreen_db MS MAILTABLE
  3939.     # initial values
  3940.     set name [mag_msg NEW]
  3941.     set program /etc/mail/$name
  3942.     set table [mag_table_to_external file]
  3943.     set done no
  3944.     while {"$done" == "no"} {
  3945.         # call channel dialog first to get new channel data
  3946.         set list [list $name $program $table]
  3947.         set list [mai_channel_dialog $list]
  3948.         # user hit cancel
  3949.         if {"$list" == ""} {
  3950.             return
  3951.         }
  3952.         # validate new values
  3953.         set name [lindex $list 0]
  3954.         set program [lindex $list 1]
  3955.         set table [lindex $list 2]
  3956.         # channel name cannot conflict
  3957.         set list [ma_ch_names_get]
  3958.         if {[lsearch $list $name] >= 0} {
  3959.             VtUnLock
  3960.             mag_error CONFLICT
  3961.             VtLock
  3962.             continue
  3963.         }
  3964.         # program name must be entered
  3965.         if {"$program" == ""} {
  3966.             VtUnLock
  3967.             mag_error NULL
  3968.             VtLock
  3969.             continue
  3970.         }
  3971.         # no blanks allowed
  3972.         if {[string first " " $program] >=0} {
  3973.             VtUnLock
  3974.             mag_error1 INVALID $program
  3975.             VtLock
  3976.             continue
  3977.         }
  3978.         # program name should exist
  3979.         if {"$program" != "SMTP"} {
  3980.             if {[mag_remote_file_exists $program] == 0} {
  3981.                 VtUnLock
  3982.                 set ret [mag_query_qyn NOEXIST_IGNORE $program]
  3983.                 VtLock
  3984.                 if {"$ret" == "no"} {
  3985.                     continue
  3986.                 }
  3987.             }
  3988.         }
  3989.         # table type must be one of several enumerated values.
  3990.         set list [mag_table_enum]
  3991.         if {[lsearch $list $table] == -1} {
  3992.             VtUnLock
  3993.             mag_error1 INVALID_TABLE $table
  3994.             VtLock
  3995.             continue
  3996.         }
  3997.         # have picked a set of valid values, now create the channel
  3998.         set ret [ma_ch_create $name]
  3999.         switch $ret {
  4000.         "conflict" {
  4001.             VtUnLock
  4002.             mag_error CONFLICT
  4003.             VtLock
  4004.             continue
  4005.         }
  4006.         "badname" {
  4007.             VtUnLock
  4008.             mag_error1 INVALID_NAME $name
  4009.             VtLock
  4010.             continue
  4011.         }
  4012.         }
  4013.         # everything appears ok
  4014.         break
  4015.     }
  4016.     # finish off channel parameters
  4017.     ma_ch_equate_set $name P $program
  4018.     ma_ch_table_type_set $name [mag_table_to_internal $table]
  4019.     # set ordering, add to end, or next to end if baduser is last, we could
  4020.     # be baduser as well.  Only one baduser is allowed.
  4021.     set ret [mai_channel_order_set $name]
  4022.     if {"$ret" != "ok"} {
  4023.         ma_ch_delete $name
  4024.         # error
  4025.         VtUnLock
  4026.         mag_error BADUSER_ONLY
  4027.         VtLock
  4028.         return
  4029.     }
  4030.     # channel now exists in the back-end, we have to draw it onscreen.
  4031.     # collapse onscreen channels container
  4032.     mai_collapse $index
  4033.     # expand back again, this adds the new channel onscreen.
  4034.     mai_expand $index
  4035.     # now find the new channel.
  4036.     set start [expr $index + 1]
  4037.     set stop [llength $mainscreen_db]
  4038.     loop i $start $stop {
  4039.         set channel [lindex $mainscreen_db $i]
  4040.         set tmpname [lindex $channel $MS(name)]
  4041.         if {"$name" == "$tmpname"} {
  4042.             set found $i
  4043.             break
  4044.         }
  4045.     }
  4046.     # set all values in the channel to default values
  4047.     mao_default $found no
  4048.     # select the new channel
  4049.     mag_display_mainlist $found $found $found
  4050.     # expand the new channel
  4051.     mai_expand $found
  4052. }
  4053. proc \
  4054. mai_channel_dialog { list } \
  4055. {
  4056.     global ME PID
  4057.     # file is used to pass results to preserve stdout for child process.
  4058.     set file "/tmp/mag.PID"
  4059.     system "rm -f $file"
  4060.     VtControl -suspend
  4061.     set escape [mag_escape $list]
  4062.     system "$ME -mag_stand_channel \"$escape\" $file"
  4063.     VtControl -resume
  4064.     if {[file exists $file] == 1} {
  4065.         set result [exec cat $file]
  4066.         system "rm -f $file"
  4067.     } else {
  4068.         set result ""
  4069.     }
  4070.     return $result
  4071. }
  4072. proc \
  4073. mag_stand_channel { list file } \
  4074. {
  4075.     global app MS SLOCAL UUX MULTIHOME
  4076.     global mag_stand_name mag_stand_program mag_stand_table
  4077.     global mag_stand_outfile
  4078.     set app [VtOpen mailchild "mailadmin"]
  4079.     mag_setcat SCO_MAIL_ADMIN
  4080.     set name [lindex $list 0]
  4081.     set program [lindex $list 1]
  4082.     set table [lindex $list 2]
  4083.     set mag_stand_outfile $file
  4084.     # std dialog box.
  4085.     set mag_stand_form [ \
  4086.         VtFormDialog $app.mailchild \
  4087.         -title [mag_msg NEW_CHANNEL] \
  4088.         -resizable FALSE \
  4089.         -ok -okCallback mag_stand_channel_ok \
  4090.         -cancel -cancelCallback mag_stand_channel_quit \
  4091.         -wmCloseCallback mag_stand_channel_quit
  4092.     ]
  4093.     VtLabel $mag_stand_form.label1 -label [mag_msg CH_NAME]
  4094.     set mag_stand_name [ \
  4095.         VtText $mag_stand_form.name \
  4096.         -columns 50 \
  4097.         -value $name \
  4098.     ]
  4099.     VtLabel $mag_stand_form.label2 -label [mag_msg CH_PROGRAM]
  4100.     set programs [list $SLOCAL SMTP $UUX $MULTIHOME]
  4101.     set mag_stand_program [ \
  4102.         VtComboBox $mag_stand_form.program \
  4103.         -itemList $programs \
  4104.         -leftSide FORM -rightSide FORM \
  4105.         -value $program \
  4106.     ]
  4107.     VtLabel $mag_stand_form.label3 -label [mag_msg CH_TABLE]
  4108.     set enum [mag_table_enum]
  4109.     set mag_stand_table [ \
  4110.         VtComboBox $mag_stand_form.table \
  4111.         -itemList $enum \
  4112.         -leftSide FORM -rightSide FORM \
  4113.         -value $table \
  4114.     ]
  4115.     VtSetValues $mag_stand_name \
  4116.         -callback "mag_stand_jump $mag_stand_program"
  4117.     VtSetValues $mag_stand_program \
  4118.         -callback "mag_stand_jump $mag_stand_table"
  4119.     VtSetValues $mag_stand_table \
  4120.         -callback "mag_stand_jump [VtGetValues $mag_stand_form -ok]"
  4121.     VtShow $mag_stand_form
  4122.     VtSetFocus $mag_stand_name
  4123.     VtMainLoop
  4124. }
  4125. proc \
  4126. mag_stand_channel_ok { cbs } \
  4127. {
  4128.     global mag_stand_name mag_stand_program mag_stand_table
  4129.     global mag_stand_outfile
  4130.     set name [VtGetValues $mag_stand_name -value]
  4131.     set program [VtGetValues $mag_stand_program -value]
  4132.     set table [VtGetValues $mag_stand_table -value]
  4133.     set list [list $name $program $table]
  4134.     # our return value is sent to outfile
  4135.     if {[catch {open $mag_stand_outfile w} fd] == 0} {
  4136.         puts $fd $list
  4137.         close $fd
  4138.     }
  4139.     VtClose
  4140.     exit 0
  4141. }
  4142. proc \
  4143. mag_stand_channel_quit { cbs } \
  4144. {
  4145.     VtClose
  4146.     exit 0
  4147. }
  4148. proc \
  4149. mai_channel_order_set { name } \
  4150. {
  4151.     # find out if any other bad user channels
  4152.     set names [mai_ch_names_get]
  4153.     set found ""
  4154.     foreach channel $names {
  4155.         if {"$channel" == "$name"} {
  4156.             continue
  4157.         }
  4158.         set type [ma_ch_table_type_get $channel]
  4159.         if {"$type" == "baduser"} {
  4160.             set found $channel
  4161.             break
  4162.         }
  4163.     }
  4164.     # find out if we are baduser
  4165.     set type [ma_ch_table_type_get $name]
  4166.     if {"$type" == "baduser" && "$found" != ""} {
  4167.         # there can only be one baduser channel
  4168.         if {"$found" != ""} {
  4169.             return fail
  4170.         }
  4171.     }
  4172.     set len [llength $names]
  4173.     # subtract ourself off
  4174.     set len [expr $len - 1]
  4175.     set prev [expr $len - 1]
  4176.     if {"$found" == ""} {
  4177.         # add to end of list
  4178.         ma_ch_sequence_set $name $len
  4179.     } else {
  4180.         # add in front of bad user channel
  4181.         ma_ch_sequence_set $name $prev
  4182.         ma_ch_sequence_set $found $len
  4183.     }    
  4184.     return ok
  4185. }
  4186. proc \
  4187. mag_open_host {} \
  4188. {
  4189.     global mag_host_name mag_host_label mag_host_resolv outerMainForm
  4190.     global mainscreen_db
  4191.     # first save any previous changes, but keep open for cancel.
  4192.     set ret [mag_all_put]
  4193.     switch $ret {
  4194.     "ok" {
  4195.     }
  4196.     "fail" {
  4197.         return
  4198.     }
  4199.     "cancel" {
  4200.         return
  4201.     }
  4202.     }
  4203.     # put up open host dialog and get result
  4204.     set newhost [mag_open_host_dialog]
  4205.     if {"$newhost" == ""} {
  4206.         return
  4207.     }
  4208.     # get full name of remote machine
  4209.     set newhost [mag_host_resolv $newhost]
  4210.     # save old host name for backout
  4211.     set oldhost $mag_host_name
  4212.     # check if new host there
  4213.     set ret [mag_host_check $newhost]
  4214.     if {"$ret" != "ok"} {
  4215.         VtUnLock
  4216.         mag_error1 BADHOST $newhost
  4217.         VtLock
  4218.         return
  4219.     }
  4220.     # set new host name
  4221.     set mag_host_name $newhost
  4222.     set ret [mag_cf_get]
  4223.     if {"$ret" == "no"} {
  4224.         mag_host_backout $oldhost
  4225.         return
  4226.     }
  4227.     if {"$ret" == "fail"} {
  4228.         mag_host_backout $oldhost
  4229.         return
  4230.     }
  4231.     set ret [mag_ms1_get]
  4232.     if {"$ret" == "no"} {
  4233.         mag_host_backout $oldhost
  4234.         return
  4235.     }
  4236.     if {"$ret" == "fail"} {
  4237.         mag_host_backout $oldhost
  4238.         return
  4239.     }
  4240.     VtSetValues $outerMainForm -title [mag_msg1 WIN_TITLE \
  4241.         [mag_short_name_default]]
  4242.     VtSetValues $mag_host_label -label [mag_msg1 TITLE $mag_host_name]
  4243.     # clear and redraw main list
  4244.     mag_delete_mainlist -1 [llength $mainscreen_db]
  4245.         mao_init
  4246.         mag_insert_mainlist -1 [llength $mainscreen_db]
  4247.         mag_display_mainlist 0 1 0
  4248. }
  4249. proc \
  4250. mag_host_backout { oldhost } \
  4251. {
  4252.     global mag_host_name mag_host_label DIRTY
  4253.     VtUnLock
  4254.     set ret [mag_query_qyn GO_BACK $oldhost]
  4255.     VtLock
  4256.     if {"$ret" != "yes"} {
  4257.         quit
  4258.     }
  4259.     set mag_host_name $oldhost
  4260.     set DIRTY 0
  4261.     set ret [mag_cf_get]
  4262.     if {"$ret" == "no"} {
  4263.         quit
  4264.     }
  4265.     if {"$ret" == "fail"} {
  4266.         quit
  4267.     }
  4268.     set ret [mag_ms1_get]
  4269.     if {"$ret" == "no"} {
  4270.         quit
  4271.     }
  4272.     if {"$ret" == "fail"} {
  4273.         quit
  4274.     }
  4275. }
  4276. proc \
  4277. mag_open_host_dialog {} \
  4278. {
  4279.     global ME PID
  4280.     # file is used to pass results to preserve stdout for child process.
  4281.     set file "/tmp/mag.$PID"
  4282.     system "rm -f $file"
  4283.     VtControl -suspend
  4284.     system "$ME -mag_stand_host $file"
  4285.     VtControl -resume
  4286.     if {[file exists $file] == 1} {
  4287.         set result [exec cat $file]
  4288.         system "rm -f $file"
  4289.     } else {
  4290.         set result ""
  4291.     }
  4292.     return $result
  4293. }
  4294. proc \
  4295. mag_stand_host { file } \
  4296. {
  4297.     global app
  4298.     global mag_stand_text mag_stand_outfile mag_stand_form
  4299.     # globals for callbacks
  4300.     set mag_stand_outfile $file
  4301.     # init widget server
  4302.     set app [VtOpen mailchild "mailadmin"]
  4303.     mag_setcat SCO_MAIL_ADMIN
  4304.     # std dialog box.
  4305.     set mag_stand_form [ \
  4306.         VtFormDialog $app.mailchild \
  4307.         -title [mag_msg TITLE_OPEN] \
  4308.         -resizable FALSE \
  4309.         -ok -okCallback mag_stand_host_ok \
  4310.         -cancel -cancelCallback mag_stand_open_quit \
  4311.         -wmCloseCallback mag_stand_open_quit \
  4312.     ]
  4313.     set mag_stand_text [ \
  4314.         VtText $mag_stand_form.text \
  4315.         -columns 40 \
  4316.         -callback mag_stand_host_jump \
  4317.     ]
  4318.     VtPushButton $mag_stand_form.browse \
  4319.         -leftSide $mag_stand_text \
  4320.         -topSide FORM \
  4321.         -callback mag_stand_host_browse \
  4322.         -label [mag_msg STR_SELECT]
  4323.     VtShow $mag_stand_form
  4324.     VtSetFocus $mag_stand_text
  4325.     VtMainLoop
  4326. }
  4327. proc \
  4328. mag_stand_host_jump { cbs } \
  4329. {
  4330.     global mag_stand_form
  4331.     set ok [VtGetValues $mag_stand_form -ok]
  4332.     VtSetFocus $ok
  4333. }
  4334. proc \
  4335. mag_stand_host_browse { cbs } \
  4336. {
  4337.     global mag_stand_form
  4338.     keylset parms parent $mag_stand_form
  4339.     keylset parms instance abc
  4340.     keylset parms labeltext [mag_msg MENU_HOST]
  4341.     keylset parms buttontext [mag_msg STR_SELECT]
  4342.     keylset parms userproc mag_stand_host_browse_done
  4343.     SaSelectHostDialog $parms $cbs
  4344. }
  4345. proc \
  4346. mag_stand_host_browse_done { cbs } \
  4347. {
  4348.     global mag_stand_text
  4349.     set value [SaSelectHostGetSelection abc]
  4350.     VtSetValues $mag_stand_text -value $value
  4351. }
  4352. proc \
  4353. mag_stand_host_ok { cbs } \
  4354. {
  4355.     global mag_stand_text mag_stand_outfile
  4356.     set value [VtGetValues $mag_stand_text -value]
  4357.     if {[catch {open $mag_stand_outfile w} fd] == 0} {
  4358.         puts $fd $value
  4359.         close $fd
  4360.     }
  4361.     VtClose
  4362.     exit 0
  4363. }
  4364. proc \
  4365. mag_stand_open_quit { cbs } \
  4366. {
  4367.     VtClose
  4368.     exit 0
  4369. }
  4370. proc \
  4371. mag_host_check { host } \
  4372. {
  4373.     global mag_host_name mag_local_host
  4374.     if {"$host" == "$mag_local_host"} {
  4375.         return "ok"
  4376.     }
  4377.     set class [ list sco remoteCommand ]
  4378.     set instance [GetInstanceList NULL $host]
  4379.     set command [list ObjectAction $class $instance uname "-n"]
  4380.     set result [SaMakeObjectCall $command]
  4381.     set result [lindex $result 0]
  4382.     if { [BmipResponseErrorIsPresent result] } {
  4383.         return fail
  4384.     }
  4385.     set retStr [BmipResponseActionInfo result]
  4386.     return ok
  4387. }
  4388. proc \
  4389. mag_remote_copyout { src dst } \
  4390. {
  4391.     global mag_host_name mag_local_host
  4392.     if {"$mag_host_name" == "$mag_local_host"} {
  4393.         return [mag_local_copy $src $dst]
  4394.     }
  4395.     set host $mag_host_name
  4396.     set instance [GetInstanceList NULL $host]
  4397.     set uid [id effective userid]
  4398.     if {$uid == 0} {
  4399.         if {[catch {system "/bin/rcp $src $host:$dst >/dev/null 2>&1"} ret] == 0} {
  4400.             return ok
  4401.         } else {
  4402.             return fail
  4403.         }
  4404.     } else {
  4405.         # first copy to a temp file on remote machine
  4406.         set tmp "/tmp/[file tail $src].[pid]"
  4407.         if {[catch {system "/bin/rcp $src $host:$tmp >/dev/null 2>&1"} ret] != 0} {
  4408.             return fail
  4409.         }
  4410.         # then on remote machine, copy the temp file to destination,
  4411.         # using tfadmin cpfile
  4412.         set class [list sco remoteCommand]
  4413.         set command [list ObjectAction $class $instance /sbin/tfadmin "cpfile $tmp $dst"]
  4414.         set result [SaMakeObjectCall $command]
  4415.         set result [lindex $result 0]
  4416.         if {[BmipResponseErrorIsPresent result]} {
  4417.             return fail
  4418.         }
  4419.         # now remove the temp file on remote machine
  4420.         set class [list sco remoteCommand]
  4421.         set command [list ObjectAction $class $instance /bin/rm "-f $tmp"]
  4422.         set result [SaMakeObjectCall $command]
  4423.         return ok
  4424.     }
  4425. }
  4426. proc \
  4427. mag_remote_copyin { src dst } \
  4428. {
  4429.     global mag_host_name mag_local_host
  4430.     if {"$mag_host_name" == "$mag_local_host"} {
  4431.         return [mag_local_copy $src $dst]
  4432.     }
  4433.     set host $mag_host_name
  4434.     set instance [GetInstanceList NULL $host]
  4435.     set uid [id effective userid]
  4436.     if {$uid == 0} {
  4437.         if {[catch {system "/bin/rcp $mag_host_name:$src $dst >/dev/null 2>&1"} ret] == 0} {
  4438.             return ok
  4439.         } else {
  4440.             return fail
  4441.         }
  4442.     } else {
  4443.         # copy to a temp file on remote machine, using tfadmin
  4444.         set tmp "/tmp/[file tail $src].[pid]"
  4445.         set class [list sco remoteCommand]
  4446.         set command [list ObjectAction $class $instance /sbin/tfadmin "cpfile $src $tmp"]
  4447.         set result [SaMakeObjectCall $command]
  4448.         set result [lindex $result 0]
  4449.         if {[BmipResponseErrorIsPresent result]} {
  4450.             return fail
  4451.         }
  4452.         # copy the remote temp file in to local destination using rcp
  4453.         if {[catch {system "/bin/rcp $mag_host_name:$tmp $dst >/dev/null 2>&1"} ret] != 0} {
  4454.                         return fail
  4455.                 }
  4456.         # remove the temp file on remote machine
  4457.         set class [list sco remoteCommand]
  4458.         set command [list ObjectAction $class $instance /bin/rm "-f $tmp"]
  4459.         set result [SaMakeObjectCall $command]
  4460.         return ok
  4461.     }
  4462. }
  4463. proc \
  4464. mag_local_copy { src dst } \
  4465. {
  4466.     set uid [id effective userid]
  4467.     if {$uid == 0} {
  4468.         catch {system "copy $src $dst > /dev/null 2>&1"} ret
  4469.     } else {
  4470.         catch {system "/sbin/tfadmin cpfile $src $dst > /dev/null 2>&1"} ret
  4471.     }
  4472.     if {"$ret" == 0} {
  4473.         return ok
  4474.     } else {
  4475.         return fail
  4476.     }
  4477. }
  4478. proc \
  4479. GetInstanceList { names host } \
  4480. {
  4481.     set instanceList {}
  4482.     if { $host == "localhost" } {
  4483.         foreach name $names {
  4484.             set instance [list $name]
  4485.             lappend instanceList $instance
  4486.         }
  4487.     } else {
  4488.         foreach name $names {
  4489.             set instance [list [list systemId $host] [list $name]]
  4490.             lappend instanceList $instance
  4491.         }
  4492.     }
  4493.     return $instanceList
  4494. }
  4495. proc \
  4496. mag_restart_sendmail { prompt } \
  4497. {
  4498.     global mag_host_name mag_local_host SENDMAILPID
  4499.     set uid [id effective userid]
  4500.     if {"$mag_host_name" == "$mag_local_host"} {
  4501.         if {$uid == 0} {
  4502.             system "kill -HUP `head -1 $SENDMAILPID`"
  4503.         } else {
  4504.             system "/sbin/tfadmin kill -HUP `head -1 $SENDMAILPID`"
  4505.         }
  4506.         return ok
  4507.     }
  4508.     set class [ list sco remoteCommand ]
  4509.     set instance [GetInstanceList NULL $mag_host_name]
  4510.     if {$uid == 0} {
  4511.         set command [list ObjectAction $class $instance \
  4512.             "/usr/bin/kill" "-HUP `head -1 $SENDMAILPID`"]
  4513.     } else {
  4514.         set command [list ObjectAction $class $instance \
  4515.             "/sbin/tfadmin" "kill -HUP `head -1 $SENDMAILPID`"]
  4516.     }
  4517.     set result [SaMakeObjectCall $command]
  4518.     set result [lindex $result 0]
  4519.     if { [BmipResponseErrorIsPresent result] } {
  4520.         if {"$prompt" == "yes"} {
  4521.             VtUnLock
  4522.             mag_error SENDMAIL_RESTART
  4523.             VtLock
  4524.         }
  4525.         return fail
  4526.     }
  4527.     return ok
  4528. }
  4529. proc \
  4530. mag_host_local {} \
  4531. {
  4532.     set localhost [exec uname -n]
  4533.     set fqdn [mag_host_resolv $localhost]
  4534.     return $fqdn
  4535. }
  4536. proc \
  4537. mag_host_resolv { hostname } \
  4538. {
  4539.     global RESOLVER
  4540.     set ret [catch {exec $RESOLVER $hostname} hostlist]
  4541.     if {"$ret" != "0"} {
  4542.         return $hostname
  4543.     }
  4544.     set newhost [lindex $hostlist 0]
  4545.     return $newhost
  4546. }
  4547. proc \
  4548. mag_list_users {} \
  4549. {
  4550.     global mag_host_name mag_local_host
  4551.     if {"$mag_host_name" == "$mag_local_host"} {
  4552.         return [SaUsersGet]
  4553.     } else {
  4554.         return [SaUsersGet $mag_host_name]
  4555.     }
  4556. }
  4557. proc \
  4558. mag_list_groups {} \
  4559. {
  4560.     global mag_host_name mag_local_host
  4561.     if {"$mag_host_name" == "$mag_local_host"} {
  4562.         return [SaGroupsGet]
  4563.     } else {
  4564.         return [SaGroupsGet $mag_host_name]
  4565.     }
  4566. }
  4567. proc \
  4568. mag_remote_file_exists { path } \
  4569. {
  4570.     global mag_host_name mag_local_host
  4571.     if {"$mag_host_name" == "$mag_local_host"} {
  4572.         return [file exists $path]
  4573.     }
  4574.     set host $mag_host_name
  4575.     set class [list sco remoteCommand]
  4576.     set instance [GetInstanceList NULL $host]
  4577.     set command [list ObjectAction $class $instance file $path]
  4578.     set result [SaMakeObjectCall $command]
  4579.     set result [lindex $result 0]
  4580.     if { [BmipResponseErrorIsPresent result] } {
  4581.         return 0
  4582.     }
  4583.     return 1
  4584. }
  4585. proc \
  4586. mag_cmd_line_main {} \
  4587. {
  4588.     global argv argv0 mag_host_name DIRTY
  4589.     if {"$argv" == ""} {
  4590.         return
  4591.     }
  4592.         # check if remote host is there
  4593.         if {"[mag_host_check $mag_host_name]" != "ok"} {
  4594.                 echo "mailadmin: Unable to connect to host $mag_host_name"
  4595.                 exit 0
  4596.         }
  4597.     # check authorizations
  4598.     if {"[mag_authorized $mag_host_name]" == "fail"} {
  4599.         echo "mailadmin: You are not authorized to run the Mail Manager on [mag_short_name_default]"
  4600.         exit 0
  4601.     }
  4602.     # get our remote files from the appropriate host
  4603.     mag_cmd_file_get
  4604.     set DIRTY 0
  4605.     # now process rest of command line
  4606.     while {"$argv" != ""} {
  4607.         # do one command
  4608.         mag_cmd_one
  4609.     }
  4610.     # put our remote files
  4611.     mag_cmd_file_put
  4612.     mag_cmd_quit 0
  4613. }
  4614. proc \
  4615. mag_cmd_one {} \
  4616. {
  4617.     global CMD argv DIRTY
  4618.     set cmd [mag_cmd_popargv]
  4619.     set CMD $cmd
  4620.     switch -- "$cmd" {
  4621.     "sendmail" {
  4622.         set action [mag_cmd_popargv]
  4623.         if {"$action" != "restart"} {
  4624.             echo "mailadmin: Unknown sendmail action: $action"
  4625.             mag_cmd_quit 1
  4626.         }
  4627.         mag_restart_sendmail no
  4628.     }
  4629.     "uucp" {
  4630.         set action [mag_cmd_popargv]
  4631.         if {"$action" != "rebuild"} {
  4632.             echo "mailadmin: Unknown uucp action: $action"
  4633.             mag_cmd_quit 1
  4634.         }
  4635.         mag_rebuild_uucp_map no
  4636.     }
  4637.     "add" {
  4638.         set DIRTY 1
  4639.         set type [mag_cmd_popargv]
  4640.         set name [mag_cmd_popargv]
  4641.         switch "$type" {
  4642.         "map" {
  4643.             set list [ma_aliases_get]
  4644.             if {[lsearch $list $name] >= 0} {
  4645.                 echo "mailadmin: Duplicate map name for add: $name"
  4646.                 mag_cmd_quit 1
  4647.             }
  4648.             lappend list $name
  4649.             ma_aliases_set $list
  4650.         }
  4651.         "altname" {
  4652.             set list [ma_alternate_names_get]
  4653.             if {[lsearch $list $name] >= 0} {
  4654.                 echo "mailadmin: Duplicate altname for add: $name"
  4655.                 mag_cmd_quit 1
  4656.             }
  4657.             lappend list $name
  4658.             ma_alternate_names_set $list
  4659.         }
  4660.         "channel" {
  4661.             set list [mai_ch_names_get]
  4662.             set program [mag_cmd_popargv]
  4663.             set table [mag_cmd_popargv]
  4664.             if {[lsearch $list $name] >= 0} {
  4665.                 echo "mailadmin: Duplicate channel name for add: $name"
  4666.                 mag_cmd_quit 1
  4667.             }
  4668.             set ret [ma_ch_create $name]
  4669.             switch "$ret" {
  4670.             "conflict" {
  4671.                 echo "mailadmin: Name conflict or reserved name: $name"
  4672.                 mag_cmd_quit 1
  4673.             }
  4674.             "badname" {
  4675.                 echo "mailadmin: Invalid channel name: $name"
  4676.                 mag_cmd_quit 1
  4677.             }
  4678.             }
  4679.             ma_ch_equate_set $name P $program
  4680.             mag_cmd_table_type_check $table
  4681.             ma_ch_table_type_set $name $table
  4682.             set ret [mai_channel_order_set $name]
  4683.             if {"$ret" != "ok"} {
  4684.                 echo "mailadmin: Only one baduser channel may exist."
  4685.                 mag_cmd_quit 1
  4686.             }
  4687.             # now set all channel properties to default values.
  4688.             set list [mag_cmd_channel_prop_list]
  4689.             foreach item $list {
  4690.                 set propname [list $name $item]
  4691.                 mag_cmd_default $propname
  4692.             }
  4693.         }
  4694.         default {
  4695.             echo "mailadmin: Unknown add type: $type"
  4696.             mag_cmd_quit 1
  4697.         }
  4698.         }
  4699.     }
  4700.     "del" {
  4701.         set DIRTY 1
  4702.         set type [mag_cmd_popargv]
  4703.         set name [mag_cmd_popargv]
  4704.         switch "$type" {
  4705.         "map" {
  4706.             set list [ma_aliases_get]
  4707.             set index [lsearch $list $name]
  4708.             if {$index == -1} {
  4709.                 echo "mailadmin: Map name not found: $name"
  4710.                 mag_cmd_quit 1
  4711.             }
  4712.             set list [lreplace $list $index $index]
  4713.             ma_aliases_set $list
  4714.         }
  4715.         "altname" {
  4716.             set list [ma_alternate_names_get]
  4717.             set index [lsearch $list $name]
  4718.             if {$index == -1} {
  4719.                 echo "mailadmin: Altname not found: $name"
  4720.                 mag_cmd_quit 1
  4721.             }
  4722.             set list [lreplace $list $index $index]
  4723.             ma_alternate_names_set $list
  4724.         }
  4725.         "channel" {
  4726.             set list [mai_ch_names_get]
  4727.             set index [lsearch $list $name]
  4728.             if {$index == -1} {
  4729.                 echo "mailadmin: Channel name not found: $name"
  4730.                 mag_cmd_quit 1
  4731.             }
  4732.             ma_ch_delete $name
  4733.         }
  4734.         default {
  4735.             echo "mailadmin: Invalid del type: $type"
  4736.             mag_cmd_quit 1
  4737.         }
  4738.         }
  4739.     }
  4740.     "order" {
  4741.         set DIRTY 1
  4742.         set type [mag_cmd_popargv]
  4743.         set neworder ""
  4744.         set item [mag_cmd_popargv]
  4745.         while {"$item" != "" && "$item" != "--"} {
  4746.             lappend neworder $item
  4747.             if {"$argv" != ""} {
  4748.                 set item [mag_cmd_popargv]
  4749.             } else {
  4750.                 set item ""
  4751.             }
  4752.         }
  4753.         switch "$type" {
  4754.         "maps" {
  4755.             set oldorder [ma_aliases_get]
  4756.             mag_cmd_vfy_lists $neworder $oldorder
  4757.             ma_aliases_set $neworder
  4758.         }
  4759.         "altnames" {
  4760.             set oldorder [ma_alternate_names_get]
  4761.             mag_cmd_vfy_lists $neworder $oldorder
  4762.             ma_alternate_names_set $neworder
  4763.         }
  4764.         "channels" {
  4765.             set oldorder [mai_ch_names_get]
  4766.             mag_cmd_vfy_lists $neworder $oldorder
  4767.             # now verify that new order doesn't have a
  4768.             # baduser channel in the wrong place.
  4769.             set length [llength $neworder]
  4770.             set stop [expr $length - 1]
  4771.             loop index 0 $stop {
  4772.                 set chname [lindex $neworder $index]
  4773.                 set table [ma_ch_table_type_get $chname]
  4774.                 if {"$table" == "baduser"} {
  4775.                     echo "mailadmin: New order has a baduser channel that is not the last channel."
  4776.                     mag_cmd_quit 1
  4777.                 }
  4778.             }
  4779.             # now set the new order
  4780.             loop index 0 $length {
  4781.                 set chname [lindex $neworder $index]
  4782.                 ma_ch_sequence_set $chname $index
  4783.             }
  4784.         }
  4785.         default {
  4786.             echo "mailadmin: Invalid order type: $type"
  4787.             mag_cmd_quit 1
  4788.         }
  4789.         }
  4790.     }
  4791.     "list" {
  4792.         set type [mag_cmd_popargv]
  4793.         switch "$type" {
  4794.         "maps" {
  4795.             set list [ma_aliases_get]
  4796.         }
  4797.         "altnames" {
  4798.             set list [ma_alternate_names_get]
  4799.         }
  4800.         "channels" {
  4801.             set list [mai_ch_names_get]
  4802.         }
  4803.         default {
  4804.             echo "mailadmin: Invalid list type: $type"
  4805.             mag_cmd_quit 1
  4806.         }
  4807.         }
  4808.         foreach item $list {
  4809.             echo $item
  4810.         }
  4811.     }
  4812.     "get" {
  4813.         set propname [mag_cmd_getprop]
  4814.         mag_cmd_get $propname
  4815.     }
  4816.     "set" {
  4817.         set propname [mag_cmd_getprop]
  4818.         set value [mag_cmd_popargv]
  4819.         mag_cmd_set $propname $value
  4820.     }
  4821.     "def" {
  4822.         set propname [mag_cmd_getprop]
  4823.         mag_cmd_default $propname
  4824.     }
  4825.     default {
  4826.         echo "mailadmin: Unknown command: $cmd"
  4827.         mag_cmd_usage
  4828.         mag_cmd_quit 1
  4829.     }
  4830.     }
  4831. }
  4832. proc \
  4833. mag_cmd_get { propname } \
  4834. {
  4835.     global mag_host_name MQUEUE
  4836.     set chname ""
  4837.     if {[llength $propname] == 2} {
  4838.         set chname [lindex $propname 0]
  4839.         set propname [lindex $propname 1]
  4840.     }    
  4841.     # regular properties
  4842.     if {"$chname" == ""} {
  4843.         switch $propname {
  4844.         host {
  4845.             set value [ma_machine_name_get]
  4846.             if {"$value" == ""} {
  4847.                 set value $mag_host_name
  4848.             }
  4849.             echo $value
  4850.         }
  4851.         from {
  4852.             set value [ma_from_domain_get]
  4853.             if {"$value" == ""} {
  4854.                 set value $mag_host_name
  4855.             }
  4856.             echo $value
  4857.         }
  4858.         domain {
  4859.             set ret [ma_domain_table_enabled_get]
  4860.             if {"$ret" == "1"} {
  4861.                 echo TRUE
  4862.             } else {
  4863.                 echo FALSE
  4864.             }
  4865.         }
  4866.         fdir {
  4867.             echo [ma_ms1_get MS1_INBOX_DIR]
  4868.         }
  4869.         fname {
  4870.             echo [ma_ms1_get MS1_INBOX_NAME]
  4871.         }
  4872.         fformat {
  4873.             set ret [ma_ms1_get MS1_FOLDER_FORMAT]
  4874.             set ret [string tolower $ret]
  4875.             switch "$ret" {
  4876.             "mmdf" {
  4877.                 echo MMDF
  4878.             }
  4879.             "sendmail" {
  4880.                 echo Sendmail
  4881.             }
  4882.             }
  4883.         }
  4884.         fsync {
  4885.             echo [string toupper [ma_ms1_get MS1_FSYNC]]
  4886.         }
  4887.         fccheck {
  4888.             echo [string toupper [ma_ms1_get MS1_EXTENDED_CHECKS]]
  4889.         }
  4890.         fincore {
  4891.             echo [string toupper [ma_ms1_get MS1_FOLDERS_INCORE]]
  4892.         }
  4893.         fthreshold {
  4894.             echo [ma_ms1_get MS1_EXPUNGE_THRESHOLD]
  4895.         }
  4896.         ftimeout {
  4897.             echo [ma_ms1_get MS1_LOCK_TIMEOUT]
  4898.         }
  4899.         ffilelock {
  4900.             echo [string toupper [ma_ms1_get MS1_FILE_LOCKING]]
  4901.         }
  4902.         fumask {
  4903.             echo [ma_ms1_get MS1_UMASK]
  4904.         }
  4905.         }
  4906.     } else {
  4907.         # channel properties
  4908.         switch "$propname" {
  4909.         name {
  4910.             echo $chname
  4911.         }
  4912.         program {
  4913.             echo [ma_ch_equate_get $chname P]
  4914.         }
  4915.         args {
  4916.             echo [ma_ch_equate_get $chname A]
  4917.         }
  4918.         dir {
  4919.             set ret [ma_ch_equate_get $chname D]
  4920.             if {"$ret" == ""} {
  4921.                 set ret $MQUEUE
  4922.             }
  4923.             echo $ret
  4924.         }
  4925.         table {
  4926.             echo [ma_ch_table_type_get $chname]
  4927.         }
  4928.         file {
  4929.             echo [ma_ch_table_file_get $chname]
  4930.         }
  4931.         host {
  4932.             echo [ma_ch_host_get $chname]
  4933.         }
  4934.         flags {
  4935.             echo [ma_ch_equate_get $chname F]
  4936.         }
  4937.         eol {
  4938.             set value [ma_ch_equate_get $chname E]
  4939.             if {"$value" == ""} {
  4940.                 set value "\\n"
  4941.             }
  4942.             echo $value
  4943.         }
  4944.         maxmsg {
  4945.             set value [ma_ch_equate_get $chname M]
  4946.             if {"$value" == ""} {
  4947.                 set value 0
  4948.             }
  4949.             echo $value
  4950.         }
  4951.         maxline {
  4952.             set value [ma_ch_equate_get $chname L]
  4953.             if {"$value" == ""} {
  4954.                 set value 0
  4955.             }
  4956.             echo $value
  4957.         }
  4958.         nice {
  4959.             set value [ma_ch_equate_get $chname N]
  4960.             if {"$value" == ""} {
  4961.                 set value 0
  4962.             }
  4963.             echo $value
  4964.         }
  4965.         user {
  4966.             echo [ma_ch_equate_get $chname U]
  4967.         }
  4968.         rruleset {
  4969.             echo [ma_ch_equate_get $chname R]
  4970.         }
  4971.         sruleset {
  4972.             echo [ma_ch_equate_get $chname S]
  4973.         }
  4974.         }
  4975.     }
  4976. }
  4977. proc \
  4978. mag_cmd_set { propname value } \
  4979. {
  4980.     global MQUEUE DIRTY mag_host_name
  4981.     set DIRTY 1
  4982.     set chname ""
  4983.     if {[llength $propname] == 2} {
  4984.         set chname [lindex $propname 0]
  4985.         set propname [lindex $propname 1]
  4986.     }    
  4987.     # regular properties
  4988.     if {"$chname" == ""} {
  4989.         switch $propname {
  4990.         host {
  4991.             if {"$value" == "$mag_host_name"} {
  4992.                 set value ""
  4993.             }
  4994.             ma_machine_name_set $value
  4995.         }
  4996.         from {
  4997.             if {"$value" == "$mag_host_name"} {
  4998.                 set value ""
  4999.             }
  5000.             ma_from_domain_set $value
  5001.         }
  5002.         domain {
  5003.             set bool [mag_cmd_check_tf $value]
  5004.             ma_domain_table_enabled_set $bool
  5005.         }
  5006.         fdir {
  5007.             ma_ms1_set MS1_INBOX_DIR $value
  5008.         }
  5009.         fname {
  5010.             ma_ms1_set MS1_INBOX_NAME $value
  5011.         }
  5012.         fformat {
  5013.             set test [string tolower $value]
  5014.             switch "$test" {
  5015.             "mmdf" {
  5016.                 set value MMDF
  5017.             }
  5018.             "sendmail" {
  5019.                 set value Sendmail
  5020.             }
  5021.             default {
  5022.                 echo "mailadmin: Folder format must be MMDF or Sendmail: $value"
  5023.                 mag_cmd_quit 1
  5024.             }
  5025.             }
  5026.             ma_ms1_set MS1_FOLDER_FORMAT $value
  5027.         }
  5028.         fsync {
  5029.             mag_cmd_check_tf $value
  5030.             ma_ms1_set MS1_FSYNC [string toupper $value]
  5031.         }
  5032.         fccheck {
  5033.             mag_cmd_check_tf $value
  5034.             ma_ms1_set MS1_EXTENDED_CHECKS [string toupper $value]
  5035.         }
  5036.         fincore {
  5037.             mag_cmd_check_tf $value
  5038.             ma_ms1_set MS1_FOLDERS_INCORE [string toupper $value]
  5039.         }
  5040.         fthreshold {
  5041.             set value [mag_cmd_number $value 0 100]
  5042.             ma_ms1_set MS1_EXPUNGE_THRESHOLD $value
  5043.         }
  5044.         ftimeout {
  5045.             set value [mag_cmd_number $value 1 999]
  5046.             ma_ms1_set MS1_LOCK_TIMEOUT $value
  5047.         }
  5048.         ffilelock {
  5049.             mag_cmd_check_tf $value
  5050.             ma_ms1_set MS1_FILE_LOCKING [string toupper $value]
  5051.         }
  5052.         fumask {
  5053.             mag_cmd_check_umask $value
  5054.             ma_ms1_set MS1_UMASK $value
  5055.         }
  5056.         }
  5057.     } else {
  5058.         # channel properties
  5059.         switch "$propname" {
  5060.         name {
  5061.             # wants to rename channel
  5062.             set newname $value
  5063.             set oldname $chname
  5064.             set ret [ma_ch_rename $oldname $newname]
  5065.             switch "$ret" {
  5066.             "conflict" {
  5067.                 echo "mailadmin: Channel name conflict: $newname"
  5068.                 mag_cmd_quit 1
  5069.             }
  5070.             "badname" {
  5071.                 echo "mailadmin: Channel name invalid: $newname"
  5072.                 mag_cmd_quit 1
  5073.             }
  5074.             }
  5075.         }
  5076.         program {
  5077.             ma_ch_equate_set $chname P $value
  5078.         }
  5079.         args {
  5080.             ma_ch_equate_set $chname A $value
  5081.         }
  5082.         dir {
  5083.             if {"$value" == "$MQUEUE"} {
  5084.                 set value ""
  5085.             }
  5086.             ma_ch_equate_set $chname D $value
  5087.         }
  5088.         table {
  5089.             mag_cmd_table_type_check $value
  5090.             ma_ch_table_type_set $chname $value
  5091.         }
  5092.         file {
  5093.             ma_ch_table_file_set $chname $value
  5094.         }
  5095.         host {
  5096.             ma_ch_host_set $chname $value
  5097.         }
  5098.         flags {
  5099.             ma_ch_equate_set $chname F $value
  5100.         }
  5101.         eol {
  5102.             if {"$value" == "\\n"} {
  5103.                 set value ""
  5104.             }
  5105.             ma_ch_equate_set $chname E $value
  5106.         }
  5107.         maxmsg {
  5108.             set value [mag_cmd_number $value 0 2000000000]
  5109.             if {$value == 0} {
  5110.                 set value ""
  5111.             }
  5112.             ma_ch_equate_set $chname M $value
  5113.         }
  5114.         maxline {
  5115.             set value [mag_cmd_number $value 0 10000]
  5116.             if {$value == 0} {
  5117.                 set value ""
  5118.             }
  5119.             ma_ch_equate_set $chname L $value
  5120.         }
  5121.         nice {
  5122.             set value [mag_cmd_number $value -20 20]
  5123.             if {$value == 0} {
  5124.                 set value ""
  5125.             }
  5126.             ma_ch_equate_set $chname N $value
  5127.         }
  5128.         user {
  5129.             ma_ch_equate_set $chname U $value
  5130.         }
  5131.         rruleset {
  5132.             ma_ch_equate_set $chname R $value
  5133.         }
  5134.         sruleset {
  5135.             ma_ch_equate_set $chname S $value
  5136.         }
  5137.         }
  5138.     }
  5139. }
  5140. proc \
  5141. mag_cmd_default { propname } \
  5142. {
  5143.     global MQUEUE MAILSPOOL MAILTABLE DIRTY mag_host_name
  5144.     set DIRTY 1
  5145.     set chname ""
  5146.     if {[llength $propname] == 2} {
  5147.         set chname [lindex $propname 0]
  5148.         set propname [lindex $propname 1]
  5149.     }    
  5150.     # regular properties
  5151.     if {"$chname" == ""} {
  5152.         switch $propname {
  5153.         host {
  5154.             ma_machine_name_set ""
  5155.         }
  5156.         from {
  5157.             ma_from_domain_set ""
  5158.         }
  5159.         domain {
  5160.             ma_domain_table_enabled_set 0
  5161.         }
  5162.         fdir {
  5163.             ma_ms1_set MS1_INBOX_DIR $MAILSPOOL
  5164.         }
  5165.         fname {
  5166.             ma_ms1_set MS1_INBOX_NAME ""
  5167.         }
  5168.         fformat {
  5169.             ma_ms1_set MS1_FOLDER_FORMAT Sendmail
  5170.         }
  5171.         fsync {
  5172.             ma_ms1_set MS1_FSYNC FALSE
  5173.         }
  5174.         fccheck {
  5175.             ma_ms1_set MS1_EXTENDED_CHECKS FALSE
  5176.         }
  5177.         fincore {
  5178.             ma_ms1_set MS1_FOLDERS_INCORE FALSE
  5179.         }
  5180.         fthreshold {
  5181.             ma_ms1_set MS1_EXPUNGE_THRESHOLD 50
  5182.         }
  5183.         ftimeout {
  5184.             ma_ms1_set MS1_LOCK_TIMEOUT 10
  5185.         }
  5186.         ffilelock {
  5187.             ma_ms1_set MS1_FILE_LOCKING FALSE
  5188.         }
  5189.         fumask {
  5190.             ma_ms1_set MS1_UMASK 077
  5191.         }
  5192.         }
  5193.     } else {
  5194.         # channel properties
  5195.         switch "$propname" {
  5196.         name {
  5197.             # does nothing
  5198.         }
  5199.         program {
  5200.             # does nothing
  5201.         }
  5202.         table {
  5203.             # does nothing
  5204.         }
  5205.         args {
  5206.             # default based on channel program
  5207.             set chprogram [ma_ch_equate_get $chname P]
  5208.             set base [exec basename $chprogram]
  5209.             set value "$base \$u"
  5210.             switch $base {
  5211.             "\[IPC\]" {
  5212.                 set value "IPC \$h"
  5213.             }
  5214.             "uux" {
  5215.                 set value "uux - -r -a\$f -gmedium \$h!rmail (\$u)"
  5216.             }
  5217.             "slocal" {
  5218.                 set value "slocal \$u"
  5219.             }
  5220.             }
  5221.             ma_ch_equate_set $chname A $value
  5222.         }
  5223.         dir {
  5224.             ma_ch_equate_set $chname D ""
  5225.         }
  5226.         file {
  5227.             # based on table type
  5228.             set table [ma_ch_table_type_get $chname]
  5229.             if {"$table" == "file"} {
  5230.                 set value "$MAILTABLE/$chname"
  5231.             } else {
  5232.                 set value ""
  5233.             }
  5234.             ma_ch_table_file_set $chname $value
  5235.         }
  5236.         host {
  5237.             ma_ch_host_set $chname ""
  5238.         }
  5239.         flags {
  5240.             # default based on channel program
  5241.             set chprogram [ma_ch_equate_get $chname P]
  5242.             # custom same as SMTP
  5243.             set value "mlsDFMPeu8"
  5244.             switch [exec basename $chprogram] {
  5245.             "\[IPC\]" {
  5246.                 set value "mlsDFMPeu8"
  5247.             }
  5248.             "uux" {
  5249.                 set value "mDFMhuU8"
  5250.             }
  5251.             "slocal" {
  5252.                 set value "lsDFMPhoAw5:|/@8"
  5253.             }
  5254.             }
  5255.             ma_ch_equate_set $chname F $value
  5256.         }
  5257.         eol {
  5258.             set chprogram [ma_ch_equate_get $chname P]
  5259.             if {"$chprogram" == "\[IPC\]"} {
  5260.                 set value "\\r\\n"
  5261.             } else {
  5262.                 set value ""
  5263.             }
  5264.             ma_ch_equate_set $chname E $value
  5265.         }
  5266.         maxmsg {
  5267.             set chprogram [ma_ch_equate_get $chname P]
  5268.             if {"[exec basename $chprogram]" == "uux"} {
  5269.                 set value 100000
  5270.             } else {
  5271.                 #set value ""
  5272.                 set value 20000000
  5273.             }
  5274.             ma_ch_equate_set $chname M $value
  5275.         }
  5276.         maxline {
  5277.             set chprogram [ma_ch_equate_get $chname P]
  5278.             if {"$chprogram" == "\[IPC\]"} {
  5279.                 set value 990
  5280.             } else {
  5281.                 set value ""
  5282.             }
  5283.             ma_ch_equate_set $chname L $value
  5284.         }
  5285.         nice {
  5286.             ma_ch_equate_set $chname N ""
  5287.         }
  5288.         user {
  5289.             ma_ch_equate_set $chname U ""
  5290.         }
  5291.         rruleset {
  5292.             # default based on channel program
  5293.             set chprogram [ma_ch_equate_get $chname P]
  5294.             # custom same as SMTP
  5295.             set value "ap822_re/ap822_rh"
  5296.             switch [exec basename $chprogram] {
  5297.             "\[IPC\]" {
  5298.                 set value "ap822_re/ap822_rh"
  5299.             }
  5300.             "uux" {
  5301.                 set value "ap976_re/ap976_rh"
  5302.             }
  5303.             "slocal" {
  5304.                 set value "aplocal_re/aplocal_rh"
  5305.             }
  5306.             }
  5307.             ma_ch_equate_set $chname R $value
  5308.         }
  5309.         sruleset {
  5310.             # default based on channel program
  5311.             set chprogram [ma_ch_equate_get $chname P]
  5312.             # custom same as SMTP
  5313.             set value "ap822_se/ap822_sh"
  5314.             switch [exec basename $chprogram] {
  5315.             "\[IPC\]" {
  5316.                 set value "ap822_se/ap822_sh"
  5317.             }
  5318.             "uux" {
  5319.                 set value "ap976_se/ap976_sh"
  5320.             }
  5321.             "slocal" {
  5322.                 set value "aplocal_se/aplocal_sh"
  5323.             }
  5324.             }
  5325.             ma_ch_equate_set $chname S $value
  5326.         }
  5327.         }
  5328.     }
  5329. }
  5330. proc \
  5331. mag_cmd_usage {} \
  5332. {
  5333.     global MQUEUE
  5334. echo "Usage:"
  5335. echo "mailadmin"
  5336. echo "    invoke GUI"
  5337. echo "mailadmin \[-h host\] command \[arguments\]"
  5338. echo "    Command line mode, following are the commands and their arguments."
  5339. echo "    Multiple command may be strung together on the command line."
  5340. echo "    If any of them fail no changes to the config files are made."
  5341. echo "    Commands with a variable number of arguments may be terminated with --."
  5342. echo
  5343. echo "sendmail restart - stop and restart the sendmail daemon"
  5344. echo "    Sendmail should be restarted after all changes are completed."
  5345. echo "    The GUI does this automatically."
  5346. echo
  5347. echo "uucp rebuild - rebuild /etc/mail/table/uucp.db from /usr/lib/uucp/Systems."
  5348. echo "    This only needs to be done if a UUCP channel exists and the Systems file"
  5349. echo "    has been changed.  The GUI does this automatically."
  5350. echo
  5351. echo "add map name - add an nis alias map or alias file entry.
  5352. echo "    formats are nis:mapname or a full pathname for an alias file."
  5353. echo "add altname name - add an alternate name for this host."
  5354. echo "add channel name program type - add a new channel entry."
  5355. echo "    table type is one of: DNS UUCP local remote baduser file."
  5356. echo
  5357. echo "del map name - delete an alias map or alias file by name."
  5358. echo "del altname name - delete an alternate name entry by name."
  5359. echo "del channel name - delete a channel entry by name."
  5360. echo
  5361. echo "order maps list - give new alias map order."
  5362. echo "order altnames list - give new alternate names order."
  5363. echo "order channels list - give new channel order."
  5364. echo "    channels using the baduser table type must go last,"
  5365. echo "    and there can be at most one such channel."
  5366. echo
  5367. echo "list maps - output alias map names in order."
  5368. echo "list altnames - output alternate names in order."
  5369. echo "list channels - output channel names in order."
  5370. echo
  5371. echo "The following commands deal with individual properties."
  5372. echo
  5373. echo "def propname - set a given property to it's default value."
  5374. echo "get propname - display current value of the given property."
  5375. echo "set propname value - set a given property to the given value."
  5376. echo
  5377. echo "Propnames can be a single token or they can be a channel name,"
  5378. echo "followed by a colon and then the property name."
  5379. echo
  5380. echo "Valid property names and their values are as follows:"
  5381. echo
  5382. echo "General Mail Properties"
  5383. echo "host - Host Name, default is to use the system name."
  5384. echo "from - From Domain Name, default (systemid) is used."
  5385. echo "domain - TRUE/FALSE, Domain Table Enabled (/etc/mail/table/domain)."
  5386. echo
  5387. echo "Message Store (Folder) properties"
  5388. echo "fdir - inbox directory, zero length string means use user's home directories."
  5389. echo "fname - inbox name, zero length string means use user's login name."
  5390. echo "fformat - MMDF/Sendmail, default folder format."
  5391. echo "fsync - TRUE/FALSE, enable O_FSYNC on folders."
  5392. echo "fccheck - TRUE/FALSE, enable extended consistency checks."
  5393. echo "fincore - TRUE/FALSE, enable incore caching of entire mail folders."
  5394. echo "fthreshold - 0-100, percent of file that must be maintained as valid."
  5395. echo "    set 100 for maximum compatibility, 50 for higher performance."
  5396. echo "ftimeout - 1-999, file lock timeout for mail folders."
  5397. echo "ffilelock - TRUE/FALSE, enable file based locking on mail folders."
  5398. echo "    folder.lock files will be used.  Kernel locking is always enabled."
  5399. echo "    This option adds file based locking."
  5400. echo "fumask - 0-0777, set mask for folder and directory creation for mail system."
  5401. echo
  5402. echo "Channel properties (must be preceeded with channel name and a colon)."
  5403. echo "name - channel name, no white space in name, domain is a reserved name,"
  5404. echo "    names must be unique.  baduser, badhost, multihome, and local are treated"
  5405. echo "    specially, they are translated into local names in the GUI based on LOCALE."
  5406. echo "program - channel program (P=), either a path name or \[IPC\] for SMTP."
  5407. echo "args - channel program arguments (A=), \$h and \$u are special to sendmail."
  5408. echo "    See sendmail documentation on mailer arguments."
  5409. echo "dir - channel program execution directory, default is $MQUEUE."
  5410. echo "table - DNS, UUCP, remote, local, file, baduser, channel table type."
  5411. echo "   baduser channel is special, it must be last and there can be only one."
  5412. echo "file - channel table file, only used for channel tables of type file."
  5413. echo "host - route all mail for this channel through this host."
  5414. echo "   set this option to the zero length string to remove this routing."
  5415. echo "   This value is ignored for file table channels."
  5416. echo "flags - channel program flags (F=), see sendmail doc on mailer flags."
  5417. echo "eol - channel program end of line (usually \\n although SMTP wants \\r\\n)."
  5418. echo "maxmsg - maximum message size, zero means no maximum."
  5419. echo "maxline - maximum line size, zero means no maximum, 990 is expected to be"
  5420. echo "    set for all channels that use SMTP, most others use 0."
  5421. echo "nice - -20-20 (N=), channel program nice increment, 0 is use default value."
  5422. echo "user - user:group (U=), user and group to run channel program as. If set to"
  5423. echo "    zero length string, then bin:bin (1:1) is used."
  5424. echo "rruleset - envelope\[/header\], envelope and header recipient rulesets."
  5425. echo "    We define ap822_re/ap822_rh for SMTP, ap975_re/ap976_rh for UUCP,"
  5426. echo "    and aplocal_re/aplocal_rh for local delivery."
  5427. echo "    Custom channels will generally want the rfc822 rewriting rules."
  5428. echo "    See the sendmail doc if you to add your own rulesets to sendmail.cf."
  5429. echo "sruleset - envelope\[/header\], envelope and header sender rulesets."
  5430. echo "    We define ap822_se/ap822_sh for SMTP, ap975_se/ap976_sh for UUCP,"
  5431. echo "    and aplocal_se/aplocal_sh for local delivery."
  5432. }
  5433. proc \
  5434. mag_cmd_table_type_check { table } \
  5435. {
  5436.     set list [list baduser DNS UUCP remote local file]
  5437.     if {[lsearch $list $table] == -1} {
  5438.         echo "mailadmin: Unknown channel table type: $table"
  5439.         mag_cmd_quit 1
  5440.     }
  5441. }
  5442. proc \
  5443. mag_cmd_vfy_lists { newlist oldlist } \
  5444. {
  5445.     set slist1 [lsort $newlist]
  5446.     set slist2 [lsort $oldlist]
  5447.     if {"$slist1" != "$slist2"} {
  5448.         echo "mailadmin: Ordering lists don't have the same items:"
  5449.         echo "    new list: $newlist"
  5450.         echo "    old list: $oldlist"
  5451.         mag_cmd_quit 1
  5452.     }
  5453. }
  5454. proc \
  5455. mag_cmd_popargv {} \
  5456. {
  5457.     global argv CMD
  5458.     if {"$argv" == ""} {
  5459.         echo "mailadmin: Not enough arguments for command: $CMD"
  5460.         mag_cmd_quit 1
  5461.     }
  5462.     return [lvarpop argv]
  5463. }
  5464. proc \
  5465. mag_cmd_getprop {} \
  5466. {
  5467.     set propname [mag_cmd_popargv]
  5468.     # have a channel property
  5469.     set colon [string first ":" $propname]
  5470.     if {$colon >= 0} {
  5471.         set end [expr $colon - 1]
  5472.         set chname [csubstr $propname 0 $colon]
  5473.         if {"$chname" == ""} {
  5474.             echo "mailadmin: Null channel name"
  5475.             mag_cmd_quit 1
  5476.         }
  5477.         set channels [mai_ch_names_get]
  5478.         if {[lsearch $channels $chname] == -1} {
  5479.             echo "mailadmin: Unknown channel name: $chname"
  5480.             mag_cmd_quit 1
  5481.         }
  5482.         set start [expr $colon + 1]
  5483.         set propname [csubstr $propname $start end]
  5484.         mag_cmd_channel_prop_vfy $propname
  5485.         return [list $chname $propname]
  5486.     }
  5487.     # regular property
  5488.     mag_cmd_regular_prop_vfy $propname
  5489.     return $propname
  5490. }
  5491. proc \
  5492. mag_cmd_channel_prop_vfy { propname } \
  5493. {
  5494.     if {"$propname" == ""} {
  5495.         echo "mailadmin: Null channel property name"
  5496.         mag_cmd_quit 1
  5497.     }
  5498.     set list [mag_cmd_channel_prop_list]
  5499.     if {[lsearch $list $propname] == -1} {
  5500.         echo "mailadmin: Invalid channel property name: $propname"
  5501.         mag_cmd_quit 1
  5502.     }
  5503. }
  5504. proc \
  5505. mag_cmd_channel_prop_list {} \
  5506. {
  5507.     set list [list name program args dir table file host flags eol maxmsg maxline nice user rruleset sruleset]
  5508.     return $list
  5509. }
  5510. proc \
  5511. mag_cmd_regular_prop_vfy { propname } \
  5512. {
  5513.     if {"$propname" == ""} {
  5514.         echo "mailadmin: Null property name"
  5515.         mag_cmd_quit 1
  5516.     }
  5517.     set list [list host from domain fdir fname fformat fsync fccheck fincore fthreshold ftimeout ffilelock fumask]
  5518.     if {[lsearch $list $propname] == -1} {
  5519.         echo "mailadmin: Invalid property name: $propname"
  5520.         mag_cmd_quit 1
  5521.     }
  5522. }
  5523. proc \
  5524. mag_cmd_check_tf { value } \
  5525. {
  5526.     set test [string toupper $value]
  5527.     if {"$test" == "TRUE"} {
  5528.         return 1
  5529.     }
  5530.     if {"$test" == "FALSE"} {
  5531.         return 0
  5532.     }
  5533.     echo "mailadmin: Invalid TRUE/FALSE value: $value"
  5534.     mag_cmd_quit 1
  5535. }
  5536. proc \
  5537. mag_cmd_check_umask { value } \
  5538. {
  5539.     if {[ctype digit $value] == 0} {
  5540.         echo "mailadmin: Invalid umask value: $value"
  5541.         mag_cmd_quit 1
  5542.     }
  5543.     if {[string first 8 $value] >= 0} {
  5544.         echo "mailadmin: Invalid umask, not an octal number: $value"
  5545.         mag_cmd_quit 1
  5546.     }
  5547.     if {[string first 9 $value] >= 0} {
  5548.         echo "mailadmin: Invalid umask, not an octal number: $value"
  5549.         mag_cmd_quit 1
  5550.     }
  5551.     if {"[cindex $value 0]" != "0"} {
  5552.         echo "mailadmin: First digit of a umask must be 0"
  5553.         mag_cmd_quit 1
  5554.     }
  5555.     if {$value > 0777} {
  5556.         echo "mailadmin: Invalid umask value, greater than 0777: $value"
  5557.         mag_cmd_quit 1
  5558.     }
  5559. }
  5560. proc \
  5561. mag_cmd_number { value min max } \
  5562. {
  5563.     set test $value
  5564.     if {"[csubstr $value 0 1]" == "-"} {
  5565.         set test [csubstr $value 1 end]
  5566.     }
  5567.     if {[ctype digit $test] == 0} {
  5568.         echo "mailadmin: Invalid numeric value: $value"
  5569.         mag_cmd_quit 1
  5570.     }
  5571.     set value [mag_trim_zero $value]
  5572.     if {$value < $min} {
  5573.         echo "mailadmin: Number less than minimum value of $min: $value"
  5574.         mag_cmd_quit 1
  5575.     }
  5576.     if {$value > $max} {
  5577.         echo "mailadmin: Number greater than maximum value of $max: $value"
  5578.         mag_cmd_quit 1
  5579.     }
  5580.     return $value
  5581. }
  5582. proc \
  5583. mag_cmd_file_get {} \
  5584. {
  5585.     global MAILCF MAILCFTMP MAILDEF MAILDEFTMP mag_host_name
  5586.     system "rm -fr $MAILCFTMP $MAILDEFTMP"
  5587.     set ret [mag_remote_copyin $MAILCF $MAILCFTMP]
  5588.     if {"$ret" != "ok"} {
  5589.         echo "mailadmin: Unable to access $mag_host_name:$MAILCF"
  5590.         mag_cmd_quit 1
  5591.     }
  5592.     set ret [mag_remote_copyin $MAILDEF $MAILDEFTMP]
  5593.     if {"$ret" != "ok"} {
  5594.         echo "mailadmin: Unable to access $mag_host_name:$MAILDEF"
  5595.         mag_cmd_quit 1
  5596.     }
  5597.     # now open them
  5598.     set ret [ma_cf_open $MAILCFTMP]
  5599.     if {"$ret" != "ok"} {
  5600.         echo "mailadmin: Unable to parse $mag_host_name:$MAILCF"
  5601.         mag_cmd_quit 1
  5602.     }    
  5603.     set ret [ma_ms1_open $MAILDEFTMP]
  5604.     if {"$ret" != "ok"} {
  5605.         echo "mailadmin: Unable to parse $mag_host_name:$MAILDEF"
  5606.         mag_cmd_quit 1
  5607.     }    
  5608. }
  5609. proc \
  5610. mag_cmd_file_put {} \
  5611. {
  5612.     global MAILCF MAILCFTMP MAILDEF MAILDEFTMP mag_host_name DIRTY
  5613.     if {$DIRTY == 1} {
  5614.         set ret [ma_cf_write]
  5615.         if {"$ret" != "ok"} {
  5616.             echo "mailadmin: Unable to save: $MAILCF"
  5617.             mag_cmd_quit 1
  5618.         }
  5619.         set ret [ma_ms1_write]
  5620.         if {"$ret" != "ok"} {
  5621.             echo "mailadmin: Unable to save: $MAILDEF"
  5622.             mag_cmd_quit 1
  5623.         }
  5624.         set ret [mag_remote_copyout $MAILCFTMP $MAILCF]
  5625.         if {"$ret" != "ok"} {
  5626.             echo "mailadmin: Unable to save $mag_host_name:$MAILCF"
  5627.             mag_cmd_quit 1
  5628.         }
  5629.         set ret [mag_remote_copyout $MAILDEFTMP $MAILDEF]
  5630.         if {"$ret" != "ok"} {
  5631.             echo "mailadmin: Unable to save $mag_host_name:$MAILDEF"
  5632.             mag_cmd_quit 1
  5633.         }
  5634.     }
  5635. }
  5636. proc \
  5637. mag_cmd_quit { code } \
  5638. {
  5639.     cleanup
  5640.     exit $code
  5641. }
  5642. proc \
  5643. ma_ms1_open { path } \
  5644. {
  5645.     global ma_ms1_db ma_ms1_path ma_ms1_index
  5646.     set ma_ms1_path $path
  5647.     if {[catch {open $path r} fd] != 0} {
  5648.         return fail
  5649.     }
  5650.     # read in file
  5651.     set ma_ms1_db ""
  5652.     set ma_ms1_index ""
  5653.     set linenum -1
  5654.     while {[gets $fd line] != -1} {
  5655.         set linenum [expr $linenum + 1]
  5656.         lappend ma_ms1_db $line
  5657.         # check that line is valid syntax
  5658.         if {[mai_ms1_skip_line $line] == "ok"} {
  5659.             continue
  5660.         }
  5661.         set list [mai_ms1_parse_line $line]
  5662.         if {$list == "parserr"} {
  5663.             close $fd
  5664.             return parserr
  5665.         }
  5666.         # check if valid keyword
  5667.         set keyword [lindex $list 0]
  5668.         if {[catch {ma_ms1_default $keyword}] != 0} {
  5669.             return parserr
  5670.         }
  5671.         set value [lindex $list 1]
  5672.         if {"[mai_ms1_valid $keyword $value]" == "fail"} {
  5673.             return parserr
  5674.         }
  5675.         set list [list $keyword $linenum]
  5676.         lappend ma_ms1_index $list
  5677.     }
  5678.     close $fd
  5679.     return ok
  5680. }
  5681. proc \
  5682. ma_ms1_get { keyword } \
  5683. {
  5684.     global ma_ms1_db
  5685.     set index [mai_ms1_find $keyword]
  5686.     if {$index == -1} {
  5687.         return [ma_ms1_default $keyword]
  5688.     }
  5689.     set line [lindex $ma_ms1_db $index]
  5690.     set list [mai_ms1_parse_line $line]
  5691.     set value [lindex $list 1]
  5692.     return $value
  5693. }
  5694. proc \
  5695. ma_ms1_set { keyword value } \
  5696. {
  5697.     global ma_ms1_db
  5698.     set index [mai_ms1_find $keyword]
  5699.     if {"[mai_ms1_valid $keyword $value]" == "fail"} {
  5700.         error "Invalid value for $keyword: $value"
  5701.     }
  5702.     if {$index == -1} {
  5703.         # not exist
  5704.         lappend ma_ms1_db "${keyword}=${value}"
  5705.     } else {
  5706.         # exists
  5707.         set ma_ms1_db [lreplace $ma_ms1_db $index $index "${keyword}=${value}"]
  5708.     }
  5709. }
  5710. proc \
  5711. ma_ms1_default { keyword } \
  5712. {
  5713.     switch $keyword {
  5714.     "MS1_FOLDER_FORMAT" {
  5715.         return "MMDF"
  5716.     }
  5717.     "MS1_INBOX_DIR" {
  5718.         return "/var/mail"
  5719.     }
  5720.     "MS1_INBOX_NAME" {
  5721.         return ""
  5722.     }
  5723.     "MS1_FSYNC" {
  5724.         return "FALSE"
  5725.     }
  5726.     "MS1_EXTENDED_CHECKS" {
  5727.         return "FALSE"
  5728.     }
  5729.     "MS1_EXPUNGE_THRESHOLD" {
  5730.         return "50"
  5731.     }
  5732.     "MS1_FOLDERS_INCORE" {
  5733.         return "FALSE"
  5734.     }
  5735.     "MS1_FILE_LOCKING" {
  5736.         return "FALSE"
  5737.     }
  5738.     "MS1_LOCK_TIMEOUT" {
  5739.         return "10"
  5740.     }
  5741.     "MS1_UMASK" {
  5742.         return "077"
  5743.     }
  5744.     }
  5745.     error "Unknown keyword: $keyword"
  5746. }
  5747. proc \
  5748. ma_ms1_write {} \
  5749. {
  5750.     global ma_ms1_db ma_ms1_path
  5751.     if {[catch {open $ma_ms1_path w} fd] != 0} {
  5752.         return fail
  5753.     }
  5754.     # write out file
  5755.     foreach item $ma_ms1_db {
  5756.         puts $fd $item
  5757.     }
  5758.     close $fd
  5759.     return ok
  5760. }
  5761. proc \
  5762. mai_ms1_valid { keyword value } \
  5763. {
  5764.     switch $keyword {
  5765.     "MS1_FOLDER_FORMAT" { 
  5766.         set val [string toupper $value]
  5767.         if {"$val" == "SENDMAIL"} {
  5768.             return ok
  5769.         }
  5770.         if {"$val" == "MMDF"} {
  5771.             return ok
  5772.         }
  5773.         return fail
  5774.     }
  5775.     "MS1_INBOX_DIR" { return ok }
  5776.     "MS1_INBOX_NAME" { return ok }
  5777.     "MS1_FSYNC" {
  5778.         set val [string toupper $value]
  5779.         if {"$val" == "TRUE"} {
  5780.             return ok
  5781.         }
  5782.         if {"$val" == "FALSE"} {
  5783.             return ok
  5784.         }
  5785.         return fail
  5786.     }
  5787.     "MS1_EXTENDED_CHECKS" {
  5788.         set val [string toupper $value]
  5789.         if {"$val" == "TRUE"} {
  5790.             return ok
  5791.         }
  5792.         if {"$val" == "FALSE"} {
  5793.             return ok
  5794.         }
  5795.         return fail
  5796.     }
  5797.     "MS1_EXPUNGE_THRESHOLD" {
  5798.         if {[ctype digit $value] == 0} {
  5799.             return fail
  5800.         }
  5801.         while {"[csubstr $value 0 1]" == "0" && $value != 0} {
  5802.             return fail
  5803.         }
  5804.         if {$value > 100} {
  5805.             return fail
  5806.         }
  5807.         return ok
  5808.     }
  5809.     "MS1_FOLDERS_INCORE" {
  5810.         set val [string toupper $value]
  5811.         if {"$val" == "TRUE"} {
  5812.             return ok
  5813.         }
  5814.         if {"$val" == "FALSE"} {
  5815.             return ok
  5816.         }
  5817.         return fail
  5818.     }
  5819.     "MS1_FILE_LOCKING" {
  5820.         set val [string toupper $value]
  5821.         if {"$val" == "TRUE"} {
  5822.             return ok
  5823.         }
  5824.         if {"$val" == "FALSE"} {
  5825.             return ok
  5826.         }
  5827.         return fail
  5828.     }
  5829.     "MS1_UMASK" {
  5830.         if {[ctype digit $value] == 0} {
  5831.             return fail
  5832.         }
  5833.         if {[string first 8 $value] >= 0} {
  5834.             return fail
  5835.         }
  5836.         if {[string first 9 $value] >= 0} {
  5837.             return fail
  5838.         }
  5839.         # first digit must be zero
  5840.         if {"[cindex $value 0]" != "0"} {
  5841.             return fail
  5842.         }
  5843.         # valid octal number, now do range check,
  5844.         # leading zero makes base 8 in tcl just like in C.
  5845.         if {$value > 0777} {
  5846.             return fail
  5847.         }
  5848.         return ok
  5849.     }
  5850.     "MS1_LOCK_TIMEOUT" {
  5851.         if {[ctype digit $value] == 0} {
  5852.             return fail
  5853.         }
  5854.         if {$value > 0} {
  5855.             return ok
  5856.         }
  5857.         return fail
  5858.     }
  5859.     }
  5860.     error "Unknown keyword: $keyword"
  5861. }
  5862. proc \
  5863. mai_ms1_find { keyword } \
  5864. {
  5865.     global ma_ms1_index
  5866.     set count [llength $ma_ms1_index]
  5867.     set value ""
  5868.     loop i 0 $count {
  5869.         set list [lindex $ma_ms1_index $i]
  5870.         set lkeyword [lindex $list 0]
  5871.         if {$lkeyword == $keyword} {
  5872.             return [lindex $list 1]
  5873.         }
  5874.     }
  5875.     return -1
  5876. }
  5877. proc \
  5878. mai_ms1_skip_line { line } \
  5879. {
  5880.     if {[string length $line] == 0} {
  5881.         return ok
  5882.     }
  5883.     if {[cindex $line 0] == "#"} {
  5884.         return ok
  5885.     }
  5886.     return fail
  5887. }
  5888. proc \
  5889. mai_ms1_parse_line { line } \
  5890. {
  5891.     set index [string first "=" $line]
  5892.     if {$index == "-1"} {
  5893.         return parserr
  5894.     }
  5895.     set left [csubstr $line 0 $index]
  5896.     set left [string trim $left]
  5897.     set index [expr $index + 1]
  5898.     set right [csubstr $line $index end]
  5899.     set right [string trim $right]
  5900.     set right [string trim $right "\""]
  5901.     if {$left == ""} {
  5902.         return parserr
  5903.     }
  5904.     set list [list "$left" "$right"]
  5905.     lappend list $left $right
  5906.     return $list
  5907. }
  5908. set CF_MaxLine    80
  5909. array set optionNames {\
  5910.             7    SevenBitInput \
  5911.             8    EightBitMode \
  5912.             A    AliasFile \
  5913.             a    AliasWait \
  5914.             B    BlankSub \
  5915.             b    MinFreeBlocks \
  5916.             C    CheckpointInterval \
  5917.             c    HoldExpensive \
  5918.             D    AutoRebuildAliases \
  5919.             d    DeliveryMode \
  5920.             E    ErrorHeader \
  5921.             e    ErrorMode \
  5922.             f    SaveFromLine \
  5923.             F    TempFileMode \
  5924.             G    MatchGECOS \
  5925.             H    HelpFile \
  5926.             h    MaxHopCount \
  5927.             i    IgnoreDots \
  5928.             I    ResolverOptions \
  5929.             J    ForwardPath \
  5930.             j    SendMimeErrors \
  5931.             k    ConnectionCacheSize \
  5932.             K    ConnectionCacheTimeout \
  5933.             L    LogLevel \
  5934.             l    UseErrorsTo \
  5935.             m    MeToo \
  5936.             n    CheckAliases \
  5937.             O    DaemonPortOptions \
  5938.             o    OldStyleHeaders \
  5939.             P    PostmasterCopy \
  5940.             p    PrivacyOptions \
  5941.             Q    QueueDirectory \
  5942.             q    QueueFactor \
  5943.             R    DontPruneRoutes \
  5944.             S    StatusFile \
  5945.             s    SuperSafe \
  5946.             t    TimeZoneSpec \
  5947.             u    DefaultUser \
  5948.             U    UserDatabaseSpec \
  5949.             V    FallbackMXhost \
  5950.             v    Verbose \
  5951.             w    TryNullMXList \
  5952.             x    QueueLA \
  5953.             X    RefuseLA \
  5954.             Y    ForkEachJob \
  5955.             y    RecipientFactor \
  5956.             z    ClassFactor \
  5957.             Z    RetryFactor}
  5958. array set listOptions {AliasFile "," \
  5959.                DaemonPortOptions "," \
  5960.                PrivacyOptions "," \
  5961.                ResolverOptions " "}
  5962. proc CF:OptionFullname {id} {
  5963.     global optionNames
  5964.     if {[clength $id] == 1 && [info exists optionNames($id)]} {
  5965.     return $optionNames($id)
  5966.     } else {
  5967.     return $id
  5968.     }
  5969. }
  5970. proc CF:CommaListOption {id} {
  5971.     global listOptions
  5972.     set id [CF:OptionFullname $id]
  5973.     if {[info exists listOptions($id)] && $listOptions($id) == ","} {
  5974.     return 1
  5975.     } else {
  5976.     return 0
  5977.     }
  5978. }
  5979. proc CF:ReadCB {fileID fp} {
  5980.     Table:SetOption $fileID newFirst 1
  5981.     set context [scancontext create]
  5982.     scanmatch $context {^D\{(.*)\}(.*)} {
  5983.     Table:ProcessLine $fileID macro $matchInfo(submatch0) \
  5984.         $matchInfo(submatch1)
  5985.     }
  5986.     scanmatch $context {^D([^\{])(.*)} {
  5987.     Table:ProcessLine $fileID macro $matchInfo(submatch0) \
  5988.         $matchInfo(submatch1)
  5989.     }
  5990.     scanmatch $context {^O ([^     =]+)([     =]*)?(.*)} {
  5991.     Table:ProcessLine $fileID option $matchInfo(submatch0) \
  5992.         $matchInfo(submatch2)
  5993.     }
  5994.     scanmatch $context {^O([^ ])(.*)} {
  5995.     Table:ProcessLine $fileID option \
  5996.         [CF:OptionFullname $matchInfo(submatch0)] $matchInfo(submatch1)
  5997.     }
  5998.     scanmatch $context {^K([^     ]*)(.*)} {
  5999.     Table:ProcessLine $fileID map $matchInfo(submatch0) \
  6000.         $matchInfo(submatch1)
  6001.     }
  6002.     scanmatch $context {^C\{(.*)\}(.*)} {
  6003.     Table:ProcessLine $fileID class $matchInfo(submatch0) \
  6004.         $matchInfo(submatch1)
  6005.     }
  6006.     scanmatch $context {^C([^\{])(.*)} {
  6007.     Table:ProcessLine $fileID class $matchInfo(submatch0) \
  6008.         $matchInfo(submatch1)
  6009.     }
  6010.     scanmatch $context {^S(.*)} {
  6011.     Table:ProcessLine $fileID ruleset $matchInfo(submatch0) {}
  6012.     }
  6013.     scanmatch $context {^R.*} {
  6014.     Table:ProcessLine $fileID CONTINUATION {} $matchInfo(line)
  6015.     }
  6016.     scanmatch $context {^M([^,]*),(.*)} {
  6017.     Table:ProcessLine $fileID mailer $matchInfo(submatch0) \
  6018.         $matchInfo(submatch1)
  6019.     }
  6020.     scanmatch $context {^[     ]+[^     ]+} {
  6021.     global Table_lastType
  6022.     #if {$Table_lastType == "header" || $Table_lastType == "mailer"} {
  6023.         Table:ProcessLine $fileID CONTINUATION {} $matchInfo(line)
  6024.     #} else {
  6025.     #    Table:ProcessLine $fileID COMMENT {} $matchInfo(line)
  6026.     #}
  6027.     }
  6028.     scanmatch $context {
  6029.     Table:ProcessLine $fileID COMMENT {} $matchInfo(line)
  6030.     }
  6031.     scanfile $context $fp
  6032.     scancontext delete $context
  6033. }
  6034. proc CF:WriteCB {fileID fp type id data} {
  6035.     case $type {
  6036.     macro {
  6037.         if {[string length $id] > 1} {
  6038.         puts $fp "D\{${id}\}${data}"
  6039.         } else {
  6040.         puts $fp "D$id$data"
  6041.         }
  6042.     }
  6043.     option {
  6044.         if {[string length $id] > 1} {
  6045.         puts $fp "O $id=$data"
  6046.         } else {
  6047.         puts $fp "O$id$data"
  6048.         }
  6049.     }
  6050.     map {
  6051.         puts $fp "K$id$data"
  6052.     }
  6053.     class {
  6054.         if {[clength $id] > 1} {
  6055.         puts $fp "C\{${id}\}${data}"
  6056.         } else {
  6057.         puts $fp "C$id$data"
  6058.         }
  6059.     }
  6060.     ruleset {
  6061.         if {[clength $data] > 0} {
  6062.         puts $fp "S${id}\n${data}"
  6063.         } else {
  6064.         puts $fp "S$id"
  6065.         }
  6066.     }
  6067.     mailer {
  6068.         if {$id != {}} {
  6069.         puts $fp "M$id," nonewline
  6070.         }
  6071.         puts $fp $data
  6072.     }
  6073.     default {
  6074.         puts $fp $data
  6075.     }
  6076.     }
  6077. }
  6078. proc CF:Open {fileName {mode 0644}} {
  6079.     return [Table:Open $fileName CF:ReadCB CF:WriteCB $mode]
  6080. }
  6081. proc CF:Write {fileID {fileName {}}} {
  6082.     return [Table:Write $fileID $fileName]
  6083. }
  6084. proc CF:Close {fileID} {
  6085.     return [Table:Close $fileID]
  6086. }
  6087. proc CF:ForceWrites {fileID} {
  6088.     return [Table:ForceWrites $fileID]
  6089. }
  6090. proc CF:Get {fileID type id} {
  6091.     if {$type == "option"} {
  6092.     set id [CF:OptionFullname $id]
  6093.     if {[CF:CommaListOption $id]} {
  6094.         set result [Table:Get $fileID $type $id ","]
  6095.     } else {
  6096.         set result [Table:Get $fileID $type $id " "]
  6097.     }
  6098.     } elseif {$type == "ruleset"} {
  6099.     set result [Table:Get $fileID $type $id "\n"]
  6100.     set result [string trim $result " \n"]
  6101.     } else {
  6102.     set result [Table:Get $fileID $type $id " "]
  6103.     }
  6104.     return $result
  6105. }
  6106. proc CF:Set {fileID type id data} {
  6107.     case $type {
  6108.     {class mailer option} {
  6109.         return [CF:SetList $fileID $type $id $data]
  6110.     }
  6111.     default {
  6112.         return [Table:Set $fileID $type $id $data]
  6113.     }
  6114.     }
  6115. }
  6116. proc CF:Unset {fileID type id} {
  6117.     return [Table:Unset $fileID $type $id]
  6118. }
  6119. proc CF:SetList {fileID type id value} {
  6120.     global CF_MaxLine
  6121.     set separator " "
  6122.     set continuation 0
  6123.     # some option values are separated by commas, not whitespace
  6124.     case $type {
  6125.     option {
  6126.         set continuation 1
  6127.         set id [CF:OptionFullname $id]
  6128.         if {[CF:CommaListOption $id]} {
  6129.         set valueList {}
  6130.         foreach item [split $value {,}] {
  6131.             lappend valueList [string trim $item]
  6132.         }
  6133.         set value $valueList
  6134.         set separator ","
  6135.         }
  6136.         set data "[lvarpop value]$separator"
  6137.         if {[clength $id] > 1} {
  6138.         set length [expr \
  6139.             [string length $data] + [string length $id] + 3]
  6140.         } else {
  6141.         set length [expr [string length $data] + 2]
  6142.            }
  6143.     }
  6144.     mailer {
  6145.         set continuation 1
  6146.         set valueList {}
  6147.         foreach item [split $value {,}] {
  6148.         lappend valueList [string trim $item]
  6149.         }
  6150.         set value $valueList
  6151.         set separator ", "
  6152.             set data " [lvarpop value]$separator"
  6153.         set length [expr [string length $data] + [string length $id] + 2]
  6154.     } 
  6155.     class {
  6156.         set continuation 1
  6157.         set data "[lvarpop value]$separator"
  6158.         if {[clength $id] > 1} {
  6159.         set length [expr \
  6160.             [string length $data] + [string length $id] + 3]
  6161.         } else {
  6162.         set length [expr [string length $data] + 2]
  6163.         }
  6164.     }
  6165.     }
  6166.     set separatorLength [string length $separator]
  6167.     set first 1
  6168.     foreach word $value {
  6169.     set wordLen [string length $word]
  6170.     if {[expr "$length + $wordLen + $separatorLength"] <= $CF_MaxLine} {
  6171.         append data "${word}${separator}"
  6172.         set length [expr "$length + $wordLen + $separatorLength"]
  6173.     } else {
  6174.         if {$first} {
  6175.         Table:Set $fileID $type $id $data
  6176.         } else {
  6177.         if {$continuation} {
  6178.             Table:AppendLine $fileID CONTINUATION $id $data
  6179.         }
  6180.         }
  6181.         set first 0
  6182.         if {$continuation} {
  6183.         set data "\t${word}${separator}"
  6184.         set length [expr 8 + $wordLen + $separatorLength]
  6185.         }
  6186.     }
  6187.     }
  6188.     set data [string trimright $data $separator]
  6189.     if {$first} {
  6190.     return [Table:Set $fileID $type $id $data]
  6191.     } else {
  6192.     if {$continuation} {
  6193.         return [Table:AppendLine $fileID CONTINUATION $id $data]
  6194.     }
  6195.     }
  6196. }
  6197. proc CF:AddValue {fileID type id addValue} {
  6198.     set currentValue [CF:Get $fileID $type $id]
  6199.     set newValue [union $currentValue $addValue]
  6200.     return [CF:SetList $fileID $type $id $newValue]
  6201. }
  6202. proc CF:RemoveValue {fileID type id removeValue} {
  6203.     set currentValue [CF:Get $fileID $type $id]
  6204.     set newValue [lindex [intersect3 $currentValue $removeValue] 0]
  6205.     return [CF:SetList $fileID $type $id $newValue]
  6206. }
  6207. proc CF:GetMapInfo {fileID mapName} {
  6208.     global optarg optind
  6209.     if {[set data [CF:Get $fileID map $mapName]] == {}} {
  6210.     return {}
  6211.     }
  6212.     keylset info name $mapName
  6213.     keylset info class [ctoken data " \t"]
  6214.     while {[set item [ctoken data " \t"]] != {}} {
  6215.     lappend argv $item
  6216.     }
  6217.     set count [expr [llength $argv] - 1]
  6218.     keylset info pathName [lindex $argv $count]
  6219.     return $info
  6220. }
  6221. set MA_SENDMAIL_FILEID        -1
  6222. set MA_CH_MODIFIED        0
  6223. set MA_CH_TABLE_DIRECTORY "/etc/mail/table"
  6224. array set MA_CH_TABLE_TYPE {\
  6225.     dns_TBL        DNS \
  6226.     uucp_TBL    UUCP \
  6227.     local_TBL    local \
  6228.     remote_TBL    remote \
  6229.     baduser_TBL    baduser}
  6230. array set MA_CH_RULESET {\
  6231.     DNS        dns_TBL \
  6232.     UUCP        uucp_TBL \
  6233.     local        local_TBL \
  6234.     remote        remote_TBL \
  6235.     baduser        baduser_TBL}
  6236. set MA_CH_TABLE_TYPE_LIST [list \
  6237.     "DNS" \
  6238.     "UUCP" \
  6239.     "local" \
  6240.     "remote" \
  6241.     "baduser" \
  6242.     "file"]
  6243. set MA_CH_RESERVED_NAMES [list \
  6244.     "error" \
  6245.     "prog" \
  6246.     "*file*" \
  6247.     "*include*"]
  6248. proc ma_cf_valid {filename} {
  6249.     set retval "ok"
  6250.     if {[catch {open $filename r} fd] != 0} {
  6251.         return "fail"
  6252.     }
  6253.     if {[gets $fd line] != -1} {
  6254.     if {[regexp {^# checksum:(.*)$} $line match recordedSum] == 1} {
  6255.         set tmp /tmp/ma_cf_valid.[pid]
  6256.         set ret [catch {open $tmp w} tmpfd]
  6257.         if {$ret != 0} {
  6258.         error "Unable to open $tmp"
  6259.         }
  6260.         copyfile $fd $tmpfd
  6261.         set csum [exec sum -r $tmp]
  6262.         set currentSum [ctoken csum " \t"]
  6263.         if {$currentSum != $recordedSum} {
  6264.         set retval "fail"
  6265.         }
  6266.         close $tmpfd
  6267.         system "rm -f $tmp"
  6268.     } else {
  6269.         set retval "fail"
  6270.     }
  6271.     } else {
  6272.     set retval "fail"
  6273.     }
  6274.     close $fd
  6275.     return $retval
  6276. }
  6277. proc ma_cf_open {filename} {
  6278.     global MA_SENDMAIL_FILEID MA_SENDMAIL_FILEPATH MA_SENDMAIL_FILESUM
  6279.     if {$MA_SENDMAIL_FILEID != -1} {
  6280.         ma_cf_close
  6281.     }
  6282.     if {![file exists $filename]} {
  6283.     return "fail"
  6284.     }
  6285.     set MA_SENDMAIL_FILEID [CF:Open $filename]
  6286.     #
  6287.     # For compatibility with the GUI, sendmail.cf file must have...
  6288.     #
  6289.     # a csumline
  6290.     if {[ConfigFile:GetLine \
  6291.     $MA_SENDMAIL_FILEID 1.0 dummy dummy csumline] == -1} {
  6292.     ma_cf_close
  6293.     return "parserr"
  6294.     }
  6295.     if {[regexp {^# checksum:(.*)$} $csumline match csum] == 1} {
  6296.     set MA_SENDMAIL_FILESUM $csum
  6297.     } else {
  6298.     ma_cf_close
  6299.     return "parserr"
  6300.     }
  6301.     # correctly defined channels
  6302.     if {[catch mai_ch_structure_init errorMsg] != 0} {
  6303.     ma_cf_close
  6304.     return "parserr"
  6305.     }
  6306.     # the users map (for baduser channel table)
  6307.     if {[CF:Get $MA_SENDMAIL_FILEID map users] == ""} {
  6308.     ma_cf_close
  6309.     return "parserr"
  6310.     }
  6311.     # the uucp map (for uucp channel table)
  6312.     if {[CF:Get $MA_SENDMAIL_FILEID map uucp] == ""} {
  6313.     ma_cf_close
  6314.     return "parserr"
  6315.     }
  6316.     # the domain table map 
  6317.     if {[CF:Get $MA_SENDMAIL_FILEID map domain] == ""} {
  6318.     ma_cf_close
  6319.     return "parserr"
  6320.     }
  6321.     # macros, classes for domain table
  6322.     if {[CF:Get $MA_SENDMAIL_FILEID class P] != "." || \
  6323.     [CF:Get $MA_SENDMAIL_FILEID class D] != "DMNTAB"} {
  6324.     ma_cf_close
  6325.     return "parserr"
  6326.     }
  6327.     # the rulesets for domain table parsing
  6328.     if {[CF:Get $MA_SENDMAIL_FILEID ruleset domains] == "" || \
  6329.     [CF:Get $MA_SENDMAIL_FILEID ruleset domains_helper] == ""} {
  6330.     ma_cf_close
  6331.     return "parserr"
  6332.     }
  6333.     # all the rulesets for built-in channel tables
  6334.     if {[CF:Get $MA_SENDMAIL_FILEID ruleset local_TBL] == ""    || \
  6335.     [CF:Get $MA_SENDMAIL_FILEID ruleset dns_TBL] == ""    || \
  6336.     [CF:Get $MA_SENDMAIL_FILEID ruleset uucp_TBL] == ""    || \
  6337.     [CF:Get $MA_SENDMAIL_FILEID ruleset remote_TBL] == ""    || \
  6338.     [CF:Get $MA_SENDMAIL_FILEID ruleset baduser_TBL] == ""} {
  6339.     ma_cf_close
  6340.     return "parserr"
  6341.     }
  6342.     # all the rulesets for built-in R=, S= equates
  6343.     if {[CF:Get $MA_SENDMAIL_FILEID ruleset ap822_se] == ""    || \
  6344.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap822_sh] == ""    || \
  6345.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap822_re] == ""    || \
  6346.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap822_rh] == ""    || \
  6347.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap976_se] == ""    || \
  6348.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap976_sh] == ""    || \
  6349.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap976_re] == ""    || \
  6350.     [CF:Get $MA_SENDMAIL_FILEID ruleset ap976_rh] == ""    || \
  6351.     [CF:Get $MA_SENDMAIL_FILEID ruleset aplocal_se] == ""    || \
  6352.     [CF:Get $MA_SENDMAIL_FILEID ruleset aplocal_sh] == ""    || \
  6353.     [CF:Get $MA_SENDMAIL_FILEID ruleset aplocal_re] == ""    || \
  6354.     [CF:Get $MA_SENDMAIL_FILEID ruleset aplocal_rh] == ""} {
  6355.     ma_cf_close
  6356.     return "parserr"
  6357.     }
  6358.     set MA_SENDMAIL_FILEPATH $filename
  6359.     return ok
  6360. }
  6361. proc ma_cf_close {} {
  6362.     global MA_SENDMAIL_FILEID MA_CH_MODIFIED MA_SENDMAIL_FILESUM channels
  6363.     if {$MA_SENDMAIL_FILEID == -1} {
  6364.     error "Sendmail configuration file is not open"
  6365.     }
  6366.     Table:CloseNoWrite $MA_SENDMAIL_FILEID
  6367.     set MA_SENDMAIL_FILEID -1
  6368.     set MA_CH_MODIFIED 0
  6369.     if {[info exists MA_SENDMAIL_FILESUM]} {
  6370.     unset MA_SENDMAIL_FILESUM
  6371.     }
  6372.     if {[info exists channels]} {
  6373.     unset channels
  6374.     }
  6375. }
  6376. proc ma_cf_write {} {
  6377.     global MA_SENDMAIL_FILEID MA_SENDMAIL_FILEPATH MA_SENDMAIL_FILESUM
  6378.     global MA_CH_MODIFIED 
  6379.     if {$MA_SENDMAIL_FILEID == -1} {
  6380.     error "Sendmail configuration file is not open"
  6381.     }
  6382.     if {$MA_CH_MODIFIED} {
  6383.     if {[catch mai_ch_structure_commit errorMsg] != 0} {
  6384.        return "fail"
  6385.     }
  6386.     }
  6387.     CF:Write $MA_SENDMAIL_FILEID
  6388.     # get a checksum of contents, *without* the csum line
  6389.     set ret [catch {open $MA_SENDMAIL_FILEPATH r} fd]
  6390.     if {$ret != 0} {
  6391.         return "fail"
  6392.     }
  6393.     set ret [gets $fd line]
  6394.     if {$ret == -1} {
  6395.         return "fail"
  6396.     }
  6397.     set tmp /tmp/ma_cf_write.[pid]
  6398.     set ret [catch {open $tmp w} tmpfd]
  6399.     if {$ret != 0} {
  6400.     return "fail"
  6401.     }
  6402.     copyfile $fd $tmpfd
  6403.     close $fd
  6404.     close $tmpfd
  6405.     set csum [exec sum -r $tmp]
  6406.     set currentSum [ctoken csum " \t"]
  6407.     if {$currentSum != $MA_SENDMAIL_FILESUM} {
  6408.     set newCsumline "# checksum:$currentSum"
  6409.     set type "COMMENT"
  6410.     set id ""
  6411.     ConfigFile:ReplaceLine $MA_SENDMAIL_FILEID 1.0 $type $id newCsumline
  6412.     CF:ForceWrites $MA_SENDMAIL_FILEID
  6413.     CF:Close $MA_SENDMAIL_FILEID
  6414.     }
  6415.     system "rm -f $tmp"
  6416.     return "ok"
  6417. }
  6418. proc ma_machine_name_get {} {
  6419.     global MA_SENDMAIL_FILEID
  6420.     if {$MA_SENDMAIL_FILEID == -1} {
  6421.     error "Sendmail configuration file is not open"
  6422.     }
  6423.     # NOTE: If the j macro is in turned defined by other macros, these
  6424.     #         are not expanded, but are passed as is to the front end.
  6425.     set machineName [CF:Get $MA_SENDMAIL_FILEID macro j]
  6426.     return $machineName
  6427. }
  6428. proc ma_machine_name_set {name} {
  6429.     global MA_SENDMAIL_FILEID
  6430.     if {$MA_SENDMAIL_FILEID == -1} {
  6431.     error "Sendmail configuration file is not open"
  6432.     }
  6433.     # NOTE: We are assuming that we would never want to intentionally
  6434.     #        set the j macro to a null string, or white space
  6435.     #        Also, if the j macro is in turn defined by other
  6436.     #        macros, then the macros are not expanded.
  6437.     if {[ctype space $name]} {
  6438.     set name ""
  6439.     }
  6440.     set currentName [ma_machine_name_get]
  6441.     if {[cequal $name $currentName ]} {
  6442.     return
  6443.     }
  6444.     if {[cequal $name ""]} {
  6445.     # unset the machine name in sendmail.cf, which allows
  6446.     # sendmail itself to internally define these
  6447.     CF:RemoveValue $MA_SENDMAIL_FILEID class w \
  6448.         [list [CF:Get $MA_SENDMAIL_FILEID macro j] \
  6449.               [CF:Get $MA_SENDMAIL_FILEID macro w]]
  6450.     CF:Unset $MA_SENDMAIL_FILEID macro j
  6451.     CF:Unset $MA_SENDMAIL_FILEID macro w
  6452.     CF:Unset $MA_SENDMAIL_FILEID macro m
  6453.     CF:Unset $MA_SENDMAIL_FILEID macro k
  6454.     } else {
  6455.     set fqdn $name
  6456.     set host [ctoken name "."]
  6457.     set domain [string trim $name "."]
  6458.     if {"$currentName" != ""} {
  6459.         if {[regexp {([^\.]+)\..+} $currentName \
  6460.             match currentHost] == 1} {
  6461.             set removeList [list $currentName $currentHost]
  6462.         } else {
  6463.             set removeList [list $currentName]
  6464.         }
  6465.         CF:RemoveValue $MA_SENDMAIL_FILEID class w $removeList
  6466.     }
  6467.     CF:Set $MA_SENDMAIL_FILEID macro w $host
  6468.     CF:Set $MA_SENDMAIL_FILEID macro m $domain
  6469.     CF:Set $MA_SENDMAIL_FILEID macro j $fqdn
  6470.     CF:Set $MA_SENDMAIL_FILEID macro k $host
  6471.     CF:AddValue $MA_SENDMAIL_FILEID class w \
  6472.         [list $host $fqdn]
  6473.     }
  6474. }
  6475. proc ma_alternate_names_get {} {
  6476.     global MA_SENDMAIL_FILEID
  6477.     if {$MA_SENDMAIL_FILEID == -1} {
  6478.     error "Sendmail configuration file is not open"
  6479.     }
  6480.     set list [CF:Get $MA_SENDMAIL_FILEID class w]
  6481.     if { [lindex $list 0] == "\$M" } {
  6482.         set list [lrange $list 1 end]
  6483.     }
  6484.     return $list
  6485. }
  6486. proc ma_alternate_names_set {nameList} {
  6487.     global MA_SENDMAIL_FILEID
  6488.     if {$MA_SENDMAIL_FILEID == -1} {
  6489.     error "Sendmail configuration file is not open"
  6490.     }
  6491.     if {[llength $nameList] == 0} {
  6492.     CF:Set $MA_SENDMAIL_FILEID class w "\$M"
  6493.     } else {
  6494.     CF:Set $MA_SENDMAIL_FILEID class w "\$M $nameList"
  6495.     }
  6496. }
  6497. proc ma_from_domain_get {} {
  6498.     global MA_SENDMAIL_FILEID
  6499.     if {$MA_SENDMAIL_FILEID == -1} {
  6500.     error "Sendmail configuration file is not open"
  6501.     }
  6502.     return [CF:Get $MA_SENDMAIL_FILEID macro M]
  6503. }
  6504. proc ma_from_domain_set {domain} {
  6505.     global MA_SENDMAIL_FILEID
  6506.     if {$MA_SENDMAIL_FILEID == -1} {
  6507.     error "Sendmail configuration file is not open"
  6508.     }
  6509.     CF:Set $MA_SENDMAIL_FILEID macro M $domain
  6510. }
  6511. proc ma_aliases_get {} {
  6512.     global MA_SENDMAIL_FILEID
  6513.     set result {}
  6514.     if {$MA_SENDMAIL_FILEID == -1} {
  6515.     error "Sendmail configuration file is not open"
  6516.     }
  6517.     foreach aliasFile \
  6518.     [split [CF:Get $MA_SENDMAIL_FILEID option AliasFile] {,}] {
  6519.     lappend result "[string trim $aliasFile]"
  6520.     }
  6521.     return $result
  6522. }
  6523. proc ma_aliases_set {aliasFileList} {
  6524.     global MA_SENDMAIL_FILEID
  6525.     if {$MA_SENDMAIL_FILEID == -1} {
  6526.     error "Sendmail configuration file is not open"
  6527.     }
  6528.     set cfString ""
  6529.     foreach aliasFile $aliasFileList {
  6530.     append cfString "$aliasFile,"
  6531.     }
  6532.     set cfString [string trimright $cfString ","]
  6533.     CF:Set $MA_SENDMAIL_FILEID option AliasFile $cfString
  6534. }
  6535. proc ma_domain_table_enabled_get {} {
  6536.     global MA_SENDMAIL_FILEID
  6537.     if {$MA_SENDMAIL_FILEID == -1} {
  6538.     error "Sendmail configuration file is not open"
  6539.     }
  6540.     set cfString [CF:Get $MA_SENDMAIL_FILEID macro D]
  6541.     if {[clength $cfString] == 0} {
  6542.     return 0
  6543.     } else {
  6544.     return 1
  6545.     }
  6546. }
  6547. proc ma_domain_table_enabled_set {enable} {
  6548.     global MA_SENDMAIL_FILEID
  6549.     if {$MA_SENDMAIL_FILEID == -1} {
  6550.     error "Sendmail configuration file is not open"
  6551.     }
  6552.     if {$enable} {
  6553.     CF:Set $MA_SENDMAIL_FILEID macro D DMNTAB
  6554.     } else {
  6555.     CF:Set $MA_SENDMAIL_FILEID macro D ""
  6556.     }
  6557. }
  6558. proc ma_domain_table_file_get {} {
  6559.     global MA_SENDMAIL_FILEID
  6560.     if {$MA_SENDMAIL_FILEID == -1} {
  6561.     error "Sendmail configuration file is not open"
  6562.     }
  6563.     set mapInfo [CF:GetMapInfo $MA_SENDMAIL_FILEID domain]
  6564.     keylget mapInfo pathName mapFile
  6565.     return $mapFile
  6566. }
  6567. proc mai_ch_default_equates {} {
  6568.     set equateList {}
  6569.     keylset equateList P "\[IPC\]"
  6570.     keylset equateList F "mDFMuXa"
  6571.     keylset equateList S "ap822_se/ap822_sh"
  6572.     keylset equateList R "ap822_re/ap822_rh"
  6573.     keylset equateList E "\\r\\n"
  6574.     keylset equateList L "990"
  6575.     keylset equateList A "IPC \$h"
  6576.     return $equateList
  6577. }
  6578. proc mai_ch_equates_get { mailer } {
  6579.     global MA_SENDMAIL_FILEID
  6580.     set equateStr [CF:Get $MA_SENDMAIL_FILEID mailer $mailer]
  6581.     set equateList {}
  6582.     set equatesAttr {}
  6583.     set listitem ""
  6584.     while {[set token [ctoken equateStr ","]] != {}} {
  6585.     set i [expr [clength $token] - 1]
  6586.     set backslashes 0
  6587.     # if there is a \ before the comma, we have to count the
  6588.     # number of \'s before the comma, since \\ is acceptable
  6589.     # as well as \,
  6590.     while {$i >= 0 && [cindex $token $i] == "\\"} {
  6591.         incr backslashes
  6592.         set i [expr $i - 1]
  6593.     }
  6594.     if {[expr $backslashes % 2] == 1} {
  6595.         set listitem "${listitem}${token},"
  6596.     } else {
  6597.         set listitem "${listitem}${token}"
  6598.         lappend equateList $listitem
  6599.         set listitem ""
  6600.     }
  6601.     }
  6602.     foreach equate $equateList {
  6603.     if {[regexp {([A-Z]).*=[     ]*(.*)} $equate \
  6604.         match equateLetter equateValue] == 1} {
  6605.         keylset equatesAttr $equateLetter [string trim $equateValue]
  6606.     }
  6607.     }
  6608.     return $equatesAttr
  6609. }
  6610. proc mai_ch_order {chName1 chName2} {
  6611.     global channels
  6612.     set seq1 [lindex $channels($chName1) 0]
  6613.     set seq2 [lindex $channels($chName2) 0]
  6614.     if {$seq1 < $seq2} {
  6615.     return -1
  6616.     } elseif {$seq1 == $seq2} {
  6617.     return 0
  6618.     } else {
  6619.     return 1
  6620.     }
  6621. }
  6622. proc mai_ch_valid_table_type {type} {
  6623.     global MA_CH_TABLE_TYPE_LIST
  6624.     if {[lsearch -exact $MA_CH_TABLE_TYPE_LIST $type] == -1} {
  6625.     return 0
  6626.     } else {
  6627.     return 1
  6628.     }
  6629. }
  6630. proc mai_ch_valid_name {name} {
  6631.     global MA_SENDMAIL_FILEID MA_CH_RESERVED_NAMES channels
  6632.     # check if this channel already exists
  6633.     set currentNames [ma_ch_names_get]
  6634.     if {[lsearch -exact $currentNames $name] != -1} {
  6635.         return 0
  6636.     }
  6637.     # check if this channel name is a reserved name
  6638.     if {[lsearch -exact $MA_CH_RESERVED_NAMES $name] != -1} {
  6639.     return 0
  6640.     }
  6641.     # check if this channel name already exists as a ruleset or mailer name
  6642.     set rulesetAndMailerNames [union [Table:List $MA_SENDMAIL_FILEID ruleset] \
  6643.                 [Table:List $MA_SENDMAIL_FILEID mailer]]
  6644.     if {[lsearch -exact $rulesetAndMailerNames $name] != -1} {
  6645.     return 0
  6646.     }
  6647.     # would this channel name have a conflict with the map name ${name}_MAP ?
  6648.     set mapNames [Table:List $MA_SENDMAIL_FILEID map]
  6649.     if {[lsearch -exact $mapNames ${name}_MAP] != -1} {
  6650.     return 0
  6651.     }
  6652.     return 1
  6653. }
  6654. proc mai_ch_valid_chars {name} {
  6655.     global MA_SENDMAIL_FILEID
  6656.     # get the characters that sendmail uses internally as separation chars
  6657.     set oValue [CF:Get $MA_SENDMAIL_FILEID macro o]
  6658.     set invalidChars "${oValue}()<>,;\\\"\r\n\t "
  6659.     if {[llength [split $name $invalidChars]] > 1} {
  6660.     return 0
  6661.     }
  6662.     return 1
  6663. }
  6664. proc mai_ch_structure_init {} {
  6665.     global MA_SENDMAIL_FILEID MA_CH_TABLE_TYPE channels MA_CH_TABLE_DIRECTORY
  6666.     set channelsRuleset [CF:Get $MA_SENDMAIL_FILEID ruleset channels]
  6667.     if {$channelsRuleset == ""} {
  6668.     error "Ruleset \"channels\" doesn't exist; config file not compatible."
  6669.     }
  6670.     set channelsList [split $channelsRuleset "\n"]
  6671.     set thisSeq 0
  6672.     foreach rule $channelsList {
  6673.     if {[regexp {^R\$\*[    ]+\$:[ ]*\$>[ ]*([^ ]+)[ ]+\$1} \
  6674.         $rule match chName] == 1} {
  6675.         set sequenceAttr $thisSeq
  6676.         set channelRulesList \
  6677.         [split [CF:Get $MA_SENDMAIL_FILEID ruleset $chName] "\n"]
  6678.         set rule1 [lindex $channelRulesList 0]
  6679.         set rule2 [lindex $channelRulesList 1]
  6680.         #
  6681.         # Determine table type, table file...
  6682.         #
  6683.         if {[regexp {\$:[ ]*\$>[ ]*([^ ]+)[ ]*\$} \
  6684.         $rule1 match table] == 1} {
  6685.         # See if a built in table (ruleset)
  6686.         if {[info exists MA_CH_TABLE_TYPE($table)]} {
  6687.             # this is a built-in table type
  6688.             set tableTypeAttr "$MA_CH_TABLE_TYPE($table)"
  6689.         } else {
  6690.             # we don't know what table type this is
  6691.             error "Unknown table type \"$table\""
  6692.         }    
  6693.         set tableFileAttr ""
  6694.         } elseif {[regexp {\$:[ ]*<[ ]*\$\(([^ ]+)[ ]+.*\$\)[ ]*>} \
  6695.             $rule1 match mapName] == 1} {
  6696.         # Otherwise, see if a there's a table map file
  6697.         set tableTypeAttr "file"
  6698.         set mapConfigStr [CF:Get $MA_SENDMAIL_FILEID map $mapName]
  6699.         if {[clength $mapConfigStr] != 0} {
  6700.             set tableFileAttr "[lindex $mapConfigStr end]"
  6701.         } else {
  6702.             set tableFileAttr "$MA_CH_TABLE_DIRECTORY/${chName}"
  6703.         }
  6704.         } else {
  6705.             # This channel is not defined within expected conventions
  6706.         error "Invalid channel \"$chName\": cannot determine table"
  6707.         }
  6708.         #
  6709.         # Determine delivery agent...
  6710.         #
  6711.         set equatesAttr {}
  6712.         if {[regexp {\$#[ ]*([^ ]+)[ ]+} \
  6713.         $rule2 match mailer] == 1} {
  6714.         # By convention, the mailer name should be the same as the
  6715.         # channel name.
  6716.         if {![cequal $mailer $chName]} {
  6717.             error "Channel \"$chName\" has different mailer name \"$mailer\""
  6718.         }
  6719.         set equatesAttr [mai_ch_equates_get $mailer]
  6720.         } else {
  6721.             # This channel is not defined within expected conventions
  6722.         error "Invalid channel \"$chName\": cannot determine deliver agent"
  6723.         }
  6724.         if {[lempty $equatesAttr]} {
  6725.         error "Invalid channel \"$chName\": no delivery agent equates"
  6726.         }
  6727.         #
  6728.         # Determine forwarding host (if any)...
  6729.         #
  6730.         if {[regexp {\$@[ ]*([^ ]+)[ ]*\$:} \
  6731.         $rule2 match host] == 1} {
  6732.         if {[regexp {\$[0-9]+} $host] == 1} {
  6733.            # $@ is a positional parameter
  6734.             set forwardHostAttr ""
  6735.         } else {
  6736.             # Note: This allows host= to be a defined macro
  6737.             set forwardHostAttr $host    
  6738.         }
  6739.         } else {
  6740.         # No $@ host specification (probably a channel that
  6741.         # does local delivery)
  6742.         set forwardHostAttr ""
  6743.         }
  6744.         set attributeList [list $sequenceAttr\
  6745.                     $tableTypeAttr \
  6746.                     $tableFileAttr \
  6747.                     $forwardHostAttr \
  6748.                     $equatesAttr]
  6749.         set channels($chName) $attributeList
  6750.         incr thisSeq    
  6751.     }
  6752.     }
  6753.     #
  6754.     # Determine if baduser host is configured
  6755.     #
  6756.     set lastRuleset5 \
  6757.     [lindex [split [CF:Get $MA_SENDMAIL_FILEID ruleset 5] "\n" ] end]
  6758.     if {[regexp {\$:[ ]*\$>([^ ]+)[ ]*\$1} $lastRuleset5 \
  6759.     match subroutineName] == 1} {
  6760.     set subroutineRules \
  6761.         [split [CF:Get $MA_SENDMAIL_FILEID ruleset $subroutineName] "\n"]
  6762.     if {[regexp {\$:[ ]*\$>([^ ]*)[ ]*} [lindex $subroutineRules 0] \
  6763.         match tableRoutine] == 1 && [cequal $tableRoutine "baduser_TBL"]} {
  6764.         set chName $subroutineName
  6765.         set sequenceAttr $thisSeq
  6766.         set tableTypeAttr "baduser"
  6767.         set tableFileAttr ""
  6768.         set forwardHostAttr ""
  6769.         set equatesAttr {}
  6770.         # get mailer's equates
  6771.         if {[regexp {\$#[ ]*([^ ]+)[ ]+} \
  6772.         [lindex $subroutineRules 1] match mailer] == 1} {
  6773.         if {![cequal $mailer $chName]} {
  6774.             error "Channel \"$chName\" has different mailer name \"$mailer\""
  6775.         }
  6776.         set equatesAttr [mai_ch_equates_get $mailer]
  6777.         }
  6778.         if {[lempty $equatesAttr]} {
  6779.         error "Invalid channel \"$chName\": no delivery agent equates"
  6780.         }
  6781.         # get the forwarding host
  6782.         if {[regexp {\$@[ ]*([^ ]*)[ ]*\$:} \
  6783.         [lindex $subroutineRules 1] match host] == 1} {
  6784.             # NOTE: By convention, we always put the
  6785.             # name of the forwarding host in the $@ portion
  6786.             # of the triple.  But the cf file could be hand
  6787.             # edited to put some macro, or operator there-- these
  6788.             # are simply passed up for now, but maybe some error
  6789.             # checks should be put in?
  6790.             set forwardHostAttr $host
  6791.         }
  6792.         set attributeList [list \
  6793.         $sequenceAttr \
  6794.         $tableTypeAttr \
  6795.         $tableFileAttr \
  6796.         $forwardHostAttr \
  6797.         $equatesAttr]
  6798.         set channels($chName) $attributeList
  6799.     }
  6800.     }
  6801. }
  6802. proc mai_ch_structure_commit {} {
  6803.     global MA_SENDMAIL_FILEID MA_CH_RULESET MA_CH_TABLE_DIRECTORY channels
  6804.     set orderedNames [ma_ch_names_get]
  6805.     set numChannels [llength $orderedNames]
  6806.     set channelsRuleset ""
  6807.     loop index 1 [expr $numChannels + 1] {
  6808.     set chName [lvarpop orderedNames]
  6809.     set tableType [lindex $channels($chName) 1]
  6810.     set tableFile [lindex $channels($chName) 2]
  6811.     set forwardingHost [lindex $channels($chName) 3]
  6812.     set equateList [lindex $channels($chName) 4]
  6813.     #
  6814.     # Construct the ruleset for this channel, depending upon the table type
  6815.     #
  6816.     set thisChannelRuleset ""
  6817.     case $tableType {
  6818.         file {
  6819.         if {[clength $tableFile] == 0 || [ctype space $tableFile]} {
  6820.             error "Channel \"$chName\" has table type \"file\" but no table file defined."
  6821.         }
  6822.         append thisChannelRuleset \
  6823.         "R\$*<@\$+.>\$*\t\t\$: <\$(${chName}_MAP \$2 \$)> \$1<@\$2.>\$3\n"
  6824.         append thisChannelRuleset \
  6825.         "R<\$+.FOUND>\$+\t\t\$# $chName \$@ \$1 \$: \$2\n"
  6826.         append thisChannelRuleset \
  6827.         "R<\$+>\$+\t\t\t$@ \$2"
  6828.         # Add call to this channel's ruleset to Schannels
  6829.         append channelsRuleset "R\$*\t\t\t\$: \$>${chName} \$1\n"
  6830.         # Add the K map command too
  6831.         CF:Set $MA_SENDMAIL_FILEID map ${chName}_MAP \
  6832.             " hash -o -a.FOUND $tableFile"
  6833.         }
  6834.         local {
  6835.         append thisChannelRuleset \
  6836.         "R\$*\t\t\t\$: \$>local_TBL \$1\n"
  6837.         if {[clength $forwardingHost] == 0} {
  6838.             append thisChannelRuleset \
  6839.             "R<FOUND>\$+\t\t\$# $chName \$: \$1"
  6840.         } else {
  6841.             append thisChannelRuleset \
  6842.             "R<FOUND>\$+\t\t\$# $chName \$@ $forwardingHost \$: \$1"
  6843.         }    
  6844.         # Add call to this channel's ruleset to Schannels
  6845.         append channelsRuleset "R\$*\t\t\t\$: \$>${chName} \$1\n"
  6846.         }
  6847.         baduser {
  6848.         if {$index != $numChannels} {
  6849.             error "Baduser channel \"$chName\" is not last in order"
  6850.         }
  6851.         append thisChannelRuleset \
  6852.         "R\$+\t\t\t\$: \$>baduser_TBL \$1\n"
  6853.         if {[clength $forwardingHost] == 0} {
  6854.             append thisChannelRuleset \
  6855.             "R<FOUND>\$+\t\t\$# $chName \$: \$1"
  6856.         } else {
  6857.             append thisChannelRuleset \
  6858.             "R<FOUND>\$+\t\t\$# $chName \$@ $forwardingHost \$: \$1"
  6859.         }
  6860.         # Add call to baduser ruleset to S5, 
  6861.         # if not already there
  6862.         set baduserRule "\nR\$*\t\t\t\$: \$>${chName} \$1"
  6863.         set exp "\\\$>${chName}"
  6864.         set ruleset5 [CF:Get $MA_SENDMAIL_FILEID ruleset 5]
  6865.         set lastRuleset5 [lindex [split $ruleset5 "\n"] end]
  6866.         if {[regexp $exp $lastRuleset5] == 0} {
  6867.             append ruleset5 $baduserRule
  6868.             CF:Set $MA_SENDMAIL_FILEID ruleset 5 $ruleset5
  6869.         }
  6870.         }
  6871.         default {
  6872.         append thisChannelRuleset \
  6873.         "R\$*<@\$+.>\$*\t\t\$: \$>$MA_CH_RULESET($tableType) \$1<@\$2.>\$3\n"
  6874.         if {[clength $forwardingHost] == 0} {
  6875.             append thisChannelRuleset \
  6876.             "R<FOUND>\$*<@\$+.>\$*\t\$# $chName \$@ \$2 \$: \$1<@\$2.>\$3"
  6877.         } else {
  6878.             append thisChannelRuleset \
  6879.             "R<FOUND>\$*<@\$+.>\$*\t\$# $chName \$@ $forwardingHost \$: \$1<@\$2.>\$3"
  6880.         }
  6881.         # Add call to this channel's ruleset to Schannels
  6882.         append channelsRuleset "R\$*\t\t\t\$: \$>${chName} \$1\n"
  6883.         }
  6884.     }
  6885.     # Set this channel's ruleset in the cf file
  6886.     CF:Set $MA_SENDMAIL_FILEID ruleset $chName $thisChannelRuleset
  6887.     # Set the mailer for this channel
  6888.     set equateString ""
  6889.     set fields [keylkeys equateList]
  6890.     set indexA [lsearch -exact $fields "A"]
  6891.     if {$indexA != -1} {
  6892.         lvarpop fields $indexA
  6893.         set argA [keylget equateList A]
  6894.     }
  6895.     foreach field $fields {
  6896.         set arg [keylget equateList $field]
  6897.         append equateString "${field}=${arg},"
  6898.     }
  6899.     if {$indexA != -1} {
  6900.         append equateString "A=${argA}"
  6901.     }
  6902.     if {[clength $equateString] == 0} {
  6903.         error "Channel \"$chName\" has no delivery agent equates specified"
  6904.     }
  6905.     CF:Set $MA_SENDMAIL_FILEID mailer $chName \
  6906.         [string trim $equateString " \t,"]
  6907.     }
  6908.     # Set the Schannels in the cf file
  6909.     CF:Set $MA_SENDMAIL_FILEID ruleset channels \
  6910.     [string trim $channelsRuleset "\n"]
  6911. }
  6912. proc ma_ch_names_get {} {
  6913.     global MA_SENDMAIL_FILEID channels
  6914.     set result {}
  6915.     if {$MA_SENDMAIL_FILEID == -1} {
  6916.     error "Sendmail configuration file is not open"
  6917.     }
  6918.     if {[info exists channels]} {
  6919.     set allNames [array names channels]
  6920.     set result [lsort -command mai_ch_order $allNames]
  6921.     }
  6922.     return $result
  6923. }
  6924. proc ma_ch_sequence_get {chName} {
  6925.     global channels
  6926.     if {![info exists channels($chName)]} {
  6927.     error "Unknown channel \"$chName\""
  6928.     }
  6929.     return [lindex $channels($chName) 0]
  6930. }
  6931. proc ma_ch_sequence_set {chName sequence} {
  6932.     global channels MA_CH_MODIFIED
  6933.     if {![info exists channels($chName)]} {
  6934.     error "Unknown channel \"$chName\""
  6935.     }
  6936.     lvarpop channels($chName)
  6937.     lvarpush channels($chName) $sequence
  6938.     set MA_CH_MODIFIED 1
  6939. }
  6940. proc ma_ch_table_type_get {chName} {
  6941.     global channels
  6942.     if {![info exists channels($chName)]} {
  6943.     error "Unknown channel \"$chName\""
  6944.     }
  6945.     return [lindex $channels($chName) 1]
  6946. }
  6947. proc ma_ch_table_type_set {chName type} {
  6948.     global channels MA_CH_MODIFIED
  6949.     if {![info exists channels($chName)]} {
  6950.     error "Unknown channel \"$chName\""
  6951.     }
  6952.     if {[mai_ch_valid_table_type $type]} {
  6953.     lvarpop channels($chName) 1
  6954.     lvarpush channels($chName) $type 1
  6955.     set MA_CH_MODIFIED 1
  6956.     } else {
  6957.     error "Unknown channel table type \"$type\""
  6958.     }
  6959. }
  6960. proc ma_ch_table_file_get {chName} {
  6961.     global channels
  6962.     if {![info exists channels($chName)]} {
  6963.     error "Unknown channel \"$chName\"" 
  6964.     }
  6965.     return [lindex $channels($chName) 2]
  6966. }
  6967. proc ma_ch_table_file_set {chName file} {
  6968.     global channels MA_CH_MODIFIED
  6969.     if {![info exists channels($chName)]} {
  6970.     error "Unknown channel \"$chName\""
  6971.     }
  6972.     lvarpop channels($chName) 2
  6973.     lvarpush channels($chName) $file 2
  6974.     set MA_CH_MODIFIED 1
  6975. }
  6976. proc ma_ch_host_get {chName} {
  6977.     global channels
  6978.     if {![info exists channels($chName)]} {
  6979.     error "Unknown channel \"$chName\""
  6980.     }
  6981.     return [lindex $channels($chName) 3]
  6982. }
  6983. proc ma_ch_host_set {chName host} {
  6984.     global channels MA_CH_MODIFIED
  6985.     if {![info exists channels($chName)]} {
  6986.     error "Unknown channel \"$chName\""
  6987.     }
  6988.     lvarpop channels($chName) 3
  6989.     lvarpush channels($chName) $host 3
  6990.     set MA_CH_MODIFIED 1
  6991. }
  6992. proc ma_ch_equate_get {chName equate} {
  6993.     global channels
  6994.     set equateValue ""
  6995.     if {![info exists channels($chName)]} {
  6996.     error "Unknown channel \"$chName\""
  6997.     }
  6998.     set equateList [lindex $channels($chName) 4]
  6999.     keylget equateList $equate equateValue
  7000.     return $equateValue
  7001. }
  7002. proc ma_ch_equate_set {chName equateName equateValue} {
  7003.     global channels MA_CH_MODIFIED
  7004.     if {![info exists channels($chName)]} {
  7005.     error "Unknown channel \"$chName\""
  7006.     }
  7007.     set equateList [lindex $channels($chName) 4]
  7008.     if {[clength $equateValue] == 0} {
  7009.     set currentEquates [keylkeys equateList]
  7010.     if {[lsearch -exact $currentEquates $equateName] != -1} {
  7011.         keyldel equateList $equateName
  7012.     } else {
  7013.         return
  7014.     }
  7015.     } else {
  7016.     keylset equateList $equateName $equateValue
  7017.     }
  7018.     set oldChannel $channels($chName)
  7019.     set newChannel [lreplace $oldChannel 4 4 $equateList]
  7020.     set channels($chName) $newChannel
  7021.     set MA_CH_MODIFIED 1
  7022. }
  7023. proc ma_ch_create {chName} {
  7024.     global channels MA_CH_MODIFIED
  7025.     if {![mai_ch_valid_chars $chName]} {
  7026.     return "badname"
  7027.     }
  7028.     if {[cequal "$chName" ""]} {
  7029.     return "badname"
  7030.     }
  7031.     if {![mai_ch_valid_name $chName]} {
  7032.     return "conflict"
  7033.     }
  7034.     set sequence [llength [ma_ch_names_get]]
  7035.     set tableType "DNS"
  7036.     set tableFile ""
  7037.     set host ""
  7038.     set equates [mai_ch_default_equates]
  7039.     set channels($chName) [list $sequence $tableType $tableFile $host $equates]
  7040.     set MA_CH_MODIFIED 1
  7041.     return "ok"
  7042. }
  7043. proc ma_ch_delete {chName} {
  7044.     global MA_SENDMAIL_FILEID MA_CH_MODIFIED channels
  7045.     if {![info exists channels($chName)]} {
  7046.     error "Unknown channel \"$chName\""
  7047.     }
  7048.     CF:Unset $MA_SENDMAIL_FILEID ruleset $chName
  7049.     CF:Unset $MA_SENDMAIL_FILEID mailer $chName
  7050.     set tableType [lindex $channels($chName) 1]
  7051.     # if there is a channel table file, remove associated map config cmd
  7052.     if {[cequal $tableType "file"]} {
  7053.     CF:Unset $MA_SENDMAIL_FILEID map "${chName}_MAP"
  7054.     }
  7055.     # if this is the baduser channel, then remove subroutine call in S5
  7056.     if {[cequal $tableType "baduser"]} {
  7057.     set ruleset5 [split [CF:Get $MA_SENDMAIL_FILEID ruleset 5] "\n" ]
  7058.     set lastLine [lindex $ruleset5 end]
  7059.     if {[regexp {\$:[ ]*\$>([^ ]+)[ ]*\$1} $lastLine \
  7060.         match subroutineName] == 1 && [cequal $subroutineName $chName]} {
  7061.         lvarpop ruleset5 end
  7062.         set newRuleset5 [join $ruleset5 "\n"]
  7063.         CF:Set $MA_SENDMAIL_FILEID ruleset 5 $newRuleset5
  7064.     }
  7065.     }
  7066.     unset channels($chName)
  7067.     set MA_CH_MODIFIED 1
  7068. }
  7069. proc ma_ch_rename {oldName newName} {
  7070.     global MA_SENDMAIL_FILEID MA_CH_MODIFIED channels
  7071.     if {![info exists channels($oldName)]} {
  7072.     error "Unknown channel \"$oldName\""
  7073.     }
  7074.     if {![mai_ch_valid_chars $newName]} {
  7075.     return "badname"
  7076.     }
  7077.     if {[cequal "$newName" ""]} {
  7078.     return "badname"
  7079.     }
  7080.     if {![mai_ch_valid_name $newName]} {
  7081.     return "conflict"
  7082.     }
  7083.     # create a new channel in our internal channel data structure,
  7084.     # using the old channel's data
  7085.     set channels($newName) $channels($oldName)
  7086.     # unset the cf lines associated with the old channel
  7087.     # (we don't have to set them here-- that will be done anyway in 
  7088.     # mai_ch_structure_commit)
  7089.     CF:Unset $MA_SENDMAIL_FILEID ruleset $oldName
  7090.     CF:Unset $MA_SENDMAIL_FILEID mailer $oldName
  7091.     set tableType [lindex $channels($oldName) 1]
  7092.     if {[cequal $tableType "file"]} {
  7093.     CF:Unset $MA_SENDMAIL_FILEID map "${oldName}_MAP"
  7094.     }
  7095.     # if this is the baduser channel, want to remove the last rule in
  7096.     # ruleset 5
  7097.     if {[cequal $tableType "baduser"]} {
  7098.     set ruleset5 [split [CF:Get $MA_SENDMAIL_FILEID ruleset 5] "\n" ]
  7099.     set lastLine [lindex $ruleset5 end]
  7100.     if {[regexp {\$:[ ]*\$>([^ ]+)[ ]*\$1} $lastLine \
  7101.         match subroutineName] == 1 && [cequal $subroutineName $oldName]} {
  7102.         lvarpop ruleset5 end
  7103.         set newRuleset5 [join $ruleset5 "\n"]
  7104.         CF:Set $MA_SENDMAIL_FILEID ruleset 5 $newRuleset5
  7105.     }
  7106.     }
  7107.     # remove the old channel from our internal channel data structure
  7108.     unset channels($oldName)
  7109.     set MA_CH_MODIFIED 1
  7110.     return "ok"
  7111. }
  7112. proc ma_multihome_macro_set {enable} {
  7113.     global MA_SENDMAIL_FILEID
  7114.     if {$MA_SENDMAIL_FILEID == -1} {
  7115.     error "Sendmail configuration file is not open"
  7116.     }
  7117.     if {$enable} {
  7118.     CF:Set $MA_SENDMAIL_FILEID macro V VIRTDOMAINS
  7119.     } else {
  7120.     CF:Set $MA_SENDMAIL_FILEID macro V ""
  7121.     }
  7122. }
  7123. proc ConfigFile:Open {} {
  7124.     global Config_next
  7125.     if {![info exists Config_next]} {
  7126.     set Config_next 0
  7127.     }
  7128.     set file "config$Config_next"
  7129.     incr Config_next
  7130.     upvar #0 Config_${file}_next file_next
  7131.     set file_next "1.0"
  7132.     return $file
  7133. }
  7134. proc ConfigFile:Close {file} {
  7135.     upvar #0 Config_$file fileList
  7136.     upvar #0 Config_${file}_next file_next
  7137.     unset file_next
  7138.     foreach line [ConfigFile:GetList $file] {
  7139.     unset fileList($line)
  7140.     }
  7141. }
  7142. proc ConfigFile:Compare {line1 line2} {
  7143.     set subLine1 [ctoken line1 "."]
  7144.     set subLine2 [ctoken line2 "."]
  7145.     if {$subLine1 == "" && $subLine2 == ""} {
  7146.     return 0
  7147.     } elseif {$subLine1 == ""} {
  7148.     return -1
  7149.     }  elseif {$subLine2 == ""} {
  7150.     return 1
  7151.     } elseif {$subLine1 < $subLine2} {
  7152.     return -1
  7153.     } elseif {$subLine1 > $subLine2} {
  7154.     return 1
  7155.     } else {
  7156.     set line1 [string trimleft $line1 "."]
  7157.     set line2 [string trimleft $line2 "."]
  7158.     return [ConfigFile:Compare $line1 $line2]
  7159.     }
  7160. }
  7161. proc ConfigFile:ReplaceLine {file line type id dataVar} {
  7162.     upvar #0 Config_$file fileList
  7163.     upvar #0 Config_${file}_next file_next
  7164.     upvar $dataVar data
  7165.     keylset fileList($line) type $type
  7166.     keylset fileList($line) data $data
  7167.     keylset fileList($line) id $id
  7168.     if {[ConfigFile:Compare $line $file_next] == 1} {
  7169.     set temp $line
  7170.     set file_next [ctoken temp "."]
  7171.     incr file_next
  7172.     set file_next "${file_next}.0"
  7173.     }
  7174. }
  7175. proc ConfigFile:AppendLine {file line type id dataVar} {
  7176.     upvar #0 Config_$file fileList
  7177.     upvar #0 Config_${file}_next file_next
  7178.     upvar $dataVar data
  7179.     if {$line == -1} {
  7180.     set line $file_next
  7181.     set temp [ctoken file_next "."]
  7182.     incr temp
  7183.     set file_next "${temp}.0"
  7184.     } else {
  7185.     set found 0
  7186.     set left [ctoken line "."]
  7187.     set right [ctoken line "."]
  7188.     if {$right == "0"} {
  7189.         set tryNext $left
  7190.         incr tryNext
  7191.         set tryNext "${tryNext}.0"
  7192.         if {![info exists fileList($tryNext)]} { 
  7193.         set found 1
  7194.         }
  7195.     }
  7196.     if {!$found} {
  7197.         set lastDigit [cindex $right end]
  7198.         if {$lastDigit < 9} {
  7199.             incr lastDigit
  7200.             set tryNext "${left}.[csubstr $right 0 end]${lastDigit}"
  7201.             if {![info exists fileList($tryNext)]} {
  7202.             set found 1
  7203.             }    
  7204.         }
  7205.     }
  7206.     if {!$found} {
  7207.         set leadingZeros ""
  7208.         set tryNext "${left}.${right}.1"
  7209.         while {[info exists fileList($tryNext)]} {
  7210.         set leadingZeros "${leadingZeros}.0"
  7211.         set tryNext "${left}.${right}${leadingZeros}.1"
  7212.         }
  7213.     }
  7214.     set line $tryNext
  7215.     }
  7216.     keylset fileList($line) type $type
  7217.     keylset fileList($line) id $id
  7218.     keylset fileList($line) data $data
  7219.     if {[string compare $line $file_next] == 1} {
  7220.     set temp $line
  7221.     set file_next [ctoken temp "."]
  7222.     incr file_next
  7223.     set file_next "${file_next}.0"
  7224.     }
  7225.     return $line
  7226. }
  7227. proc ConfigFile:GetLine {file line typeVar idVar dataVar} {
  7228.     upvar #0 Config_$file fileList
  7229.     upvar $typeVar type
  7230.     upvar $idVar id
  7231.     upvar $dataVar data
  7232.     if {![info exists fileList($line)]} {
  7233.     set type {}
  7234.     set id {}
  7235.     set data {}
  7236.     return -1
  7237.     }
  7238.     keylget fileList($line) type type
  7239.     keylget fileList($line) id id
  7240.     keylget fileList($line) data data
  7241.     return 0
  7242. }
  7243. proc ConfigFile:RemoveLine {file line} {
  7244.     upvar #0 Config_$file fileList
  7245.     if {![info exists fileList($line)]} {
  7246.     # already gone
  7247.     return
  7248.     }
  7249.     unset fileList($line)
  7250. }
  7251. proc ConfigFile:GetList {file} {
  7252.     upvar #0 Config_$file fileList
  7253.     if {![info exists fileList]} {
  7254.     return {}
  7255.     }
  7256.     return [lsort -command ConfigFile:Compare [array names fileList]]
  7257. }
  7258. proc Table:ProcessLine {fileID type id data} {
  7259.     global Table_lastType Table_lastID
  7260.     set lineNum [ConfigFile:AppendLine $fileID -1 $type $id data]
  7261.     if {[Table:GetOption $fileID makelower] != {}} {
  7262.     set id [string tolower $id]
  7263.     }
  7264.     case $type {
  7265.     CONTINUATION {
  7266.         set type $Table_lastType
  7267.         set id $Table_lastID
  7268.     }
  7269.     COMMENT {
  7270.     }
  7271.     default {
  7272.         set Table_lastType $type
  7273.         set Table_lastID $id
  7274.     }
  7275.     }
  7276.     if {$id != {}} {
  7277.     upvar #0 Table_${fileID}_$type typeList
  7278.     lappend typeList($id) $lineNum
  7279.     }
  7280. }
  7281. proc Table:Read {fileName callBack mode} {
  7282.     global Table_info
  7283.     if {[info exists Table_info($fileName.ID)]} {
  7284.     return $Table_info($fileName.ID)
  7285.     }
  7286.     set fileID [ConfigFile:Open]
  7287.     set Table_info($fileID.mode) $mode
  7288.     if {![file exists $fileName]} {
  7289.     return $fileID
  7290.     }
  7291.     set fp [open $fileName r]
  7292.     set Table_info($fileName.ID) $fileID
  7293.     set Table_info($fileID.fileName) $fileName
  7294.     eval $callBack $fileID $fp
  7295.     close $fp
  7296.     return $fileID
  7297. }
  7298. proc Table:Write {fileID {fileName {}} {callBack {}}} {
  7299.     global Table_info
  7300.     if {[info exists Table_info($fileID.deferred)]} {
  7301.     return
  7302.     }
  7303.     if {![info exists Table_info($fileID.modified)] && $fileName == {}} {
  7304.     return
  7305.     }
  7306.     if {$callBack == {}} {
  7307.     set callBack $Table_info($fileID.writeCB)
  7308.     }
  7309.     if {$fileName == {}} {
  7310.     set fileName $Table_info($fileID.fileName)
  7311.     set clearModified 1
  7312.     } else {
  7313.     set clearModified 0
  7314.     }
  7315.     #
  7316.     # If the file exists, make sure the new file has the
  7317.     # same owner and perms.  Otherwise, make sure the
  7318.     # parent directory exists.
  7319.     #
  7320.     if {[file exists $fileName]} {
  7321.     file stat $fileName info
  7322.     set Table_info($fileID.uid) $info(uid)
  7323.     set Table_info($fileID.gid) $info(gid)
  7324.     set Table_info($fileID.mode) $info(mode)
  7325.     } else {
  7326.     set directory [file dirname $fileName]
  7327.     set oldUmask [umask]
  7328.     umask 0222
  7329.     if {![file isdirectory $directory]} {
  7330.         mkdir -path $directory
  7331.     }
  7332.     umask $oldUmask
  7333.     }
  7334.     set fp [open ${fileName}.new w]
  7335.     chmod $Table_info($fileID.mode) ${fileName}.new
  7336.     if {[info exists Table_info($fileID.uid)]} {
  7337.     chown [list $Table_info($fileID.uid) $Table_info($fileID.gid)] \
  7338.         ${fileName}.new
  7339.     }
  7340.     foreach line [ConfigFile:GetList $fileID] {
  7341.     if {[ConfigFile:GetLine $fileID $line type id data] != 0} {
  7342.         continue
  7343.     }
  7344.     eval "$callBack $fileID $fp {$type} {$id} {$data}"
  7345.     }
  7346.     close $fp
  7347.     if {[file exists $fileName]} {
  7348.     unlink $fileName
  7349.     }
  7350.     frename ${fileName}.new $fileName
  7351.     if {$clearModified} {
  7352.     unset Table_info($fileID.modified)
  7353.     }
  7354. }
  7355. proc Table:Open {fileName readCB writeCB {mode 0666}} {
  7356.     global Table_info
  7357.     set fileID [Table:Read $fileName $readCB $mode]
  7358.     set Table_info($fileID.fileName) $fileName
  7359.     set Table_info($fileID.readCB) $readCB
  7360.     set Table_info($fileID.writeCB) $writeCB
  7361.     set Table_info($fileName.ID) $fileID
  7362.     return $fileID
  7363. }
  7364. proc Table:Close {fileID {fileName {}}} {
  7365.     global Table_info
  7366.     if {![info exists Table_info($fileID.fileName)]} {
  7367.     return
  7368.     }
  7369.     if {[info exists Table_info($fileID.deferred)]} {
  7370.     unset Table_info($fileID.deferred)
  7371.     }
  7372.     Table:Write $fileID $fileName $Table_info($fileID.writeCB)
  7373.     if {$fileName == {}} {
  7374.     set fileName $Table_info($fileID.fileName)
  7375.     }
  7376.     unset Table_info($fileID.fileName)
  7377.     unset Table_info($fileName.ID)
  7378.     ConfigFile:Close $fileID
  7379. }
  7380. proc Table:CloseNoWrite {fileID {fileName {}}} {
  7381.     global Table_info
  7382.     if {![info exists Table_info($fileID.fileName)]} {
  7383.     return
  7384.     }
  7385.     if {[info exists Table_info($fileID.deferred)]} {
  7386.     unset Table_info($fileID.deferred)
  7387.     }
  7388.     if {$fileName == {}} {
  7389.     set fileName $Table_info($fileID.fileName)
  7390.     }
  7391.     unset Table_info($fileID.fileName)
  7392.     unset Table_info($fileName.ID)
  7393.     ConfigFile:Close $fileID
  7394. }
  7395. proc Table:DeferWrites {fileID} {
  7396.     global Table_info
  7397.     set Table_info($fileID.deferred) 1
  7398. }
  7399. proc Table:ForceWrites {fileID} {
  7400.     global Table_info
  7401.     if {[info exists Table_info($fileID.deferred)]} {
  7402.     unset Table_info($fileID.deferred)
  7403.     }
  7404.     set Table_info($fileID.modified) 1
  7405. proc Table:SetOption {fileID option {value 1}} {
  7406.     global Table_options
  7407.     set Table_options($fileID.$option) $value
  7408. }
  7409. proc Table:HasOption {fileID option} {
  7410.     return [info exists Table_options($fileID.$option)]
  7411. }
  7412. proc Table:GetOption {fileID option} {
  7413.     global Table_options
  7414.     if {![info exists Table_options($fileID.$option)]} {
  7415.     return {}
  7416.     }
  7417.     return $Table_options($fileID.$option)
  7418. }
  7419. proc Table:Modified {fileID} {
  7420.     global Table_info
  7421.     if {[info exists Table_info($fileID.modified)]} {
  7422.     return $Table_info($fileID.modified)
  7423.     } else {
  7424.     return 0
  7425.     }
  7426. }
  7427. proc Table:GetLineList {fileID type {idList {}}} {
  7428.     upvar #0 Table_${fileID}_$type typeList
  7429.     if {![info exists typeList]} {
  7430.     return {}
  7431.     }
  7432.     if {$idList == {}} {
  7433.     set idList [array names typeList]
  7434.     }
  7435.     set lineList {}
  7436.     foreach id $idList {
  7437.     if {[info exists typeList($id)]} {
  7438.         append lineList " $typeList($id)"
  7439.     }
  7440.     }
  7441.     return [lsort -command ConfigFile:Compare $lineList]
  7442. }
  7443. proc Table:Get {fileID type id {separator {}}} {
  7444.     upvar #0 Table_${fileID}_$type typeList
  7445.     if {[Table:GetOption $fileID makelower] != {}} {
  7446.     set id [string tolower $id]
  7447.     }
  7448.     set value {}
  7449.     if {![info exists typeList($id)]} {
  7450.     return $value
  7451.     }
  7452.     set numLines [llength [Table:GetLineList $fileID $type $id]]
  7453.     set thisLine 1
  7454.     foreach line $typeList($id) {
  7455.     ConfigFile:GetLine $fileID $line dummy dummy data
  7456.     if {$thisLine == $numLines} {
  7457.         append value "$data"
  7458.     } else {
  7459.         set data [string trim $data "$separator"]
  7460.         append value "$data$separator"
  7461.     }
  7462.     incr thisLine
  7463.     }
  7464.     set value [string trimleft $value $separator]
  7465.     return $value
  7466. }
  7467. proc Table:Set {fileID type id data} {
  7468.     upvar #0 Table_${fileID}_${type} typeList
  7469.     global Table_info
  7470.     global Table_lastType Table_lastID
  7471.     set name $id
  7472.     if {[Table:GetOption $fileID makelower] != {}} {
  7473.     set id [string tolower $id]
  7474.     }
  7475.     if {[info exists typeList($id)]} {
  7476.     foreach line $typeList($id) {
  7477.         ConfigFile:RemoveLine $fileID $line
  7478.     }
  7479.     set line [lindex $typeList($id) 0]
  7480.     unset typeList($id)
  7481.     } else {
  7482.     if {[set lineList [Table:GetLineList $fileID $type]] != {}} {
  7483.         set line [lindex $lineList end]
  7484.     } else {
  7485.         if {[Table:GetOption $fileID newFirst] == 1} {
  7486.         set line 0
  7487.         } else {
  7488.         set line -1
  7489.         }
  7490.     }
  7491.     }
  7492.     lappend typeList($id) [ConfigFile:AppendLine $fileID $line \
  7493.     $type $name data]
  7494.     set Table_lastType $type
  7495.     set Table_lastID $id
  7496.     set Table_info($fileID.modified) 1
  7497. }
  7498. proc Table:Unset {fileID type id} {
  7499.     upvar #0 Table_${fileID}_$type typeList
  7500.     global Table_info
  7501.     if {[Table:GetOption $fileID makelower] != {}} {
  7502.     set id [string tolower $id]
  7503.     }
  7504.     if {![info exists typeList($id)]} {
  7505.     return
  7506.     }
  7507.     foreach line $typeList($id) {
  7508.     ConfigFile:RemoveLine $fileID $line
  7509.     }
  7510.     unset typeList($id)
  7511.     set Table_info($fileID.modified) 1
  7512. }
  7513. proc Table:AppendLine {fileID type id value {line {}}} {
  7514.     global Table_lastType Table_lastID
  7515.     global Table_info
  7516.     if {$type == "CONTINUATION"} {
  7517.     upvar #0 Table_${fileID}_$Table_lastType typeList
  7518.     } else {
  7519.     upvar #0 Table_${fileID}_$type typeList
  7520.     }
  7521.     if {[Table:GetOption $fileID makelower] != {}} {
  7522.     set id [string tolower $id]
  7523.     }
  7524.     if {$line == ""} {
  7525.     if {[info exists typeList($id)]} {
  7526.         set line [lindex $typeList($id) end]
  7527.     } else {
  7528.         if {[set lineList [Table:GetLineList $fileID $type]] == {}} {
  7529.         set line [lindex $lineList end]
  7530.         } else {
  7531.         if {[Table:GetOption $fileID newFirst] == 1} {
  7532.             set line 0
  7533.         } else {
  7534.             set line -1
  7535.         }
  7536.         }
  7537.     }
  7538.     }
  7539.     if {$type == "CONTINUATION"} {
  7540.     lappend typeList($id) \
  7541.         [ConfigFile:AppendLine $fileID $line $type {} value]
  7542.     } else {
  7543.     lappend typeList($id) \
  7544.         [ConfigFile:AppendLine $fileID $line $type $id value]
  7545.     }
  7546.     set Table_info($fileID.modified) 1
  7547. }
  7548. proc Table:RemoveLine {fileID type id deleteLine} {
  7549.     upvar #0 Table_${fileID}_$type typeList
  7550.     global Table_info
  7551.     if {[Table:GetOption $fileID makelower] != {}} {
  7552.     set id [string tolower $id]
  7553.     }
  7554.     if {![info exists typeList($id)]} {
  7555.     return
  7556.     }
  7557.     set index 0
  7558.     foreach line $typeList($id) {
  7559.     if {$line == $deleteLine} {
  7560.         lvarpop typeList($id) $index
  7561.         ConfigFile:RemoveLine $fileID $line
  7562.         break
  7563.     }
  7564.     incr index
  7565.     }
  7566.     set Table_info($fileID.modified) 1
  7567. }
  7568. proc Table:ReplaceLine {fileID type replaceLine id data} {
  7569.     global Table_info
  7570.     upvar #0 Table_${fileID}_$type typeList
  7571.     if {[ConfigFile:GetLine $fileID $replaceLine oldType oldId oldData] == 0} {
  7572.     if {$oldId != ""} {
  7573.             upvar #0 Table_${fileID}_$oldType oldTypeList
  7574.         set index [lsearch -exact $oldTypeList($oldId) $replaceLine]
  7575.         if {$index != -1} {
  7576.         lvarpop oldTypeList($oldId) $index
  7577.         if {[lempty $oldTypeList($oldId)]} {
  7578.             unset oldTypeList($oldId)
  7579.         }
  7580.         }
  7581.     }
  7582.     }
  7583.     ConfigFile:ReplaceLine $fileID $replaceLine $type $id data
  7584.     if {$id != ""} {
  7585.     if {![info exists typeList($id)]} {
  7586.         set typeList($id) {}
  7587.     }
  7588.     lappend typeList($id) $replaceLine
  7589.     }
  7590.     set Table_info($fileID.modified) 1
  7591. }
  7592. proc Table:List {fileID type {ordered 0}} {
  7593.     upvar #0 Table_${fileID}_$type typeList
  7594.     if {![info exists typeList]} {
  7595.     return {}
  7596.     }
  7597.     if {[Table:GetOption $fileID makelower] == {} && $ordered == 0} {
  7598.     return [array names typeList]
  7599.     }
  7600.     #
  7601.     # We have to go get the original ids from before they were converted 
  7602.     # to lower case, or they want the ids in the order they appear anyway.
  7603.     #
  7604.     set returnList {}
  7605.     foreach line [Table:GetLineList $fileID $type] {
  7606.     ConfigFile:GetLine $fileID $line dummy id dummy
  7607.     append returnList " $id"
  7608.     }
  7609.     return [string trimleft $returnList]
  7610. }
  7611. set versionNumber [SaGetSSOVersion]
  7612. set RESPATH /etc/mail/admin/px
  7613. set PID [pid]
  7614. set ME "/etc/mail/admin/mailadmin"
  7615. set MAILDEF /etc/default/mail
  7616. set MAILDEFTMP /tmp/mail$PID
  7617. set MAILDEFDEF /etc/mail/mail.factory
  7618. set MAILCF /etc/sendmail.cf
  7619. set MAILCFTMP /tmp/sendmail.cf$PID
  7620. set MAILCFDEF /etc/mail/sendmailcf.factory
  7621. set UUCP /usr/lib/uucp/Systems
  7622. set UUCPDB /etc/mail/table/uucp.db
  7623. set MAILTABLE /etc/mail/table
  7624. set MAILALIASES /etc/mail/aliases
  7625. set ALIAS_EDITOR /etc/mail/admin/aliases
  7626. set CTABLE_EDITOR /etc/mail/admin/channel
  7627. set DTABLE_EDITOR /etc/mail/admin/domain
  7628. set MAKEMAP /etc/mail/makemap
  7629. set SENDMAILPID /etc/sendmail.pid
  7630. set SLOCAL /etc/mail/slocal
  7631. set UUX /usr/bin/uux
  7632. set MULTIHOME /etc/mail/multihome
  7633. set MDOMAINDB /var/internet/ip/127.0.0.1/mail/virtdomains
  7634. set MQUEUE /var/spool/mqueue
  7635. set MAILSPOOL /var/mail
  7636. set INBOXNAME .mailbox
  7637. set mag_iconinit 0
  7638. set main_list_length 0
  7639. set RESOLVER /usr/sbin/host
  7640. set mag_host_name [mag_host_local]
  7641. set mag_local_host $mag_host_name
  7642. set MS(class) 0
  7643. set MS(name) 1
  7644. set MS(type) 2
  7645. set MS(level) 3
  7646. set MS(action) 4
  7647. set MS(label) 5
  7648. set MS(value) 6
  7649. set MS(state) 6
  7650. set MS(criteria) 7
  7651. set MS(chname) 8
  7652. set MS(custom) 8
  7653. proc \
  7654. mag_display_item { index } \
  7655. {
  7656.     global main_list mainscreen_db MS
  7657.     set list [lindex $mainscreen_db $index]
  7658.     set class [lindex $list $MS(class)]
  7659.     set name [lindex $list $MS(name)]
  7660.     set type [lindex $list $MS(type)]
  7661.     set level [lindex $list $MS(level)]
  7662.     set action [lindex $list $MS(action)]
  7663.     set label [lindex $list $MS(label)]
  7664.     if {"$class" == "container"} {
  7665.         set container 1
  7666.         set state [lindex $list $MS(state)]
  7667.         if {"$state" == "open"} {
  7668.             set container 2
  7669.         }
  7670.     } else {
  7671.         set container 0
  7672.         set value [lindex $list $MS(value)]
  7673.         if {[llength $list] == 8} {
  7674.             set criteria [lindex $list $MS(criteria)]
  7675.         } else {
  7676.             set criteria ""
  7677.         }
  7678.     }
  7679.     # make iconlist and formatlist
  7680.     #
  7681.     # to do this we need to check at each level if
  7682.     # equal or higher levels of indents occur for each
  7683.     # level we are already at, simulating a parent-child
  7684.     # relationship for each level, only two levels supported here.
  7685.     # any more indent level one children?
  7686.     set more1children 0
  7687.     set length [llength $mainscreen_db]
  7688.     loop j [expr $index + 1] $length {
  7689.         set nextlist [lindex $mainscreen_db $j]
  7690.         set nextlevel [lindex $nextlist $MS(level)]
  7691.         if {$nextlevel == 2} {
  7692.             continue
  7693.         }
  7694.         if {$nextlevel == 0} {
  7695.             break
  7696.         }
  7697.         if {$nextlevel == 1} {
  7698.             set more1children 1
  7699.             break
  7700.         }
  7701.         error "Unknown indent level 1 $nextlevel"
  7702.     }
  7703.     set more2children 0
  7704.     loop j [expr $index + 1] $length {
  7705.         set nextlist [lindex $mainscreen_db $j]
  7706.         set nextlevel [lindex $nextlist $MS(level)]
  7707.         if {$nextlevel == 1} {
  7708.             break
  7709.         }
  7710.         if {$nextlevel == 0} {
  7711.             break
  7712.         }
  7713.         if {$nextlevel == 2} {
  7714.             set more2children 1
  7715.             break
  7716.         }
  7717.         error "Unknown indent level 2 $nextlevel"
  7718.     }
  7719.     # now we index a table of icons to draw using the values
  7720.     # container, level, more1children and more2children.
  7721.     set icons [mag_get_icons $container $level \
  7722.         $more1children $more2children]
  7723.     # now build formatlist and fieldlist
  7724.     set formatlist ""
  7725.     set fieldlist ""
  7726.     foreach j $icons {
  7727.         # all our icons are two chars wide
  7728.         lappend formatlist "ICON 1"
  7729.         lappend fieldlist $j
  7730.     }
  7731.     if {"$class" == "container"} {
  7732.         lappend formatlist "STRING 75"
  7733.         lappend fieldlist $label
  7734.     } else {
  7735.         lappend formatlist "STRING 46"
  7736.         lappend fieldlist $label:
  7737.         set len [clength $value]
  7738.         set len [expr $len + 2]
  7739.         lappend formatlist "STRING $len"
  7740.         lappend fieldlist $value
  7741.     }
  7742.     return [list $fieldlist $formatlist]
  7743. }
  7744. proc \
  7745. mag_display_mainlist { start stop index } \
  7746. {
  7747.     global main_list mainscreen_db MS
  7748.     set length [llength $mainscreen_db]
  7749.     if {$stop == 0} {
  7750.         set stop $length
  7751.     }
  7752.     loop i $start $stop {
  7753.         set list [mag_display_item $i]
  7754.         set fieldlist [lindex $list 0]
  7755.         set formatlist [lindex $list 1]
  7756.         set position [expr $i + 1]
  7757.         VtDrawnListSetItem $main_list \
  7758.             -position $position \
  7759.             -fieldList $fieldlist \
  7760.             -formatList $formatlist
  7761.     }
  7762.     if {$index >= 0} {
  7763.         set select [expr $index + 1]
  7764.         VtDrawnListSelectItem $main_list -position $select
  7765.         mao_select $index
  7766.     }
  7767. }
  7768. proc \
  7769. mag_insert_mainlist { index count } \
  7770. {
  7771.     global main_list
  7772.     loop i 0 $count {
  7773.         set item [expr $index + $i + 1]
  7774.         set list [mag_display_item $item]
  7775.         set fieldlist [lindex $list 0]
  7776.         set formatlist [lindex $list 1]
  7777.         set position [expr $index + $i + 2]
  7778.         VtDrawnListAddItem $main_list -position $position \
  7779.             -fieldList $fieldlist -formatList $formatlist
  7780.     }
  7781. }
  7782. proc \
  7783. mag_delete_mainlist { index count } \
  7784. {
  7785.     global main_list
  7786.     set delete [expr $index + 2]
  7787.     set deletelist ""
  7788.     loop i 0 $count {
  7789.         lappend deletelist [expr $delete + $i]
  7790.     }
  7791.     VtDrawnListDeleteItem $main_list -positionList $deletelist
  7792. }
  7793. proc \
  7794. mag_get_icons { con in c1 c2 } \
  7795. {
  7796.     global mag_iconarray mag_iconinit
  7797.     if {$mag_iconinit == 0} {
  7798.         # last two bits are don't care for these,
  7799.         # but we have to set them all.
  7800.         set mag_iconarray("0000") 0
  7801.         set mag_iconarray("0001") 0
  7802.         set mag_iconarray("0010") 0
  7803.         set mag_iconarray("0011") 0
  7804.         # last bit is don't care for these
  7805.         set mag_iconarray("1000") 1
  7806.         set mag_iconarray("1001") 1
  7807.         set mag_iconarray("2000") 9
  7808.         set mag_iconarray("2001") 9
  7809.         set mag_iconarray("1010") 2
  7810.         set mag_iconarray("1011") 2
  7811.         set mag_iconarray("2010") 10
  7812.         set mag_iconarray("2011") 10
  7813.         set mag_iconarray("0100") [list 5 8]
  7814.         set mag_iconarray("0101") [list 5 8]
  7815.         set mag_iconarray("0110") [list 6 8]
  7816.         set mag_iconarray("0111") [list 6 8]
  7817.         # all bits are significant for the rest
  7818.         # containers
  7819.         set mag_iconarray("1100") [list 5 3]
  7820.         set mag_iconarray("1101") [list 5 4]
  7821.         set mag_iconarray("1110") [list 6 3]
  7822.         set mag_iconarray("1111") [list 6 4]
  7823.         set mag_iconarray("2100") [list 5 11]
  7824.         set mag_iconarray("2101") [list 5 12]
  7825.         set mag_iconarray("2110") [list 6 11]
  7826.         set mag_iconarray("2111") [list 6 12]
  7827.         # simple objects
  7828.         set mag_iconarray("0200") [list 0 5 8]
  7829.         set mag_iconarray("0201") [list 0 6 8]
  7830.         set mag_iconarray("0210") [list 7 5 8]
  7831.         set mag_iconarray("0211") [list 7 6 8]
  7832.         set mag_iconinit 1
  7833.     }
  7834.     set key "$con$in$c1$c2"
  7835.     set icons $mag_iconarray("$key")
  7836.     return $icons
  7837. }
  7838. proc \
  7839. mag_build_widgets { parent } \
  7840. {
  7841.     global RESPATH main_list status_line
  7842.     global btn_mod btn_add btn_del btn_up btn_dn
  7843.     global menu_mod menu_add menu_del menu_up menu_dn
  7844.     global mag_host_name mag_host_label
  7845.     # menubar
  7846.     set menuBar [VtMenuBar $parent.menubar \
  7847.         -helpMenuItemList [SaHelpGetOptionsList]]
  7848.     set hostMenu [VtPulldown $menuBar.hostMenu -label [mag_msg MENU_HOST] \
  7849.         -mnemonic [mag_msg MENU_HOST_MN]]
  7850.     VtPushButton $hostMenu.open -label [mag_msg MENU_OPEN] \
  7851.         -mnemonic [mag_msg MENU_OPEN_MN] \
  7852.         -callback mag_open_host_cb \
  7853.         -shortHelpString [mag_msg SHORT_OPEN] \
  7854.         -shortHelpCallback mag_short_help
  7855.     VtPushButton $hostMenu.exit -label [mag_msg MENU_EXIT] \
  7856.         -mnemonic [mag_msg MENU_EXIT_MN] \
  7857.         -callback "quit_cb 1"\
  7858.         -shortHelpString [mag_msg SHORT_EXIT] \
  7859.         -shortHelpCallback mag_short_help
  7860.     set editMenu [VtPulldown $menuBar.editMenu -label [mag_msg MENU_EDIT] \
  7861.         -mnemonic [mag_msg MENU_EDIT_MN]]
  7862.     set menu_mod [VtPushButton $editMenu.Mod -label [mag_msg MENU_MOD] \
  7863.         -mnemonic [mag_msg MENU_MOD_MN] \
  7864.         -callback mag_modify_cb \
  7865.         -shortHelpString [mag_msg SHORT_MOD] \
  7866.         -shortHelpCallback mag_short_help]
  7867.     VtSeparator $editMenu.sep1
  7868.     set menu_add [VtPushButton $editMenu.Add -label [mag_msg MENU_ADD] \
  7869.         -mnemonic [mag_msg MENU_ADD_MN] \
  7870.         -callback mag_add_cb \
  7871.         -shortHelpString [mag_msg SHORT_ADD] \
  7872.         -shortHelpCallback mag_short_help]
  7873.     set menu_del [VtPushButton $editMenu.del -label [mag_msg MENU_DEL] \
  7874.         -mnemonic [mag_msg MENU_DEL_MN] \
  7875.         -callback mag_delete_cb \
  7876.         -shortHelpString [mag_msg SHORT_DEL] \
  7877.         -shortHelpCallback mag_short_help]
  7878.     VtSeparator $editMenu.sep2
  7879.     set menu_up [VtPushButton $editMenu.up -label [mag_msg MENU_UP] \
  7880.         -mnemonic [mag_msg MENU_UP_MN] \
  7881.         -callback mag_up_cb \
  7882.         -shortHelpString [mag_msg SHORT_UP] \
  7883.         -shortHelpCallback mag_short_help]
  7884.     set menu_dn [VtPushButton $editMenu.dn -label [mag_msg MENU_DN] \
  7885.         -mnemonic [mag_msg MENU_DN_MN] \
  7886.         -callback mag_down_cb \
  7887.         -shortHelpString [mag_msg SHORT_DN] \
  7888.         -shortHelpCallback mag_short_help]
  7889.     set setMenu [VtPulldown $menuBar.setMenu -label [mag_msg MENU_SET] \
  7890.         -mnemonic [mag_msg MENU_SET_MN]]
  7891.     VtPushButton $setMenu.def -label [mag_msg MENU_DEF] \
  7892.         -mnemonic [mag_msg MENU_DEF_MN] \
  7893.         -callback mag_default_cb \
  7894.         -shortHelpString [mag_msg SHORT_DEF] \
  7895.         -shortHelpCallback mag_short_help
  7896.     VtPushButton $setMenu.badhost -label [mag_msg MENU_BADHOST] \
  7897.         -mnemonic [mag_msg MENU_BADHOST_MN] \
  7898.         -callback mag_badhost_cb \
  7899.         -shortHelpString [mag_msg SHORT_BADHOST] \
  7900.         -shortHelpCallback mag_short_help
  7901.     VtPushButton $setMenu.baduser -label [mag_msg MENU_BADUSER] \
  7902.         -mnemonic [mag_msg MENU_BADUSER_MN] \
  7903.         -callback mag_baduser_cb \
  7904.         -shortHelpString [mag_msg SHORT_BADUSER] \
  7905.         -shortHelpCallback mag_short_help
  7906.     VtPushButton $setMenu.uucp -label [mag_msg MENU_UUCP] \
  7907.         -mnemonic [mag_msg MENU_UUCP_MN] \
  7908.         -callback mag_uucp_cb \
  7909.         -shortHelpString [mag_msg SHORT_UUCP] \
  7910.         -shortHelpCallback mag_short_help
  7911.     VtPushButton $setMenu.mhome -label [mag_msg MENU_MHOME] \
  7912.         -mnemonic [mag_msg MENU_MHOME_MN] \
  7913.         -callback mag_mhome_cb \
  7914.         -shortHelpString [mag_msg SHORT_MHOME] \
  7915.         -shortHelpCallback mag_short_help
  7916.     # toolbar widget
  7917.     if {[VtInfo -charm] == 0} {
  7918.         set frameBar [VtFrame $parent.framebar \
  7919.             -topSide $menuBar \
  7920.             -topOffset 1 \
  7921.             -leftSide FORM \
  7922.             -leftOffset 2 \
  7923.             -rightSide FORM \
  7924.             -rightOffset 2 \
  7925.             -marginWidth 0 \
  7926.             -marginHeight 0 \
  7927.             -horizontalSpacing 0 \
  7928.             -verticalSpacing 0 \
  7929.             -shadowType IN \
  7930.         ]
  7931.         set toolBar [VtForm $frameBar.toolbar \
  7932.             -leftSide FORM \
  7933.             -rightSide FORM \
  7934.             -borderWidth 0 \
  7935.             -marginHeight 0 \
  7936.             -marginWidth 0 \
  7937.             -horizontalSpacing 0 \
  7938.             -verticalSpacing 0 \
  7939.         ]
  7940.         set btn_mod [VtPushButton $toolBar.mod \
  7941.             -label [mag_msg MENU_MOD] \
  7942.             -leftSide FORM \
  7943.             -topSide FORM \
  7944.             -bottomSide FORM \
  7945.             -callback mag_modify_cb \
  7946.             -shortHelpString [mag_msg SHORT_MOD] \
  7947.             -shortHelpCallback mag_short_help \
  7948.         ]
  7949.         set tmp1 [VtLabel $toolBar.sep1 \
  7950.             -label "  " \
  7951.             -leftSide $btn_mod \
  7952.             -topSide FORM \
  7953.         ]
  7954.         set btn_add [VtPushButton $toolBar.add \
  7955.             -label [mag_msg MENU_ADD] \
  7956.             -leftSide $tmp1 \
  7957.             -topSide FORM \
  7958.             -bottomSide FORM \
  7959.             -callback mag_add_cb \
  7960.             -shortHelpString [mag_msg SHORT_ADD] \
  7961.             -shortHelpCallback mag_short_help \
  7962.         ]
  7963.         set btn_del [VtPushButton $toolBar.del \
  7964.             -label [mag_msg MENU_DEL] \
  7965.             -leftSide $btn_add \
  7966.             -topSide FORM \
  7967.             -bottomSide FORM \
  7968.             -callback mag_delete_cb \
  7969.             -shortHelpString [mag_msg SHORT_DEL] \
  7970.             -shortHelpCallback mag_short_help \
  7971.         ]
  7972.         set tmp2 [VtLabel $toolBar.sep2 \
  7973.             -label "  " \
  7974.             -leftSide $btn_del \
  7975.             -topSide FORM \
  7976.         ]
  7977.         set btn_up [VtPushButton $toolBar.up -pixmap $RESPATH/prev.px \
  7978.             -callback mag_up_cb \
  7979.             -leftSide $tmp2 \
  7980.             -topSide FORM \
  7981.             -shortHelpString [mag_msg SHORT_UP] \
  7982.             -shortHelpCallback mag_short_help \
  7983.         ]
  7984.         set btn_dn [VtPushButton $toolBar.dn -pixmap $RESPATH/next.px \
  7985.             -callback mag_down_cb \
  7986.             -leftSide $btn_up \
  7987.             -topSide FORM \
  7988.             -rightSide NONE \
  7989.             -shortHelpString [mag_msg SHORT_DN] \
  7990.             -shortHelpCallback mag_short_help \
  7991.         ]
  7992.     }
  7993.     # Top status line
  7994.     set mag_host_label [VtLabel $parent.toplab \
  7995.         -leftSide FORM -rightSide FORM \
  7996.         -label [mag_msg1 TITLE $mag_host_name] \
  7997.     ]
  7998.     # list widget
  7999.     set main_list [VtDrawnList $parent.list -columns 78 -rows 16 \
  8000.         -autoSelect TRUE -selection BROWSE \
  8001.         -callback mag_select_cb \
  8002.         -defaultCallback mag_activate_cb \
  8003.         -leftSide FORM -rightSide FORM \
  8004.         -horizontalScrollBar 1 \
  8005.         -iconList [list \
  8006.             $RESPATH/blank.px \
  8007.             $RESPATH/folder_alone.px \
  8008.             $RESPATH/folder_has.px \
  8009.             $RESPATH/folder_next_alone.px \
  8010.             $RESPATH/folder_next_has.px \
  8011.             $RESPATH/item_last.px \
  8012.             $RESPATH/item_middle.px \
  8013.             $RESPATH/vbar.px \
  8014.             $RESPATH/hbar.px \
  8015.             $RESPATH/folder_open_alone.px \
  8016.             $RESPATH/folder_open_has.px \
  8017.             $RESPATH/folder_open_next_alone.px \
  8018.             $RESPATH/folder_open_next_has.px \
  8019.         ]]
  8020.     # status line
  8021.     set status_line [SaStatusBar $parent.status 1]
  8022.     SaStatusBarSet $status_line [mag_msg LOADING]
  8023.     VtSetValues $main_list -bottomSide $status_line
  8024. }
  8025. proc \
  8026. mag_open_host_cb { cbs } \
  8027. {
  8028.     VtLock
  8029.     mag_open_host
  8030.     VtUnLock
  8031. }
  8032. proc \
  8033. mag_select_cb { cbs } \
  8034. {
  8035.     VtLock
  8036.     set index [keylget cbs itemPosition]
  8037.     set index [expr $index - 1]
  8038.     mao_select $index
  8039.     VtUnLock
  8040. }
  8041. proc \
  8042. mag_activate_cb { cbs } \
  8043. {
  8044.     VtLock
  8045.     set index [keylget cbs itemPosition]
  8046.     set index [expr $index - 1]
  8047.     mao_activate $index
  8048.     VtUnLock
  8049. }
  8050. proc \
  8051. mag_default_cb { cbs } \
  8052. {
  8053.     global main_list
  8054.     VtLock
  8055.     set index [VtDrawnListGetSelectedItem $main_list]
  8056.     set index [expr $index - 1]
  8057.     mao_default $index yes
  8058.     VtUnLock
  8059. }
  8060. proc \
  8061. mag_modify_cb { cbs } \
  8062. {
  8063.     global main_list
  8064.     VtLock
  8065.     set index [VtDrawnListGetSelectedItem $main_list]
  8066.     set index [expr $index - 1]
  8067.     mao_activate $index
  8068.     VtUnLock
  8069. }
  8070. proc \
  8071. mag_add_cb { cbs } \
  8072. {
  8073.     global main_list
  8074.     VtLock
  8075.     set index [VtDrawnListGetSelectedItem $main_list]
  8076.     set index [expr $index - 1]
  8077.     mao_add $index
  8078.     VtUnLock
  8079. }
  8080. proc \
  8081. mag_delete_cb { cbs } \
  8082. {
  8083.     global main_list
  8084.     VtLock
  8085.     set index [VtDrawnListGetSelectedItem $main_list]
  8086.     set index [expr $index - 1]
  8087.     mao_delete $index
  8088.     VtUnLock
  8089. }
  8090. proc \
  8091. mag_up_cb { cbs } \
  8092. {
  8093.     global main_list
  8094.     VtLock
  8095.     set index [VtDrawnListGetSelectedItem $main_list]
  8096.     set index [expr $index - 1]
  8097.     mao_move $index up
  8098.     VtUnLock
  8099. }
  8100. proc \
  8101. mag_down_cb { cbs } \
  8102. {
  8103.     global main_list
  8104.     VtLock
  8105.     set index [VtDrawnListGetSelectedItem $main_list]
  8106.     set index [expr $index - 1]
  8107.     mao_move $index down
  8108.     VtUnLock
  8109. }
  8110. proc \
  8111. mag_badhost_cb { cbs } \
  8112. {
  8113.     VtLock
  8114.     mao_badhost
  8115.     VtUnLock
  8116. }
  8117. proc \
  8118. mag_baduser_cb { cbs } \
  8119. {
  8120.     VtLock
  8121.     mao_baduser
  8122.     VtUnLock
  8123. }
  8124. proc \
  8125. mag_uucp_cb { cbs } \
  8126. {
  8127.     VtLock
  8128.     mao_uucp
  8129.     VtUnLock
  8130. }
  8131. proc \
  8132. mag_mhome_cb { cbs } \
  8133. {
  8134.     VtLock
  8135.     mao_mhome
  8136.     VtUnLock
  8137. }
  8138. proc \
  8139. mag_short_help { cbs } \
  8140. {
  8141.     global status_line
  8142.     set helpstring [keylget cbs helpString]
  8143.     SaStatusBarSet $status_line $helpstring
  8144. }
  8145. proc \
  8146. mag_cf_get {} \
  8147. {
  8148.     global MAILCF MAILCFTMP MAILCFDEF DIRTY
  8149.     system "rm -fr $MAILCFTMP"
  8150.     set ret [mag_remote_copyin $MAILCF $MAILCFTMP]
  8151.     if {$ret != "ok"} {
  8152.         VtUnLock
  8153.         set ret [mag_query_eyn CF_COPY_OUT $MAILCF]
  8154.         VtLock
  8155.         if {$ret == "no"} {
  8156.             return no
  8157.         }
  8158.         # restore factory file
  8159.         VtUnLock
  8160.         set ret [mag_local_copy $MAILCFDEF $MAILCFTMP]
  8161.         VtLock
  8162.         if {$ret != "ok"} {
  8163.             VtUnLock
  8164.             mag_error1 CF_FACTORY_RESTORE $MAILCF
  8165.             VtLock
  8166.             return fail
  8167.         }
  8168.         set DIRTY 1
  8169.     } else {
  8170.         # validate old file
  8171.         if {[ma_cf_valid $MAILCFTMP] == "fail"} {
  8172.             # invalid old file
  8173.             VtUnLock
  8174.             set ret [mag_query_eyn CF_INVALID $MAILCF]
  8175.             VtLock
  8176.             if {$ret == "no"} {
  8177.                 return no
  8178.             }
  8179.         }
  8180.     }
  8181.     # ready to attempt open.
  8182.     set ret start
  8183.     while {"$ret" != "ok"} {
  8184.         set ret [ma_cf_open $MAILCFTMP]
  8185.         switch $ret {
  8186.         "ok"    {
  8187.         }
  8188.         "fail"    {
  8189.             VtUnLock
  8190.             mag_error1 CF_OPEN_FAIL $MAILCFTMP
  8191.             VtLock
  8192.             return fail
  8193.         }
  8194.         "parserr" {
  8195.             VtUnLock
  8196.             set ret [mag_query_eyn CF_PARSE $MAILCF]
  8197.             VtLock
  8198.             if {$ret == "no"} {
  8199.                 return no
  8200.             }
  8201.             # restore factory file
  8202.             set ret [mag_local_copy $MAILCFDEF $MAILCFTMP]
  8203.             if {$ret != "ok"} {
  8204.                 VtUnLock
  8205.                 mag_error1 CF_FACTORY_RESTORE $MAILCF
  8206.                 VtLock
  8207.                 return fail
  8208.             }
  8209.             set ret retry
  8210.             set DIRTY 1
  8211.         }
  8212.         }
  8213.     }
  8214.     return ok
  8215. }
  8216. proc \
  8217. mag_ms1_get {} \
  8218. {
  8219.     global MAILDEF MAILDEFTMP MAILDEFDEF DIRTY
  8220.     system "rm -fr $MAILDEFTMP"
  8221.     set ret [mag_remote_copyin $MAILDEF $MAILDEFTMP]
  8222.     if {$ret != "ok"} {
  8223.         VtUnLock
  8224.         set ret [mag_query_eyn CF_COPY_OUT $MAILDEF]
  8225.         VtLock
  8226.         if {$ret == "no"} {
  8227.             return no
  8228.         }
  8229.         # restore factory file
  8230.         set ret [mag_local_copy $MAILDEFDEF $MAILDEFTMP]
  8231.         if {$ret != "ok"} {
  8232.             VtUnLock
  8233.             mag_error1 CF_FACTORY_RESTORE $MAILDEF
  8234.             VtLock
  8235.             return fail
  8236.         }
  8237.         set DIRTY 1
  8238.     }
  8239.     # ready to attempt open.
  8240.     set ret start
  8241.     while {"$ret" != "ok"} {
  8242.         set ret [ma_ms1_open $MAILDEFTMP]
  8243.         switch $ret {
  8244.         "ok"     {
  8245.         }
  8246.         "fail"    {
  8247.             VtUnLock
  8248.             mag_error1 CF_OPEN_FAIL $MAILDEFTMP
  8249.             VtLock
  8250.             return fail
  8251.         }
  8252.         "parserr" {
  8253.             VtUnLock
  8254.             set ret [mag_query_eyn MS1_PARSE $MAILDEF]
  8255.             VtLock
  8256.             if {$ret == "yes"} {
  8257.                 # restore factory file
  8258.                 set ret [mag_local_copy $MAILDEFDEF $MAILDEFTMP]
  8259.                 if {$ret != "ok"} {
  8260.                     VtUnLock
  8261.                     mag_error1 CF_FACTORY_RESTORE $MAILDEF
  8262.                     VtLock
  8263.                     return fail
  8264.                 }
  8265.                 # to re-load the new MAILDEFTMP
  8266.                 set ret "parserr"
  8267.             } else {
  8268.                 set ret "ok"
  8269.             }
  8270.             set DIRTY 1
  8271.         }
  8272.         }
  8273.     }
  8274.     return ok
  8275. }
  8276. proc \
  8277. mag_all_put {} \
  8278. {
  8279.     global app DIRTY
  8280.     global MAILCF MAILCFTMP MAILDEF MAILDEFTMP
  8281.     set saved 0
  8282.     if {$DIRTY == 1} {
  8283.         VtUnLock
  8284.         set ret [mag_query_qync DIRTY notused]
  8285.         VtLock
  8286.         if {"$ret" == "cancel"} {
  8287.             return cancel
  8288.         }
  8289.         if {"$ret" == "yes"} {
  8290.             set ret [ma_cf_write]
  8291.             if {"$ret" != "ok"} {
  8292.                 VtUnLock
  8293.                 mag_query_eok CF_WRITE $MAILCFTMP
  8294.                 VtLock
  8295.                 return fail
  8296.             }
  8297.             set ret [mag_remote_copyout $MAILCFTMP $MAILCF]
  8298.             if {"$ret" != "ok"} {
  8299.                 VtUnLock
  8300.                 mag_query_eok COPY_BACK $MAILCF
  8301.                 VtLock
  8302.                 return fail
  8303.             }
  8304.             set ret [ma_ms1_write]
  8305.             if {"$ret" != "ok"} {
  8306.                 VtUnLock
  8307.                 mag_query_eok CF_WRITE $MAILDEFTMP
  8308.                 VtLock
  8309.                 return fail
  8310.             }
  8311.             set ret [mag_remote_copyout $MAILDEFTMP $MAILDEF]
  8312.             if {"$ret" != "ok"} {
  8313.                 VtUnLock
  8314.                 mag_query_eok COPY_BACK $MAILDEF
  8315.                 VtLock
  8316.                 return fail
  8317.             }
  8318.             set saved 1
  8319.         }
  8320.         set DIRTY 0
  8321.     }
  8322.     mag_rebuild_uucp_map yes
  8323.     if {"$saved" == 1} {
  8324.         mag_restart_sendmail yes
  8325.     }
  8326.     return ok
  8327. }
  8328. proc \
  8329. mag_remoteCommand {host cmd args errMsgId} \
  8330. {
  8331.         set class    [list sco remoteCommand]
  8332.         set instance [GetInstanceList NULL $host]
  8333.         set command [list ObjectAction $class $instance $cmd $args]
  8334.         set result [SaMakeObjectCall $command]
  8335.         set result [lindex $result 0]
  8336.         if { [BmipResponseErrorIsPresent result] } {
  8337.         set errorStack [BmipResponseErrorStack result]
  8338.         set topErrorCode [lindex [lindex $errorStack 0] 0]
  8339.         if { $topErrorCode != "SCO_SA_ERRHANDLER_ERR_CONNECT_FAIL" } {
  8340.             ErrorPush errorStack 1 $errMsgId
  8341.             return {}
  8342.         } else {
  8343.             ErrorThrow errorStack
  8344.             return
  8345.         }
  8346.     }
  8347.     set retVal [BmipResponseActionInfo result]
  8348.     return $retVal
  8349. }
  8350. proc \
  8351. mag_authorized {host} \
  8352. {
  8353.     set uid [id effective userid]
  8354.     if {$uid != 0} {
  8355.         set cmd "/sbin/tfadmin"
  8356.         set args1 "-t mailadmin"
  8357.         set args2 "-t cpfile"
  8358.         set args3 "-t kill"
  8359.         if {[ErrorCatch errStack 0 {mag_remoteCommand $host \
  8360.             $cmd $args1 SCO_MAIL_ADMIN_ERR_TFADMIN} ret1] || \
  8361.             [ErrorCatch errStack 0 {mag_remoteCommand $host \
  8362.             $cmd $args2 SCO_MAIL_ADMIN_ERR_TFADMIN} ret2] || \
  8363.             [ErrorCatch errStack 0 {mag_remoteCommand $host \
  8364.             $cmd $args3 SCO_MAIL_ADMIN_ERR_TFADMIN} ret3]} {
  8365.             return fail
  8366.         }
  8367.     }
  8368.     return ok
  8369. }
  8370. proc \
  8371. quit_cb { {save {}} cbs  } \
  8372. {
  8373.     global status_line
  8374.     set ret "ok"
  8375.     # save everything
  8376.     if {"$save" == "" || $save == 1} {
  8377.         VtLock
  8378.         SaStatusBarSet $status_line [mag_msg SAVING]
  8379.         set ret [mag_all_put]
  8380.         VtUnLock
  8381.     }
  8382.     switch $ret {
  8383.     "ok" {
  8384.         quit
  8385.     }
  8386.     "fail" {
  8387.         return
  8388.     }
  8389.     "cancel" {
  8390.         return
  8391.     }
  8392.     }
  8393.     error "unknown quit"
  8394. }
  8395. proc \
  8396. quit {} \
  8397. {
  8398.     VtClose
  8399.     cleanup
  8400.     exit 0
  8401. }
  8402. proc \
  8403. cleanup {} \
  8404. {
  8405.     global MAILDEFTMP MAILCFTMP
  8406.     system "rm -fr $MAILDEFTMP $MAILCFTMP"
  8407. }
  8408. proc \
  8409. main {} \
  8410. {
  8411.     global app DIRTY status_line main_list outerMainForm mainscreen_db
  8412.     global mag_host_name versionNumber
  8413.     # if command line mode, this routine does not return
  8414.     mag_cmd_line_main
  8415.     mag_setcat SCO_MAIL_ADMIN
  8416.     set app [VtOpen mailadmin [mag_msg HELPBOOK]]
  8417.     set versionString [mag_msg APP_TITLE]
  8418.     set versionString "$versionString $versionNumber"
  8419.     VtSetAppValues $app -versionString $versionString
  8420.     set outerMainForm [ \
  8421.         VtFormDialog $app.main \
  8422.         -resizable FALSE \
  8423.         -wmCloseCallback "quit_cb 1"\
  8424.         -title [mag_msg1 WIN_TITLE [mag_short_name_default]] \
  8425.         ]
  8426.     mag_build_widgets $outerMainForm
  8427.     VtShow $outerMainForm
  8428.     VtLock
  8429.     # form is visible and we are locked, now init stuff
  8430.     set DIRTY 0
  8431.         # check if host if ok
  8432.         if {"[mag_host_check $mag_host_name]" != "ok"} {
  8433.                 VtUnLock
  8434.                 mag_error1 BADHOST $mag_host_name
  8435.                 quit
  8436.         }
  8437.     # check if authorized
  8438.     if {"[mag_authorized $mag_host_name]" == "fail"} {
  8439.         SaDisplayNoAuths $outerMainForm.noAuths [mag_msg APP_TITLE] \
  8440.             "quit_cb 0" [mag_short_name_default]
  8441.         VtUnLock
  8442.         VtMainLoop
  8443.         return
  8444.     }        
  8445.     # get sendmail.cf either current one or new factory default one
  8446.     if {"[mag_cf_get]" != "ok"} {
  8447.         quit
  8448.     }
  8449.     # get /etc/default/mail either current or new one.
  8450.     if {"[mag_ms1_get]" != "ok"} {
  8451.         quit
  8452.     }
  8453.     # build onscreen db
  8454.     mao_init
  8455.     mag_insert_mainlist -1 [llength $mainscreen_db]
  8456.     mag_display_mainlist 0 1 0
  8457.     VtUnLock
  8458.     SaStatusBarClear $status_line
  8459.     VtMainLoop
  8460. }
  8461. ErrorTopLevelCatch {
  8462. if {"[lindex $argv 0]" == "-h"} {
  8463.     lvarpop argv
  8464.     set mag_host_name [lvarpop argv]
  8465.     if {"$mag_host_name" == ""} {
  8466.         echo "mailadmin: No host name"
  8467.         exit 1
  8468.     }
  8469. }
  8470. if {[lindex $argv 0] == "-mag_stand_edit"} {
  8471.     mag_stand_edit [lindex $argv 1] [lindex $argv 2]
  8472.     exit
  8473. }
  8474. if {[lindex $argv 0] == "-mag_stand_channel"} {
  8475.     mag_stand_channel [lindex $argv 1] [lindex $argv 2]
  8476.     exit
  8477. }
  8478. if {[lindex $argv 0] == "-mag_stand_host"} {
  8479.     mag_stand_host [lindex $argv 1]
  8480.     exit
  8481. }
  8482. main} "mailadmin"
  8483.