001 /*
002 * Author : Curtis Call
003 * Version : 1.43
004 * Last Modified : September 21, 2011
005 * Platform : all
006 * Release : 9.4 and above
007 * License : Public Domain
008 *
009 * Description : slax-doctor detects common SLAX syntax errors that can be hard
010 * to locate manually and can cause confusing error messages.
011 *
012 * While not perfect, the following errors will typically be caught:
013 * - Unterminated comments
014 * - Unterminated strings
015 * - Lines that lack proper termination
016 * - Mixed up parenthesis and curly braces
017 * - Missing brackets
018 * - Missing parenthesis
019 * - Unknown parameters included in template calls
020 * - Missing default-less parameters in template calls
021 * - Trying to treat template parameters like function arguments
022 * - Trying to treat function arguments like template parameters
023 * - Missing call statements when redirecting template results to variables
024 * - Missing namespaces for <func:function> function names
025 *
026 * Caveats:
027 * - Comment delimiters within quotes will cause false errors
028 * - Comment delimiters within comments will cause false errors
029 * - Brackets, parenthesis, and braces within quotes will cause false errors
030 * - Equal signs within quotes passed as function arguments will cause false errors
031 * - More than one single-line comment within a line will cause false errors
032 * - Location paths with /* will cause false errors
033 * - Parameter checking only works within parenthesis, not using the with statement
034 * - Code lines that are split across multiple file lines could cause false errors
035 *
036 * Revisions:
037 * 1.1 - Don't complain about missing jcs templates because they are included in
038 * junos.xsl.
039 * 1.2 - Switched from jcs:invoke() to jcs:execute() because it performs much faster
040 * for bulk operations. Also cleared up the status output.
041 * 1.3 - Clarified error message when parameters look incorrect, it could be a false
042 * error, so insert a "might"
043 * - Added check for missing call statement when redirecting template results to
044 * a variable.
045 * 1.4 - Added check for closing curly brace on lines where it likely was mistakenly
046 * added (will result in false errors for scripts where the closing brace is not
047 * typically put on a line by itself.)
048 * 1.41 - Added check for back function argument syntax
049 * - Added check for missing namespace on <func:function> function name
050 * 1.42 - Fixed function argument syntax check to not mistake templates for functions
051 * 1.43 - Made minor syntax change to workaround a PR - no change in functionality
052 *
053 */
054
055 version 1.0;
056
057 ns junos = "http://xml.juniper.net/junos/*/junos";
058 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
059 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
060 ns str = "http://exslt.org/strings";
061
062 import "../import/junos.xsl";
063
064 var $arguments = {
065 <argument> {
066 <name> "filename";
067 <description> "Script filename to check";
068 }
069 }
070
071 param $filename;
072
073 /* Single session for all SNMP operations */
074 var $connection = jcs:open();
075
076 var $comment-start-instance = "Doctor-Comment-Start";
077 var $base-index-instance = "Doctor-Base-Index";
078
079 /* The size of lines that should be processed at the same time - is the recursion boundary */
080 var $line-chunk-size = 100;
081
082 match / {
083
084 /* Check minimum version */
085 call check-version( $minimum-version = "9.4", $failure-message = "Sorry, the SLAX Doctor needs JUNOS 9.4 or above." );
086
087 /* Retrieve from prompt if not specified as an argument */
088 var $script-file = {
089 if( string-length( $filename) == 0 ) {
090 var $name = jcs:input( "Enter script filename to check: " );
091 expr $name;
092 }
093 else {
094 expr $filename;
095 }
096 }
097
098 /* Open the file */
099 var $show-file-rpc = {
100 <file-show> {
101 <filename> $script-file;
102 }
103 }
104
105 var $show-file-contents = jcs:execute( $connection, $show-file-rpc );
106
107 /* Exit if an error */
108 if( $show-file-contents/..//xnm:error ) {
109 <xsl:message terminate="yes"> "Invalid script file";
110 }
111
112 var $lines = jcs:break-lines( $show-file-contents );
113
114 /* Assemble a string of all characters except for the quote (space won't be recorded due to whitespace trimming) */
115 var $no-quote = {
116 for-each( $ascii/char[num != 34 ] ) {
117 expr sym;
118 }
119 }
120
121 /* Assemble a string of all characters except {(}) (space and tab won't be recorded) */
122 var $no-containers = {
123 for-each( $ascii/char[sym != "{" && sym != "}" && sym != "(" && sym != ")" ] ) {
124 expr sym;
125 }
126 }
127
128 /* Assemble a string of all characters except {(}) and ; (space and tab won't be recorded) */
129 var $no-containers-or-semi-colon = {
130 for-each( $ascii/char[sym != "{" && sym != "}" && sym != "(" && sym != ")" && sym != ";" ] ) {
131 expr sym;
132 }
133 }
134
135 /* Set the comment start to -1 to indicate no comment */
136 call write-integer( $name = $comment-start-instance, $integer = -1 );
137
138 /* Set the base index at 0 */
139 call write-integer( $name = $base-index-instance, $integer = 0 );
140
141 /* Announce the total lines, minus 1 for the extra blank line added */
142 var $total = count( $lines ) - 1;
143 expr jcs:output( "->Total lines in ", $script-file, " = ", $total );
144
145 /* Load the templates so they can be referenced line by line */
146 var $templates := { call load-templates( $lines ); }
147 expr jcs:output( "->Found ", count( $templates/template ), " templates in script file" );
148
149 /* Load the functions so they can be referenced line by line */
150 var $functions := { call load-functions( $lines ); }
151 expr jcs:output( "->Found ", count( $functions/function ), " functions in script file" );
152
153 /* Check for duplicate functions - also report about missing namespaces */
154 call check-for-duplicate-functions( $functions );
155
156 expr jcs:output( "->SLAX Doctor - starting line by line checkup...");
157
158
159 for-each( $lines[ position() mod $line-chunk-size == 1 ] ) {
160
161 var $base-index = { call read-integer( $name = $base-index-instance ); }
162
163 /* Retrieve a chunk of a hundred lines */
164 var $chunk = $lines[ position() > $base-index && $base-index + $line-chunk-size >= position() ];
165
166 /* Record the comment status */
167 var $comment-line = { call read-integer( $name = $comment-start-instance ); }
168
169 /* Announce position */
170 var $adjusted-position = $base-index + 1;
171 var $adjusted-max = $adjusted-position + $line-chunk-size;
172 expr jcs:output( "[Processing lines ", $adjusted-position, "-", $adjusted-max, "]" );
173
174 var $new-comment-line = { call process-lines( $chunk, $base-index, $no-quote, $no-containers,$no-containers-or-semi-colon, $templates, $comment-line, $index = 1 ); }
175
176 /* Store the comment line */
177 call write-integer( $name = $comment-start-instance, $integer = $new-comment-line );
178
179 /* Advance the base-index */
180 call write-integer( $name = $base-index-instance, $integer = $base-index + $line-chunk-size );
181 }
182
183 /* Check if there is an open comment */
184 var $comment-line = { call read-integer( $name = $comment-start-instance ); }
185 if( $comment-line != -1 ) {
186 var $real-line = $comment-line - 1;
187 expr jcs:output( "Possible unterminated comment at line ", $real-line );
188 }
189
190 expr jcs:output( "->Checkup Done!" );
191
192 /* Cleanup */
193 call clear-integer( $name = $comment-start-instance );
194 call clear-integer( $name = $base-index-instance );
195 expr jcs:close( $connection );
196 }
197
198 /*
199 * Parses $functions XML structure looking for dups
200 */
201 template check-for-duplicate-functions( $functions ) {
202 for-each( $functions/function ) {
203 var $outer-position = position();
204 var $outer-name = name;
205
206 if( not( contains( name, ":" ) ) ) {
207 expr jcs:output( "Function ", name, " is missing its namespace" );
208 }
209
210 for-each( $functions/function ) {
211
212 if( position != $outer-position ) {
213
214 if( name == $outer-name ) {
215 expr jcs:output( "Function ", name, " is declared more than once" );
216 }
217 }
218 }
219 }
220 }
221
222 /*
223 * Processes the given line. Compares the included parameters against the
224 * parameters gathered within $templates and reports unknown parameters as well
225 * as missing default-less parameters.
226 */
227 template check-parameters( $line, $real-line, $templates ) {
228
229 var $after-call = substring-after( $line, "call " );
230 var $before-parenthesis = substring-before( $after-call, "(" );
231 var $template-name = normalize-space( $before-parenthesis );
232
233 if( jcs:empty( $templates/template[name == $template-name] ) ) {
234 /* Don't complain about any jcs: functions because they are in import.xsl */
235 if( not( starts-with( $template-name, "jcs:" ) ) ) {
236 expr jcs:output("Line ", $real-line, ": Template ", $template-name, " is not in script file");
237 }
238 }
239 else {
240 var $after-parenthesis = substring-after( $line, "(" );
241 var $parameter-string = { call substring-before-last( $string = $after-parenthesis, $pattern =")" ); }
242
243 var $parameters = jcs:split( ",", $parameter-string );
244 var $template = $templates/template[name == $template-name];
245 var $included := {
246 for-each( $parameters ) {
247 var $name-raw = {
248 if( contains( ., "=" ) ) {
249 expr substring-before( ., "=" );
250 }
251 else {
252 expr .;
253 }
254 }
255 var $name = normalize-space( $name-raw );
256
257 if( string-length( $name ) > 0 ) {
258 /* If it doesn't start with a $ then it isn't a parameter */
259 if( not( starts-with( $name, "$" ) ) ) {
260 expr jcs:output( "Line ", $real-line, ": Template parameter value might not be assigned correctly" );
261 }
262 else if( jcs:empty( $template/parameter[name == $name] ) ) {
263 expr jcs:output( "Line ", $real-line, ": Unknown template parameter ", $name, " for template ", $template-name );
264 }
265 else {
266 <name> $name;
267 }
268 }
269 }
270 }
271 /* Compare against the non-default parameters for the template */
272 for-each( $template/parameter[ jcs:empty( has-default ) ] ) {
273 var $parameter-name = name;
274 if( jcs:empty( $included[name == $parameter-name] ) ) {
275 expr jcs:output( "Line ", $real-line, ": Template ", $template-name, " called without parameter ", $parameter-name, " (It has no default)" );
276 }
277 }
278 }
279 }
280
281 /*
282 * Pulls out all the declared templates and records their parameters. Uses
283 * this XML format:
284 * <template> {
285 * <name> "template-name";
286 * <parameter> {
287 * <name> "parameter-name";
288 * <has-default>; - Included when the parameters has a default value
289 * }
290 * }
291 */
292 template load-templates( $lines ) {
293
294 for-each( $lines ) {
295 var $line = normalize-space( . );
296
297 if( starts-with( $line, "template" ) ) {
298 <template> {
299 var $after-template = substring-after( $line, "template " );
300 var $before-brace = {
301 if( contains( $after-template, "{" ) ) {
302 expr substring-before( $after-template, "{" );
303 }
304 else {
305 expr $after-template;
306 }
307 }
308 var $before-parenthesis = {
309 if( contains( $before-brace, "(" ) ) {
310 expr substring-before( $before-brace, "(" );
311 }
312 else {
313 expr $before-brace;
314 }
315 }
316 <name> normalize-space( $before-parenthesis );
317
318 var $after-parenthesis = substring-after( $line, "(" );
319 var $parameter-string = substring-before( $after-parenthesis, ")" );
320
321 var $parameters = jcs:split( ",", $parameter-string );
322 for-each( $parameters ) {
323 var $has-default = contains( ., "=" );
324 var $name-raw = {
325 if( contains( ., "=" ) ) {
326 expr substring-before( ., "=" );
327 }
328 else {
329 expr .;
330 }
331 }
332 var $name = normalize-space( $name-raw );
333 if( string-length( $name ) > 0 ) {
334 <parameter> {
335 <name> $name;
336 if( $has-default ) {
337 <has-default>;
338 }
339 }
340 }
341 }
342 }
343 }
344 }
345 }
346
347 /*
348 * Pulls out all the declared functions. Uses this XML format:
349 * <function> {
350 * <name> "function-name";
351 * }
352 */
353 template load-functions( $lines ) {
354
355 for-each( $lines ) {
356 var $line = normalize-space( . );
357 var $test-string = "<func:function name"; /* "> */
358 if( starts-with( $line, $test-string ) ) {
359 <function> {
360 var $quote-raw = {
361 expr "\"";
362 }
363 var $quote = {
364 /* Do this because of PR 436699 */
365 if( string-length( $quote-raw ) == 2 ) {
366 expr substring( $quote-raw, 2, 1 );
367 }
368 else {
369 expr $quote-raw;
370 }
371 }
372 var $after-quote = substring-after( $line, $quote );
373 var $before-quote = substring-before( $after-quote, $quote );
374 <name> $before-quote;
375 }
376 }
377 }
378 }
379
380 /*
381 * Returns the substring before the last occurrence of $pattern
382 */
383 template substring-before-last( $string, $pattern ) {
384
385 /* Is pattern at the end? */
386 var $pattern-length = string-length( $pattern );
387 var $string-length = string-length( $string );
388
389 var $slice = substring( $string, $string-length - $pattern-length + 1 );
390
391 if( $string-length == 0 ) {
392 expr "";
393 }
394 else if( $slice == $pattern ) {
395 expr substring( $string, 1, $string-length - $pattern-length - 1 );
396 }
397 else {
398 call substring-before-last( $string = substring( $string, 1, $string-length - 1 ), $pattern );
399 }
400 }
401
402 template count-substring( $string, $substring, $count = 0 ) {
403 if( contains( $string, $substring ) ) {
404 var $before = substring-before( $string, $substring );
405 var $after = substring-after( $string, $substring );
406 call count-substring( $string = $before _ $after, $substring, $count = $count + 1 );
407 }
408 else {
409 expr $count;
410 }
411 }
412
413 template process-lines( $chunk, $base-index, $no-quote, $no-containers, $no-containers-or-semi-colon,$templates, $comment-line, $index ) {
414
415 /* Get the current line */
416 var $line = $chunk[ $index ];
417
418 /* The actual line in the output - including the added blank line at the beginnig */
419 var $current-line = $base-index + $index;
420
421 /* The reported line in the output - after removing the added blank line */
422 var $real-line = $current-line - 1;
423 var $real-comment-line = $comment-line - 1;
424
425 /* Look for starting and ending comment delimiters */
426 var $comment-start = contains( $line, "/*" );
427 var $comment-stop = contains( $line, "*/" );
428
429 /* Check comments, return the $comment-line variable */
430 var $new-comment-line = {
431 /* Look for a /* when a comment is already in progress */
432 if( $comment-line != -1 && $comment-start ) {
433 /* Record an error */
434 expr jcs:output( "Line ", $real-comment-line, ": Possible unterminated comment detected at line ", $real-line );
435
436 /* Change the comment position to the current line if the comment wasn't stopped */
437 if( not( $comment-stop ) ) {
438 expr $current-line;
439 }
440 else {
441 /* comment stopped so set it to -1 */
442 expr -1;
443 }
444 }
445 else if( $comment-start && not( $comment-stop ) ) {
446 /* Record the starting comment */
447 expr $current-line;
448 }
449 /* Look for a stopped comment with no start comment */
450 else if( $comment-stop && not( $comment-start) && $comment-line == -1 ) {
451 /* Record an error */
452 expr jcs:output( "Line ", $real-line, ": Comment stop with no comment start" );
453 /* Comment remains at -1 */
454 expr -1;
455 }
456 /* Stop the comment */
457 else if( $comment-stop && $comment-line > -1 ) {
458 expr -1;
459 }
460 else {
461 expr $comment-line;
462 }
463 }
464
465 /* Only perform the other checks if they aren't part of a multi-line comment and the line has somelength to it */
466 if( string-length( $line ) > 0 && ( $comment-line == -1 && ( not( $comment-start ) || $comment-stop ) ) ) {
467
468 var $check-string = {
469 /* Single line comment is there, remove it */
470 if( $comment-start && $comment-stop ) {
471 expr substring-before( $line, "/*" );
472 expr substring-after( $line, "*/" );
473 }
474 else {
475 expr $line;
476 }
477 }
478 /* For when no extra whitespace is desired */
479 var $normalized-check-string = normalize-space( $check-string );
480
481 /* Check quotes */
482 /* Translate everything except quotes to nothing - do this because of the quote PR */
483 var $only-quotes-raw = translate( $check-string, $no-quote, "" );
484
485 /* Remove spaces and tabs now because the no-quotes string didn't remove them */
486 var $only-quotes = translate( $only-quotes-raw, " \t", "" );
487 if( string-length( $only-quotes ) mod 2 == 1 ) {
488 expr jcs:output( "Line ", $real-line, ": Possible unterminated quote" );
489 }
490
491 /* Check line termination */
492 if( string-length( $normalized-check-string ) > 0 ) {
493 var $end-1 = substring( $normalized-check-string, string-length( $normalized-check-string) );
494 var $end-2 = substring( $normalized-check-string, string-length( $normalized-check-string) - 1 );
495 var $end-3 = substring( $normalized-check-string, string-length( $normalized-check-string) - 2 );
496 var $end-4 = substring( $normalized-check-string, string-length( $normalized-check-string) - 3 );
497
498 /* Allow it to be either { } _ + - / , ; || | && and or mod div */
499 if( $end-1 != "{" && $end-1 != "}" && $end-1 != "_" && $end-1 != "+" && $end-1 != "-" &&$end-1 != "/" &&
500 $end-1 != ";" && $end-1 != "," && $end-1 != "|" && $end-2 != "||" && $end-2 != "&&" &&$end-3 != " or" &&
501 $end-4 != " and" && $end-4 != " mod" && $end-4 != " div" ) {
502
503 expr jcs:output( "Line ", $real-line, ": Check line termination" );
504 }
505 }
506
507 /* Look for ( where { should be or ) where } should be */
508 /* Get rid of all spaces and tabs */
509 var $no-white-space = translate( $check-string, " \t", "" );
510
511 /* This first check could be seen when using ( instead of } in a RTF variable assignment from a template */
512 if( contains( $no-white-space, "=(call" ) ) {
513 expr jcs:output( "Line ", $real-line, ": Possible use of opening parenthesis instead of opening curly brace" );
514 }
515
516 /* This second check could be seen when using ) instead of } in a RTF variable assignment from a template */
517 if( contains( $no-white-space, ");)" ) ) {
518 expr jcs:output( "Line ", $real-line, ": Possible use of closing parenthesis instead of closing curly brace" );
519 }
520
521 /* Look for ({ or }) */
522 /* Get rid of everything except for ({}) */
523 var $only-container = translate( $no-white-space, $no-containers, "" );
524
525 if( contains( $only-container, "({" ) || contains( $only-container, "})" ) ) {
526 expr jcs:output( "Line ", $real-line, ": Possible incorrect parenthesis and curly brace usage" );
527 }
528
529 /* Look for )}; */
530 /* Get rid of everything except for ({}) */
531 var $only-container-or-semi-colon = translate( $no-white-space, $no-containers-or-semi-colon, "");
532
533 if( contains( $only-container-or-semi-colon, ")};" ) ) {
534 expr jcs:output( "Line ", $real-line, ": Possible incorrect semi-colon placement" );
535 }
536 /* Look for )} with no semi-colon */
537 /* Get rid of everything except for ({}); */
538 else if( contains( $only-container-or-semi-colon, ")}" ) ) {
539 expr jcs:output( "Line ", $real-line, ": Possible missing semi-colon" );
540 }
541
542 /* Look for a } in a line that isn't alone, and that doesn't also contain a { */
543 if( string-length( $no-white-space ) > 1 && contains( $no-white-space, "}" ) && not( contains($no-white-space, "{" ) ) ) {
544 expr jcs:output( "Line ", $real-line, ": Possible extra closing curly brace." );
545 }
546
547 /* Check for missing call statements in single-line template to variable assignments */
548 /* i.e. var $example = { get-value(); } */
549 if( contains( $no-white-space, "var" ) && contains( $no-white-space, "={" ) &&
550 contains( $no-white-space, ");}" ) && not( contains( $no-white-space, "{call" ) ) ) {
551
552 expr jcs:output( "Line ", $real-line, ": Possible missing call statement" );
553 }
554
555 /* Check for invalid function argument syntax */
556 /* i.e. var $example = function( $var = "something" ); */
557 if( ( starts-with( $no-white-space, "var" ) || starts-with( $no-white-space, "expr" ) ) && not( contains( $no-white-space, "{call" ) ) ) {
558 var $equal-sign-count = { call count-substring( $string = $no-white-space, $substring = "="); }
559 var $equality-check-count = { call count-substring( $string = $no-white-space, $substring ="==" ); }
560
561 /* Don't get confused by equality checks */
562 var $final-equal-sign-count = $equal-sign-count - ( $equality-check-count * 2 );
563
564 if( $final-equal-sign-count > 1 || ( starts-with( $no-white-space, "expr" ) && $final-equal-sign-count == 1 ) ) {
565 expr jcs:output( "Line ", $real-line, ": Possible bad function argument syntax (ignore if equal sign is inside quotes)" );
566 }
567 }
568
569 /* Verify that func:function names have a : in them */
570 if( contains( $no-white-space, "func:function" ) ) {
571 var $colon-count = { call count-substring( $string = $no-white-space, $substring = ":" ); }
572
573 if( 2 > $colon-count ) {
574 expr jcs:output( "Line ", $real-line, ": Possible missing namespace in function name" );
575 }
576 }
577
578 /* Bracket and parenthesis count checks */
579
580 var $end-1 = substring( $no-white-space, string-length( $no-white-space ) );
581
582 /* A complete line starts with param, call, var, for-each, expr, templatee, if, or < and ends with ; } or { > */
583 var $complete-line = ( (starts-with( $no-white-space, "param" ) || starts-with( $no-white-space,"var" ) || starts-with( $no-white-space, "for-each" ) || starts-with( $no-white-space, "call" ) ||
584 starts-with( $no-white-space, "expr") || starts-with( $no-white-space,"template" ) || starts-with( $no-white-space, "if" ) || starts-with( $no-white-space, "<" ) )
585 && ( $end-1 == ";" || $end-1 == "{" || $end-1 == "}" ) ); /* "> */
586
587 if( $complete-line ) {
588 /* Check for miscount of [ and ] */
589 var $opening-bracket-count = { call count-substring( $string = $no-white-space, $substring ="[" ); }
590 var $closing-bracket-count = { call count-substring( $string = $no-white-space, $substring ="]" ); }
591 if( $opening-bracket-count != $closing-bracket-count ) {
592 expr jcs:output( "Line ", $real-line, ": Possible missing bracket" );
593 }
594
595 /* Check for miscount of ( and ) */
596 var $opening-parenthesis-count = { call count-substring( $string = $no-white-space,$substring = "(" ); }
597 var $closing-parenthesis-count = { call count-substring( $string = $no-white-space,$substring = ")" ); }
598 if( $closing-parenthesis-count != $opening-parenthesis-count ) {
599 expr jcs:output( "Line ", $real-line, ": Possible missing parenthesis" );
600 }
601
602 /* Check for back to back opening braces {{ this probably shouldn't happen */
603 if( contains( $no-white-space, "{{" ) ) {
604 expr jcs:output( "Line ", $real-line, ": Possible extra curly brace" );
605 }
606 }
607
608 /* Check the parameters of lines with template calls in them */
609 if( ( contains( $check-string, " call " ) || contains( $check-string, "{call" ) ) && ( contains($check-string, "(" ) || contains( $check-string, "{" ) ) ) {
610 call check-parameters( $line = $check-string, $real-line, $templates );
611 }
612 }
613
614 /* Recurse through the chunk... */
615 var $new_test_var = count( $chunk );
616 if( ($new_test_var >= $index + 1) ) {
617 call process-lines( $chunk, $base-index, $no-quote, $no-containers, $no-containers-or-semi-colon,$templates, $comment-line = $new-comment-line, $index = $index + 1 );
618 }
619 else {
620 /* Otherwise, output the current value of $new-comment-line */
621 expr $new-comment-line;
622 }
623 }
624
625
626 /*
627 * Writes the given $integer to the Utility Mib using the instance $name
628 */
629 template write-integer( $name, $integer ) {
630
631 var $rpc = {
632 <request-snmp-utility-mib-set> {
633 <instance> $name;
634 <object-type> "integer";
635 <object-value> $integer;
636 }
637 }
638 var $results = jcs:execute( $connection, $rpc );
639
640 }
641
642
643 /*
644 * Clears the integer in the Utility Mib using the instance $name
645 */
646 template clear-integer( $name ) {
647
648 var $rpc = {
649 <request-snmp-utility-mib-clear> {
650 <instance> $name;
651 <object-type> "integer";
652 }
653 }
654 var $results = jcs:execute( $connection, $rpc );
655
656 }
657
658
659 /*
660 * Reads the instance $name integer from the Utility Mib, converts it to oid form first
661 */
662 template read-integer( $name ) {
663 var $oid-name = { call build-oid-name( $name, $type = "integer" ); }
664
665 var $rpc = {
666 <get-snmp-object> {
667 <snmp-object-name> $oid-name;
668 }
669 }
670 var $object = jcs:execute( $connection, $rpc );
671 expr $object/snmp-object/object-value;
672
673 }
674
675
676 /*
677 * This template takes the $instance name and converts it to an oid name for its value.
678 * The type should be specified as well, either "string", "counter", "counter64",
679 * "integer", or "unsigned-integer".
680 * This is used with <get-snmp-object>
681 */
682 template build-oid-name( $name, $type ) {
683
684 /* Build the type portion of the name */
685 var $string-portion = {
686 if( $type == "string" ) {
687 expr "jnxUtilStringValue";
688 }
689 else if( $type == "counter" ) {
690 expr "jnxUtilCounter32Value";
691 }
692 else if( $type == "integer" ) {
693 expr "jnxUtilIntegerValue";
694 }
695 else if( $type == "counter64" ) {
696 expr "jnxUtilCounter64Value";
697 }
698 else if( $type == "counter" ) {
699 expr "jnxUtilUintValue";
700 }
701 }
702
703 /* Split the name into characters */
704 var $characters = str:tokenize( $name, "" );
705
706 var $number-portion = {
707 for-each( $characters ) {
708
709 /* Convert the characters to their ASCII code equivalent */
710 var $char = .;
711 var $ascii-char = $ascii/char[ sym == $char ];
712 expr "." _ $ascii-char/num;
713 }
714 }
715
716 /* Return the full string */
717 expr $string-portion _ $number-portion;
718 }
719
720
721 var $ascii := {
722 <char> { <num> 32; <sym> " "; }<char> { <num> 33; <sym> "!"; }<char> { <num> 34; <sym> "\""; }<char> { <num> 35; <sym> "#"; }<char> { <num> 36; <sym> "$"; }
723 <char> { <num> 37; <sym> "%"; }<char> { <num> 38; <sym> "&"; }<char> { <num> 39; <sym> "'"; }<char> { <num> 40; <sym> "("; }<char> { <num> 41; <sym> ")"; }
724 <char> { <num> 42; <sym> "*"; }<char> { <num> 43; <sym> "+"; }<char> { <num> 44; <sym> ","; }<char> { <num> 45; <sym> "-"; }<char> { <num> 46; <sym> "."; }
725 <char> { <num> 47; <sym> "/"; }<char> { <num> 48; <sym> "0"; }<char> { <num> 49; <sym> "1"; }<char> { <num> 50; <sym> "2"; }<char> { <num> 51; <sym> "3"; }
726 <char> { <num> 52; <sym> "4"; }<char> { <num> 53; <sym> "5"; }<char> { <num> 54; <sym> "6"; }<char> { <num> 55; <sym> "7"; }<char> { <num> 56; <sym> "8"; }
727 <char> { <num> 57; <sym> "9"; }<char> { <num> 58; <sym> ":"; }<char> { <num> 59; <sym> ";"; }<char> { <num> 60; <sym> "<"; }<char> { <num> 61; <sym> "="; } /* >" */
728 <char> { <num> 62; <sym> ">"; }<char> { <num> 63; <sym> "?"; }<char> { <num> 64; <sym> "@"; }<char> { <num> 65; <sym> "A"; }<char> { <num> 66; <sym> "B"; }
729 <char> { <num> 67; <sym> "C"; }<char> { <num> 68; <sym> "D"; }<char> { <num> 69; <sym> "E"; }<char> { <num> 70; <sym> "F"; }<char> { <num> 71; <sym> "G"; }
730 <char> { <num> 72; <sym> "H"; }<char> { <num> 73; <sym> "I"; }<char> { <num> 74; <sym> "J"; }<char> { <num> 75; <sym> "K"; }<char> { <num> 76; <sym> "L"; }
731 <char> { <num> 77; <sym> "M"; }<char> { <num> 78; <sym> "N"; }<char> { <num> 79; <sym> "O"; }<char> { <num> 80; <sym> "P"; }<char> { <num> 81; <sym> "Q"; }
732 <char> { <num> 82; <sym> "R"; }<char> { <num> 83; <sym> "S"; }<char> { <num> 84; <sym> "T"; }<char> { <num> 85; <sym> "U"; }<char> { <num> 86; <sym> "V"; }
733 <char> { <num> 87; <sym> "W"; }<char> { <num> 88; <sym> "X"; }<char> { <num> 89; <sym> "Y"; }<char> { <num> 90; <sym> "Z"; }<char> { <num> 91; <sym> "["; }
734 <char> { <num> 92; <sym> "\\"; }<char> { <num> 93; <sym> "]"; }<char> { <num> 94; <sym> "^"; }<char> { <num> 95; <sym> "_"; }<char> { <num> 96; <sym> "`"; }
735 <char> { <num> 97; <sym> "a"; }<char> { <num> 98; <sym> "b"; }<char> { <num> 99; <sym> "c"; }<char> { <num> 100; <sym> "d"; }<char> { <num> 101; <sym> "e"; }
736 <char> { <num> 102; <sym> "f"; }<char> { <num> 103; <sym> "g"; }<char> { <num> 104; <sym> "h"; }<char> { <num> 105; <sym> "i"; }<char> { <num> 106; <sym> "j"; }
737 <char> { <num> 107; <sym> "k"; }<char> { <num> 108; <sym> "l"; }<char> { <num> 109; <sym> "m"; }<char> { <num> 110; <sym> "n"; }<char> { <num> 111; <sym> "o"; }
738 <char> { <num> 112; <sym> "p"; }<char> { <num> 113; <sym> "q"; }<char> { <num> 114; <sym> "r"; }<char> { <num> 115; <sym> "s"; }<char> { <num> 116; <sym> "t"; }
739 <char> { <num> 117; <sym> "u"; }<char> { <num> 118; <sym> "v"; }<char> { <num> 119; <sym> "w"; }<char> { <num> 120; <sym> "x"; }<char> { <num> 121; <sym> "y"; }
740 <char> { <num> 122; <sym> "z"; }<char> { <num> 123; <sym> "{"; }<char> { <num> 124; <sym> "|"; }<char> { <num> 125; <sym> "}"; }<char> { <num> 126; <sym> "~"; }
741 }
742
743
744 /*
745 * Checks if JUNOS version is at the minimum version or above, displays the
746 * failure message and exits if it is not.
747 */
748 template check-version( $minimum-version, $failure-message ) {
749
750 var $kern-osrelease = jcs:sysctl("kern.osrelease", "s");
751
752 var $version-set = jcs:split("[IRSB-]", $kern-osrelease );
753
754 var $version = $version-set[1];
755
756 if( $minimum-version > $version ) {
757 <xsl:message terminate="yes"> $failure-message;
758 }
759 }
|