Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

690 lines
25 KiB

  1. @rem = '
  2. @goto endofperl
  3. ';
  4. $USAGE = "
  5. Usage: $0 InputFiles
  6. ########### ADD $retrysleep $retrycount
  7. ###########
  8. MKDSX makes NTDS-Connection objects. An input file specifies where the
  9. connection is to be created, updated or deleted. Create and update commands
  10. take additional parameters specifying whether the connection is enabled and
  11. a schedule parameter. Since connection names are often GUIDs a specific
  12. connection among a list of alternate connections is located by the value of
  13. the connection's From-Sever attribute.
  14. MKDSX Parameters set via enviroment vars.
  15. MKDSX_REDO_FILE Output file of failed mkdsx commands (default: MKDSX.REDO)
  16. MKDSX_DCNAME computer name of DC to bind to.
  17. Input command file entries consist of one record per connection operation.
  18. The following commands are supported.
  19. Host Server From Server Enabled Schedule option
  20. create site\\server site\\server on|off s-ii-cc-pp [/dc dcname] # comment
  21. update site\\server site\\server on|off s-ii-cc-pp [/dc dcname] # comment
  22. del site\\server site\\server|* [/dc dcname] # comment
  23. dump site\\server site\\server|* [/dc dcname] # comment
  24. /dc <default computer name of DC on which to create the connection objects>
  25. /auto_cleanup [DCname1 DCname2 ...]
  26. /debug processes the file but prevents mkdsxe.exe from actually modifying the DC.
  27. /verbose enables verbose output.
  28. /schedmask <file with 7x24 string of ascii hex digit pairs to turn off the schedule>
  29. /schedoverride <file with 7x24 string of ascii hex digit pairs to turn on the schedule>
  30. No embedded blanks are allowed within parameters.
  31. The /dc option can be used in two ways:
  32. 1. On a command line by itself to specify the global default DC on which
  33. to create/update the connection object for subsequent connection operation
  34. commands. The default can be changed multiple times in the input file.
  35. 2. The /dc option can also be used at the end of the create, update, del
  36. and dump commands to override the current global default for this
  37. single command. This is useful if you need to create a connection object
  38. on a remote DC that currently has no connection objects and so is not
  39. replicating but the global default is sufficient for all the other commands.
  40. The /auto_cleanup option is used to automatically delete ALL old connections
  41. under a given host site\\server before the first new connection is created.
  42. This is done only once before the first create operation on the host is processed.
  43. If the first operation on a given host is an update command then it is assumed
  44. that no cleanup should be done on this host. The del and dump commands do not
  45. trigger an auto cleanup. The actual delete connection operation is performed on the
  46. DC specified by the /dc option described above. In addition the /auto_cleanup
  47. option can take an optional list of DC computer names separated by spaces.
  48. If supplied, the automatic connection delete operation is ALSO performed on EACH
  49. of these DCs. This is useful if you are creating new inbound connection
  50. objects on branch DCs and want to be sure that any old inbound connection
  51. objects are deleted on the branch DC AND on the Hub DCs. Otherwise if the
  52. branch has not replicated in some time there could be undesired connection
  53. objects lingering on the Hub DC that will replicate to the branch once the new
  54. connection object is created. You can prevent this by specifying a list of Hub
  55. DC names as parameters to the /auto_cleanup option.
  56. Create: Create a connection under the host server in the specified site.
  57. The DN for the From-Server attribute is built using the specified site
  58. and server name. The Enabled-Connection attribute is set based on the
  59. on|off parameter. The Schedule attribute is constructed using the
  60. schedule paramter. Create behaves like update if the specified connection
  61. already exists.
  62. Update: Update a connection under the host server in the specified site.
  63. Parameters are the same as for create. The specific connection is found
  64. by searching for a connection under the host site\\server with a matching
  65. From-Server attribute. Update returns an error if the specified connection
  66. is not found.
  67. Update reads the schedule and enabled attributes and performs the
  68. update only if there is a change. This means that the same connection
  69. data file can be run repeatedly trying to create connections and only
  70. perform creates or updates as needed.
  71. Del : Delete the connection under the host server in the specified site.
  72. The specific connection is found as described in the update command.
  73. If there are duplicate connection objects with the same From Server
  74. attribute then all are deleted.
  75. In addition, if '*' is specified for the From Server parameter then
  76. all NTDS-Connection objects under the host site\\server are deleted.
  77. Dump: Dump out the attribute information for the specified connections.
  78. Automatically building a hub-spoke topology -
  79. An associated script called mkhubbchtop takes a list of hub servers and a list
  80. of branch servers and builds a connection data file for a hub-branch topology
  81. that can be used by this script. mkhubbchtop balances the branch servers
  82. across the list of hub servers with a staggered schedule so all branches are
  83. not hitting the hub server at the same time. See the help info in mkhubbchtop
  84. Schedule parameter and load sharing -
  85. The schedule parameter provides a means for setting a repeating replication schedule.
  86. Connection schedules are an attribute associated with each NTDS-Connection object
  87. in the DC. They contain a 7x24 array of bytes, one byte for each hour in a
  88. 7 day week (UTC time zone). You can use the schedule paramter to spread the
  89. replication load among multiple inbound source servers.
  90. The paramter is of the form s-iii-ccc-ppp where the i, c and p fields are decimal
  91. numbers. The i field describes the desired interval (in hours) between inbound
  92. replication events on the host server. The c field describes the number of
  93. connections objects present that will import data to this host server. Or, put
  94. another way, it is the number of other servers that will be providing data to
  95. this server. The p field is offset parameter that ranges from 0 to c-1. It
  96. is used to stagger the schedule relative to the schedules on the other connection
  97. objects.
  98. For example, lets assume you have two connection objects that refer to two servers
  99. SA and SB which will supply replication updates to the host server. We would
  100. like to arrange the schedules of these two connection objects so that our host
  101. server is updated every 4 hours. To do this, the schedule parameter for the
  102. connection object referring to server SA would be 's-4-2-0' and the parameter
  103. for the connection to server SB is 's-4-2-1'.
  104. Source H o u r
  105. Server 0 4 8 12 16 20
  106. SA s-4-2-0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
  107. SB s-4-2-1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ...
  108. Repl Events ^ ^ ^ ^ ^ ^
  109. With these two connection objects the net interval between replication events
  110. will be every 4 hours. The schedule for server B is offset by 4 hours as a result
  111. of the p field being 1. Both of the above schedule patterns continue to repeat
  112. over the course of the 7x24 array comprising the schedule attribute.
  113. As a second example, assume you want to replicate every 2 hours and you establish
  114. connections with three other servers to provide the data. The schedule paramter
  115. values and the schedule array are then:
  116. Source H o u r
  117. Server 0 4 8 12 16 20
  118. SA s-2-3-0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ...
  119. SB s-2-3-1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ...
  120. SC s-2-3-2 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 ...
  121. Repl Events ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  122. Schedmask and Schedoverride parameters -
  123. Schedmask and schedoverride data are formatted as a pair of ascii hex digits
  124. for each byte in the 7x24 schedule array with byte 0 corresponding to day 1 hour 0.
  125. For each connection the 7x24 result schedule is formed using the schedule parameter (see
  126. below) and then the schedule mask is applied (each bit set in the schedule mask
  127. clears the corresponding bit in the result schedule). Finally the schedule override
  128. is applied with a logical OR of the override schedule to the result schedule.
  129. Schedmask and schedoverride can have embedded whitespace chars (including cr/lf)
  130. which are deleted or be a single string of 336 (7*24*2) hex digits. For example:
  131. FF0000000000 000000000000 000000000000 000000000000
  132. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  133. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  134. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  135. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  136. FF0000000000 000000000000 000000000000 000000000000
  137. FF0000000000 000000000000 000000000000 000000000000
  138. SAMPLE INPUT FILE ---
  139. #A sample input file might look as follows:
  140. #
  141. /dc ntdev-dc-01
  142. /clean
  143. #
  144. # Host Server From Server Enabled Schedule
  145. #
  146. create Red-Bldg40\\ntdev-dc-01 Red-bldg40\\ntdsdc9 on s-4-2-0 # update every 8 hours beg at hr 0
  147. create Red-Bldg40\\ntdev-dc-01 Red-bldg40\\ntdsdc8 on s-4-2-1 # update every 8 hours beg at hr 4
  148. # update every 2 hours beg at hr 0
  149. update Red-Bldg40\\ntdev-dc-01 Red-bldg40\\ntdsdc90 on s-2-1-0
  150. #End of file
  151. EXAMPLE CREATE COMMAND --
  152. As an example the following create command produces a connection object on ntdsdc9.
  153. (Host Server) (From Server)
  154. create Red-bldg40\\ntdsdc9 ITG-Red-Bldg11\\NTDEV-DC-08 on s-1-37-0 /DC ntdsdc9
  155. /DC parameter value (optional) is used as the first parameter in the ldap_open()
  156. call by mkdsxe.exe to bind to the desired DC.
  157. The two parameters are the host server (or the destination server) and the
  158. from server. Each is of the form <site name>\\<server name>
  159. The FQDN of the created connection object is formed as follows with site name
  160. and server name plugged in as shown with underlines.
  161. Dn:CN=From-ITG-Red-Bldg11-NTDEV-DC-08,CN=NTDS Settings,CN=ntdsdc9,CN=Servers,CN=Red-bldg40,CN=Sites,CN=Configuration,DC=ntdev,DC=microsoft,DC=com
  162. ------- ----------
  163. The FQDN of the fromServer attribute for the connection is formed as follows
  164. with site name and server name plugged in as shown with underlines.
  165. fromServer: CN=NTDS Settings,CN=NTDEV-DC-08,CN=Servers,CN=ITG-Red-Bldg11,CN=Sites,CN=Configuration,DC=ntdev,DC=microsoft,DC=com
  166. ----------- --------------
  167. Note that the "connection object name attribute" is NOT used in finding a connection
  168. object (e.g. in del, dump or update commands). Instead the NTDS settings container
  169. is used and a search is made on the fromServer attribute (which may return multiple
  170. objects).
  171. ERROR HANDLING --
  172. Any command line that returns an error is written to the ReDo file.
  173. An error message is written to standard out.
  174. Note: The redo file is deleted when the script starts so if no redo file exists
  175. after completion of the script then all commands were processed without errors.
  176. ";
  177. die $USAGE unless @ARGV;
  178. ## $mkdsx = "mkdsxe.exe /v ";
  179. $mkdsx = "mkdsxe.exe ";
  180. $varnumargs = 99;
  181. $time = scalar localtime;
  182. printf DAT ("Running mkdsx on: %s\n", $time);
  183. printf("\n\n");
  184. $redo = $ENV{'MKDSX_REDO_FILE'}; printf("MKDSX_REDO_FILE: %s\n", $redo);
  185. $dcname = $ENV{'MKDSX_DCNAME'}; printf("MKDSX_DCNAME: %s\n", $dcname);
  186. $verbose = $ENV{'MKDSX_VERBOSE'}; printf("MKDSX_VERBOSE: %s\n", $verbose);
  187. if ($redo eq "") {$redo = "mkdsx.redo";}
  188. if ($dcname ne "") {$dcname = "/dc $dcname";}
  189. if ($verbose ne "") {$verbosemode = "/v";}
  190. printf("\n\n");
  191. print $0 @argv;
  192. printf("Redo File: %s\n", $redo) if ($redo ne "");
  193. #
  194. # mkdsx.exe error return codes (from mkdsx.h)
  195. #
  196. $MKDSXE_SUCCESS = 0;
  197. $MKDSXE_BAD_ARG = 1;
  198. $MKDSXE_CANT_BIND = 2;
  199. $MKDSXE_NO_T0_NTDS_SETTINGS = 3;
  200. $MKDSXE_NO_FROM_NTDS_SETTINGS = 4;
  201. $MKDSXE_CXTION_OBJ_CRE_FAILED = 5;
  202. $MKDSXE_UNUSED_1 = 6;
  203. $MKDSXE_CXTION_OBJ_UPDATE_FAILED = 7;
  204. $MKDSXE_CXTION_NOT_FOUND_UPDATE = 8;
  205. $MKDSXE_CXTION_DUPS_FOUND_UPDATE = 9;
  206. $MKDSXE_CXTION_DELETE_FAILED =10;
  207. $MKDSXE_CXTION_NOT_FOUND_DELETE =11;
  208. $MKDSXE_MULTIPLE_CXTIONS_DELETED =12;
  209. $MKDSXE_CXTION_DUMP_FAILED =13;
  210. $MKDSXE_CXTION_NOT_FOUND_DUMP =14;
  211. $MKDSXE_MULTIPLE_CXTIONS_DUMPED =15;
  212. $ErrMsg[$MKDSXE_SUCCESS ] = "Success.";
  213. $ErrMsg[$MKDSXE_BAD_ARG ] = "Invalid Arguments.";
  214. $ErrMsg[$MKDSXE_CANT_BIND ] = "Could not bind to the DC.";
  215. $ErrMsg[$MKDSXE_NO_T0_NTDS_SETTINGS ] = "Could not find 'NTDS Settings' object. Check the host site\\server parameter.";
  216. $ErrMsg[$MKDSXE_NO_FROM_NTDS_SETTINGS ] = "Could not find 'NTDS Settings' object. Check the from site\\server parameter.";
  217. $ErrMsg[$MKDSXE_CXTION_OBJ_CRE_FAILED ] = "Error creating connection.";
  218. $ErrMsg[$MKDSXE_UNUSED_1 ] = "Connection already exists.";
  219. $ErrMsg[$MKDSXE_CXTION_OBJ_UPDATE_FAILED] = "Error updating connection.";
  220. $ErrMsg[$MKDSXE_CXTION_NOT_FOUND_UPDATE ] = "Error updating connection; connection not found.";
  221. $ErrMsg[$MKDSXE_CXTION_DUPS_FOUND_UPDATE] = "Error updating connection; duplicate connections found.";
  222. $ErrMsg[$MKDSXE_CXTION_DELETE_FAILED ] = "Error deleting connection.";
  223. $ErrMsg[$MKDSXE_CXTION_NOT_FOUND_DELETE ] = "Error deleting connection; connection not found.";
  224. $ErrMsg[$MKDSXE_MULTIPLE_CXTIONS_DELETED] = "Deleting multiple connection.";
  225. $ErrMsg[$MKDSXE_CXTION_DUMP_FAILED ] = "Error dumping connection.";
  226. $ErrMsg[$MKDSXE_CXTION_NOT_FOUND_DUMP ] = "Error dumping; connection not found.";
  227. $ErrMsg[$MKDSXE_MULTIPLE_CXTIONS_DUMPED ] = "Dumping duplicate connections.";
  228. #
  229. # Valid commands with number of required params.
  230. #
  231. $cmdtab{"/dc"} = 1;
  232. $cmdtab{"/schedmask"} = 1;
  233. $cmdtab{"/schedoverride"} = 1;
  234. $cmdtab{"/debug"} = 0;
  235. $cmdtab{"/verbose"} = 0;
  236. $cmdtab{"/auto_cleanup"} = $varnumargs;
  237. $cmdtab{"create"} = 4;
  238. $cmdtab{"update"} = 4;
  239. $cmdtab{"del"} = 2;
  240. $cmdtab{"dump"} = 2;
  241. $linenumber = 0;
  242. $InFile = "";
  243. unlink $redo;
  244. $redo_cnt = 0;
  245. $cleanup = 0;
  246. while (<>) {
  247. if ($InFile ne $ARGV) {
  248. $InFile = $ARGV;
  249. printf("Processing file %s \n\n", $InFile);
  250. $linenumber = 0;
  251. }
  252. $linenumber++;
  253. $cleancmd = "";
  254. chop;
  255. ($func, @a) = split;
  256. if (($func eq "") || ($func =~ m/^#/)) {next;}
  257. #
  258. # check for valid command and for missing or extraneous parameters.
  259. #
  260. $func = lc($func);
  261. if (!exists($cmdtab{$func})) {
  262. printf("Line %d: Error: %s unrecognized command.\n%s\n\n", $linenumber, $func, $_);
  263. goto ERROR;
  264. }
  265. $numargs = $cmdtab{$func};
  266. #
  267. # Are there any optional params present?
  268. #
  269. if ($numargs ne $varnumargs) {
  270. $option = ""; $optionarg = "";
  271. if ($a[$numargs] =~ m/\/dc/i) {
  272. $option = $a[$numargs]; $optionarg = $a[$numargs+1];
  273. $numargs += 2;
  274. }
  275. if (($a[$numargs] ne "") && !($a[$numargs] =~ m/^#/)) {
  276. printf("Line %d: Error: %s has extraneous or missing parameters - skipping\n%s\n\n", $linenumber, $func, $_);
  277. goto ERROR;
  278. }
  279. $i = $numargs;
  280. while ($i-- > 0) {
  281. if (($a[i] eq "") || ($a[$i] =~ m/^#/)) {
  282. printf("Line %d: Error: %s missing parameters - skipping\n%s\n\n", $linenumber, $func, $_);
  283. goto ERROR;
  284. }
  285. }
  286. }else {
  287. #
  288. # This command has a variable number of args. Scan for the last one.
  289. #
  290. $i = 0;
  291. while ($i <= $#a) {
  292. if ($a[$i] =~ m/^#/) {
  293. $#a = $i - 1; # Truncate the array at the comment marker
  294. last;
  295. }
  296. $i += 1;
  297. }
  298. }
  299. #
  300. # func a0 a1 a2 a3 a4
  301. # Host Server From Server Enabled Schedule option
  302. # create site\\server site\\server on|off s-ii-cc-pp [/dc dcname] # comment
  303. # update site\\server site\\server on|off s-ii-cc-pp [/dc dcname] # comment
  304. #
  305. # /dc <default computer name of DC on which to create the connection objects>
  306. # /auto_cleanup [DCname1 DCname2 ...]
  307. # /debug
  308. # /schedmask <file>
  309. # /schedoverride <file>
  310. if ($func =~ m/\/dc/i) {
  311. $dcname = "/dc $a[0]";
  312. printf("Default DC name change: %s\n", $a[0]);
  313. next;
  314. }
  315. if ($func =~ m/\/schedmask/i) {
  316. $schedmask = "/schedmask $a[0]";
  317. printf("schedmask change: %s\n", $a[0]);
  318. next;
  319. }
  320. if ($func =~ m/\/schedoverride/i) {
  321. $schedoverride = "/schedoverride $a[0]";
  322. printf("schedoverride change: %s\n", $a[0]);
  323. next;
  324. }
  325. if ($func =~ m/\/auto_cleanup/i) {
  326. printf("Automatic cleanup (i.e. delete) of old connections under each site\server is enabled.\n");
  327. $cleanup = 1;
  328. push @cleanup_list, @a;
  329. printf("Auto cleanup will occur on the following computers:\n");
  330. print @cleanup_list;
  331. next;
  332. }
  333. if ($func =~ m/\/debug/i) {
  334. printf("Debug mode enabled. DC modifications supressed.\n");
  335. $debugmode = "/debug";
  336. next;
  337. }
  338. if ($func =~ m/\/verbose/i) {
  339. printf("Verbose mode enabled.\n");
  340. $verbosemode = "/v";
  341. next;
  342. }
  343. $host = $a[0]; $fromsrv = $a[1]; $enable = $a[2]; $sched = $a[3];
  344. ($host_site, $host_srv) = split(/\\/, $host);
  345. ($from_site, $from_srv) = split(/\\/, $fromsrv);
  346. #
  347. # check for correct number of parameters.
  348. #
  349. if (($host_site eq "") || ($host_srv eq "")) {
  350. printf("Line %d: Error: Host Site or Server is null - skipping\n%s\n\n", $linenumber, $_);
  351. goto ERROR;
  352. }
  353. if (($from_site eq "") || (($from_srv eq "") && ($from_site ne "*"))) {
  354. printf("Line %d: Error: Host Site or Server is null - skipping\n%s\n\n", $linenumber, $_);
  355. goto ERROR;
  356. }
  357. #
  358. # check for DC override option.
  359. #
  360. $binddc = $dcname;
  361. if ($option =~ m/\/dc/i) {
  362. $binddc = "/dc $optionarg";
  363. }
  364. #
  365. # build function call for create / update commands.
  366. #
  367. if ($func =~ m/create|update/i) {
  368. if ($from_site eq "*") {
  369. printf("Line %d: From site of \"*\" not allowed for %s command - skipping\n%s\n\n",
  370. $linenumber, $func, $_);
  371. goto ERROR;
  372. }
  373. if (!($enable =~ m/on|off/i)) {
  374. printf("Line %d: Third parameter of %s command must be 'on' or 'off' - skipping\n%s\n\n",
  375. $linenumber, $func, $_);
  376. goto ERROR;
  377. }
  378. $enable_arg = ($enable =~ m/on/i) ? "/enable" : "/disable";
  379. if (!($sched =~ m/s\-[0-9]+\-[0-9]+\-[0-9]+/i)) {
  380. printf("Line %d: Fourth parameter of %s command must be s-iii-ccc-ppp - skipping\n%s\n\n",
  381. $linenumber, $func, $_);
  382. goto ERROR;
  383. }
  384. ($junk, $iii, $ccc, $ppp) = split(/-/, $sched);
  385. if ($ppp >= $ccc) {
  386. printf("Line %d: Fourth parameter of %s command s-iii-ccc-ppp, ppp must be less than ccc - skipping\n%s\n\n",
  387. $linenumber, $func, $_);
  388. goto ERROR;
  389. }
  390. #
  391. # Make up a delete command if we are auto cleaning old connections.
  392. #
  393. if ($cleanup && ($func =~ m/create/i) && !$hostcleaned{$host}) {
  394. $cleancmd = "$mkdsx $debugmode $verbosemode \
  395. /del /tosite $host_site /toserver $host_srv /all";
  396. }
  397. #
  398. # Remember that we have done either a create or update against this
  399. # host site\server so it is done only once. In particular if we
  400. # see an update command for a host before the first create for the host
  401. # we will NOT do a cleanup on that host if we see a create for it later.
  402. #
  403. $hostcleaned{$host} += 1;
  404. #
  405. # Make a cxtion name if a create.
  406. #
  407. $name_arg = ($func =~ m/create/i) ? "/name From-$from_site-$from_srv" : "";
  408. $mcmd = "$mkdsx $binddc $debugmode $verbosemode /$func $name_arg $enable_arg \
  409. /tosite $host_site /toserver $host_srv \
  410. /fromsite $from_site /fromserver $from_srv \
  411. /schedule $iii $ccc $ppp $schedmask $schedoverride";
  412. }
  413. #
  414. # build function calls for del / dump commands.
  415. #
  416. # func a0 a1 a2 a3
  417. # del site\\server site\\server|* [/dc dcname] # comment
  418. # dump site\\server site\\server|* [/dc dcname] # comment
  419. #
  420. if ($func =~ m/del|dump/i) {
  421. $fromarg = ($from_site eq "*") ? "/all" : "/fromsite $from_site /fromserver $from_srv";
  422. $mcmd = "$mkdsx $binddc $debugmode $verbosemode /$func \
  423. /tosite $host_site /toserver $host_srv $fromarg ";
  424. }
  425. #
  426. # Do the operation on the connection.
  427. #
  428. if ($verbosemode ne "" ) {printf("\n");}
  429. printf("%s\n", $_);
  430. if ($cleancmd ne "") {
  431. doautoclean($cleancmd);
  432. }
  433. if ($verbosemode ne "" ) {printf("\nRunning:\n%s\n", $mcmd)};
  434. $rc = system ($mcmd) / 256;
  435. if ($rc != 0) {
  436. printf("Line %d: Error from mkdsx.exe (%d) - %s - skipping\n%s\n\n",
  437. $linenumber, $rc, $ErrMsg[$rc], $_);
  438. ++$redo_cnt;
  439. goto REDO_CMD;
  440. }
  441. next;
  442. ERROR:
  443. #
  444. # append command record to redo file.
  445. #
  446. $errorcount += 1;
  447. REDO_CMD:
  448. open(REDO, ">>$redo");
  449. #
  450. # put options out first.
  451. #
  452. if ($redo_cnt == 1) {
  453. $time = scalar localtime;
  454. printf REDO ("#Time generated: %s\n", $time);
  455. print REDO "$dcname \n";
  456. print REDO "/auto_cleanup ", @cleanup_list if ($cleanup == 1);
  457. print REDO "/debug \n" if ($debugmode ne "");
  458. print REDO "/verbose \n" if ($verbosemode ne "");
  459. print REDO "$schedmask\n" if ($schedmask ne "");
  460. print REDO "$schedoverride\n" if ($schedoverride ne "");
  461. print REDO "# \n";
  462. }
  463. print REDO "$_\n";
  464. close(REDO);
  465. } # end while()
  466. printf("WARNING: %d command(s) were invalid and not performed. They were written to the Redo File: %s\n",
  467. $errorcount, $redo) if ($errorcount > 0);
  468. printf("WARNING: %d command(s) failed their connection operation. They were written to the Redo File: %s\n",
  469. $redo_cnt, $redo) if ($redo_cnt > 0);
  470. sub doautoclean {
  471. #++
  472. #
  473. # Routine Description:
  474. #
  475. # Run the cleanup command to delete old connections for this site\server.
  476. # This is executed on the target DC.
  477. # If the optional auto cleanup list is supplied then run the command
  478. # against each DC in the list.
  479. #
  480. # If the global params $retrycount and $retrysleep are provided then
  481. # the command is retried after a sleep period if the return status from
  482. # mkdsx is $MKDSXE_CANT_BIND. This is to handle the case where a dialup
  483. # connection is takes too long to be established so the ldap_bind fails.
  484. #
  485. # Arguments:
  486. #
  487. # $command -- The mkdsx connection delete command.
  488. #
  489. # Return Value:
  490. #
  491. # None
  492. #
  493. #--
  494. my ($rclast, $retryx, $rc, $targetdc);
  495. my($command) = @_;
  496. printf("\nRunning autoclean:\n%s\n", $command) if ($verbosemode ne "");
  497. printf(" Clean - %s\n", $binddc) if ($verbosemode ne "");
  498. $rclast = -1;
  499. $retryx = $retrycount;
  500. while ($retryx-- > 0) {
  501. $rc = system ("$command $binddc") / 256;
  502. last if $rc == $MKDSXE_SUCCESS;
  503. if (($rc != $MKDSXE_SUCCESS) && ($rc != $rclast)) {
  504. printf("Line %d: Status return from mkdsx.exe (%d) - %s - for auto cleanup command. Continuing.\n",
  505. $linenumber, $rc, $ErrMsg[$rc]);
  506. $rclast = $rc;
  507. }
  508. last if $rc != $MKDSXE_CANT_BIND;
  509. printf("Line %d: Sleep %d sec followed by a retry\n", $linenumber, $retrysleep);
  510. sleep $retrysleep;
  511. }
  512. #
  513. # Do the same to the auto cleanup list if we have one.
  514. #
  515. foreach $targetdc (@cleanup_list) {
  516. printf(" Clean - /dc %s\n", $targetdc) if ($verbosemode ne "");
  517. $rclast = -1;
  518. $retryx = $retrycount;
  519. while ($retryx-- > 0) {
  520. $rc = system ("$cleancmd /dc $targetdc") / 256;
  521. last if $rc == $MKDSXE_SUCCESS;
  522. if (($rc != $MKDSXE_SUCCESS) && ($rc != $rclast)) {
  523. printf("Line %d: Status return from mkdsx.exe (%d) - %s - for auto cleanup command. Continuing.\n",
  524. $linenumber, $rc, $ErrMsg[$rc]);
  525. }
  526. last if $rc != $MKDSXE_CANT_BIND;
  527. printf("Line %d: Sleep %d sec followed by a retry\n", $linenumber, $retrysleep);
  528. sleep $retrysleep;
  529. }
  530. }
  531. }
  532. __END__
  533. :endofperl
  534. @perl %~dpn0.cmd %*