-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathckermit90.txt
2013 lines (1697 loc) · 95.3 KB
/
ckermit90.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[1]The Columbia Crown The Kermit Project | Columbia University
612 West 115th Street, New York NY 10025 USA o [2][email protected]
...since 1981
[3]Home [4]Kermit 95 [5]C-Kermit [6]Scripts [7]Current [8]New [9]FAQ
[10]Support
C-Kermit 9.0 Update Notes
Note: C-Kermit 9.0.301 contains a correction that applies only to
Solaris 10 and 11.
C-Kermit 9.0.302 contains corrections that apply only to FreeBSD 8
and 9.
* [15]Large Files
* [16]How to Test Large-File Transfer
* [17]Arithmetic with Large Integers
* [18]FORCE-3 Packet Protocol
* [19]Variable Evaluation
* [20]The RENAME Command You Always Wanted
* [21]Other New Features
* [22]Incompatibilities
* [23]What's Not In C-Kermit 9.0
* [24]And a Loose End
* [25]Demonstration: Secure POP mail fetcher
* [26]Demonstration: HP Switch Configuration Backup
* [27]Demonstration: HP iLO Blade Configuration
* [28]Demonstration: IBM/Rolm/Siemens CBX Management
* [29]Demonstration: CSV and TSV Files
* [30]Demonstration Scripts for Webmasters
This is the third supplement to [31]Using C-Kermit, Second Edition. I
apologize for the scattered nature of the information and I hope I can
organize it and gather it all into one place for easy and definitive
reference some day. It's a big job so it depends on the demand. For the
time being the definitive reference and introduction is the book (which
is now available also in a [32]Kindle Edition), plus the [33]C-Kermit
7.0 update, [34]C-Kermit 8.0 update, and now this one. Plus tons of
other web pages on this site, sample script programs, and so on.
In version 6.0, C-Kermit was a pretty powerful and flexible
communication program with scripting capabilities. By version 9.0, I'd
like to think of it more as a scripting language with built-in
communications. You can get an idea of the kinds of programs you can
write in Kermit language [35]here. You can develop programs quickly
because it's an interactive program, not a compiler. The scripting
language is the command language. Kind of like the Unix shell but
"somewhat" less cryptic, including concepts not only from C but from
PL/I, Snobol, LISP, Bliss, and Smalltalk. The language itself is built
upon the command language of the much-loved [36]DECSYSTEM-20 from the
1970s and 80s, the Clipper Ship of the Text Era. (Text is not a bad
word. Those of us who can touch-type and who are proficient in
text-based computing environments like Unix shell or VMS DCL are likely
to be orders of magnitude more productive than users of GUIs.)
Thanks to (at least) Jeff Altman, William Bader, Ian Beckwith, Nelson
Beebe, Gerry Belanger, Joop Boonen, Rob Brown, Christian Corti, Alexey
Dokuchaev, John Dunlap, Peter Eichhorn, Carl Friedberg, Terry Kennedy,
Günter Knauf, Jason Lehr, Arthur Marsh, Lewis McCarthy, Gary Mills, Ed
Ravin, Jonathan Reams, Mike Rechtman, Mark Sapiro, Steven Schweda
(SMS), Kinjal Shah, Michael Sokolov, Andy Tanenbaum, Seth Theriault,
Zach A. Thomas, Martin Vorländer, and Eric Weaver for assistance, and
to Hewlett-Packard Company for support.
- Frank da Cruz [37][email protected], 30 June 2011
P.S. It occurred to me just before the end of the day that maybe I
should back up the Kermit website on DVD, just in case. Using
[38]Kermit 95 on the desktop over an SSH connection to the Unix file
system where the website resides, I made a fresh directory on the PC,
CD'd to it, and on Unix cd'd to the Website directory, and told
C-Kermit 9.0 to:
C-Kermit> send /recursive /dotfiles /nobackup *
and it re-created the website directory tree in the PC directory, text
files correctly converted to Windows format and binary files correctly
left as-is. The /dotfiles switch means to include files such as
.htaccess whose names start with a dot (period), and the /nobackup
switch means to skip backup files created by EMACs (such as
index.html.~243~). And then I did the same with the FTP sites, about
8GB in all. Watching the file-transfer display was kind of like having
30 years of my life flash before my eyes in a few minutes. Then I
copied the two directories to DVD (the FTP site had to be split over 2
DVDs). The whole operation took under half an hour. The directory tree
on the CD is directly usable in Windows, Unix, or any other operating
system (unlike if I had transferred the files all in binary mode or all
in text mode, or if I had made, say, a gzipped tar archive or a zip
archive). I believe that, to this day, Kermit is the only software that
can do this. If someday I have to upload from these DVDs to Unix, VMS,
or any other operating system, it can be done exactly the same way,
with any necessary conversions on text files done automatically, and
binary files left intact, recursively through a whole very large
directory tree.
What's New in General
Very briefly, the major items:
* [39]Open Source license.
* [40]64-bit file access and transfer and 64-bit integer arithmetic
on most common platforms.
* Support for recent releases of Linux, Mac OS X, *BSD, etc ([41]see
table).
* Support for newer OpenSSL releases up to and including 1.0.0d
([42]see table).
* [43]Strengthened error checking for file transfer under extremely
harsh conditions.
* [44]Simplified semantics for variables used in scripts.
* Super-handy [45]extensions to the RENAME command.
* Other scripting improvements including support for reading and
writing [46]CSV and TSV files.
* [47]MIME character-set names are now recognized.
* Improved logging and debugging (see demo [48]here).
* Lots more described or listed below, and [49]here.
Open Source License
C-Kermit 9.0 has the [50]Revised 3-Clause BSD License, an open source
license approved by OSI, the [51]Open Source Initiative.
Large Files
Kermit is, first and foremost, a file-transfer program. One might
expect it to be able to transfer any kind of file, but that has been
decreasingly the case as file sizes began to cross the 2 gigabyte
threshold.
The biggest change since C-Kermit 8.0.211 is support for large files on
platforms that support them. A "large file" is one whose size is
greater than 2^31-1 (2,147,483,647) bytes (2GB-1); that is, one whose
size requires more than 31 bits to represent. Before now, Kermit was
able to access such files only on 100% 64-bit platforms such as Digital
Unix, later known as Tru64 Unix. In the new release, Kermit takes
advantage of the X/Open Single UNIX Specification Version 2 (UNIX 98)
Large File Support (LFS) specification, which allows 32-bit platforms
to create, access, and manage files larger than 2GB.
Accommodating large files required code changes in many modules,
affecting not only file transfer, but also file management functions
from directory listings to local file manipulation, plus the user
interface itself to allow entry and display of large numbers. All this
had to be done in a way that would not affect pure 32-bit builds on
platforms that do not support large files. Large file support is
summarized in the [52]Table of Platforms; entries in Yellow (32-bit
builds that support 64-bit integers) and Green (64-bit builds) support
large files.
Note that VMS C-Kermit and Kermit 95 for Windows have always been able
to transfer large files. However their user interface used 32-bit
integers for statistics and the file transfer display. In C-Kermit 9.0
Alpha.03, VMS C-Kermit on 64-bit platforms (Alpha and Itanium) should
now give correct statistics and progress displays. (We'll see about
Kermit 95 later.)
How to Test Large-File Transfer
Several methods are available for testing large-file transfers:
* By transferring a real file that is more than 2147483648 bytes long
(a file whose length requires more than 31 bits to express); or to
be totally sure, that is longer than 4294967296 bytes (32 bits or
more). Or to be double super sure, longer than 8589934592 (33
bits).
* If you don't have such a file or there is not sufficient disk space
for such a file, you can create a special kind of file that takes
up one block on the disk but appears to be 4.3GB long by compiling
and running [53]THIS C PROGRAM on Linux, Solaris, HP-UX, or other
Unix platform that supports large files. Kermit or FTP or any other
file transfer program will transfer the result (BIGFILE) in such a
way as to actually put 4.3GB (or other desired size; see source) on
the wire.
* You can use Kermit's CALIBRATE feature to transfer a large file
that doesn't exist. At the receiver, use RECEIVE /CALIBRATE. At the
sender, use SEND /CALIBRATE:length, e.g.:
(At remote kermit...)
$ kermit -Y
C-Kermit> receive /calibrate
(Return to local kermit...)
Ctrl-\c
C-Kermit> send /calibrate:4300000000
This sends a simulated file 4.3GB in length, that does not exist on
the sender and will not take up any disk space on the receiver.
SEND /CALIBRATE: accepts big numbers only in Kermit versions that
support them (this does not include Kermit 95 on Windows). This
method tests only Kermit's ability to express and understand large
file sizes, but does not test Kermit's file-system interface, since
no files are involved.
Arithmetic with Large Integers
Because large file support requires the availability of a 64-bit signed
integer data type, other aspects of C-Kermit were adapted to use it
too, most notably Kermit's algebraic expression evaluator and its
[54]S-Expression interpreter, on all platforms that support large files
(those listed as 64 or 32/64 in the Word column of the [55]table). In
fact, every Kermit command that parses a number in any field can now
parse a large number on those platforms.
S-Expressions can now be forced to operate with integers only, without
floating-point conversion or having to explicitly truncate each result;
as an example. see the revised [56]Easter date calculation script.
FORCE-3 Packet Protocol
The Kermit protocol has proven itself over the past 30 years to be
robust in terms of surviving harsh transmission environments and
delivering the data correctly and completely. In these times of
Internet everywhere and error-correcting modems in the few places where
the Internet isn't, few people even recall the kinds of difficult
conditions that were common when the Kermit protocol was first
developed: noisy telephone lines, serial interfaces that drop
characters, lack of transparency to control or 8-bit characters,
absence of flow control, "bare" modems without error correction.
But the Internet is not everywhere, and not all modems are
error-correcting. Perhaps the most difficult trial so far for Kermit or
any other protocol is the [57]EM-APEX project, in which floats are
dropped into the ocean from an aircraft into the path of a hurricane;
these floats dive into the water measuring current, temperature, and
salinity at different depths and then surface to phone home, sending
the data to land stations using Kermit protocol over
non-error-correcting 300bps [58]Iridium satellite modems, with high
seas and winds battering the floats and heavy ([59]sometimes
electrical) storms between the modem and the satellite.
Because of the transmission speed and long distances involved, the
transfers were very slow. The Kermit software in the floats is
[60]Embedded Kermit, which did not implement sliding windows, which
would have sped up the flow considerably. John Dunlap, engineer at the
University of Washington's Applied Physics Laboratory, undertook the
task of adding sliding windows to E-Kermit. For testing, he rigged up a
[61]simulator in which Kermit transfers take place over a connection
with different amounts of noise and delay. He found that occasionally,
a transfer would appear to succeed, but the received file would be
corrupt.
According to the Kermit protocol definition, the first packet always
has block-check type 1, a 6-bit checksum, which is the only block check
type that all Kermit implementations are required to support; thus any
Kermit partner can process this packet. This packet itself can
negotiate a higher level of checking, such that subsequent packets have
(say) block-check type 3, a 16-bit cyclic redundancy check (CRC)
encoded as three printable 7-bit ASCII characters. The 16-bit CRC can
catch all errors of certain kinds (single-bit, double-bit, bursts of 16
bits or less), and more than 99.9984741210937% of all other possible
errors.
John's simulations revealed that file corruption could occur undetected
when the initial packet was corrupted in such a way that a parameter or
capability byte was changed and the checksum also changed to make the
packet appear to be correct, thus allowing the transfer to proceed with
the two Kermit partners out of sync as to packet encoding and
interpretation (the chances of two such errors producing a seemingly
valid packet are about 1 in 6000 when using the 6-bit checksum). For
example, the compression technique might be misnegotiated and then the
receiver might store incoming data without decompressing it.
The solution is a new option, selected by:
BLOCK-CHECK TYPE 5
to require a type 3 block check (16-bit CRC) on every packet, including
the initial ones, thus reducing the probability of a misnegotiation by
many orders of magnitude. THIS PARAMETER CAN NOT BE NEGOTIATED. Each
Kermit program must be given the "set block 5" command prior to
transfer. That's because normally every Kermit program expects the
first packet to have a 6-bit checksum, and if the first packet has a
3-byte, 16-bit CRC, the packet receiver will think it is corrupted.
In practice, however, it is possible to code the packet receiver
"cheat" by reading the packet data before verifying the block check.
Thus when the receiver is C-Kermit 9.0 or later or E-Kermit 1.7 or
later, it is only necessary to give the "set block 5" command to the
file sender, and the receiver will check for a FORCE-3 first packet. If
the receiver does not support this feature, however, the initial packet
will be be rejected (after several retries) and the file transfer will
not take place. There is no attempt to "back off" to normal behavior.
CAPTION: Table 4. Kermit Protocol Packet Block Check Types
Type Command Bytes Status Explanation
1 SET BLOCK 1 1 Required in all Kermit implementations. Negotiated.
6-bit checksum, suitable for good connections.
2 SET BLOCK 2 2 Optional, negotiated. 12-bit checksum. 64 times
stronger than type 1.
3 SET BLOCK 3 3 Optional, negotiated. 16-bit CRC.
BLANK-FREE-2 SET BLOCK 4 2 Optional, negotiated. 12-bit checksum, two
nonblank bytes.
FORCE-3 SET BLOCK 5 3 Optional, not negotiated. 16-bit CRC forced all
packets.
BLANK-FREE-2 is for environments where Kermit packets are treated as
lines of text, and in which trailing blanks can be stripped; for
example, when transferring files with an IBM mainframe through a 3270
protocol converter.
[62]E-Kermit 1.7
Variable Evaluation
Does the strange behavior of Kermit's \%x variables puzzle or annoy
you?
Kermit software development has been a collaborative project over the
years, with contributions coming in from almost every country and every
sector of the economy - academic, corporate, government. Thus not all
versions, and not all features of a given version, are a product of
systematic design.
One example was the introduction of variables for text substitution,
first in a version of MS-DOS Kermit that was sent in by someone
somewhere (I could look it up, but no time...) Although the design of
the notation for variable names (table below) is mine, the underlying
code was contributed. In that code there was only one kind of variable,
and if I recall correctly the variable name was a backslash followed by
a single letter, for example \a, \b, etc. The contributed code
evaluated these variables recursively, meaning if the definition of a
variable contained variable references, then these were resolved when
dereferencing the variable, and the process would continue as deep down
as necessary to resolve the thing fully.
This was sometimes handy, but it had one severe drawback: There was no
way to use variables in a straightforward way to represent strings that
contained literal backslashes; for example, DOS or Windows pathnames.
This gave rise to all kinds of quoting rules and conventions (e.g.
doubling backslashes or forcing single-level evaluation with
\\fcontents()), and also to the introduction of other kinds of
variables that were evaluated one level deep, rather than recursively.
To accommodate coexistence of different kinds of variables as well as
"escape sequences" for representing control and 8-bit characters, the
syntax for variable names was extended to include three elements: the
leading backslash, then a single character indicating the type of
variable, and then the name of the variable in a format corresponding
to the type designator, as shown in this somewhat simplified table:
CAPTION: Table 1. Variable-name Syntax in Kermit
Notation Meaning
\000 - \255 8-bit character constant (decimal)
\d000 - \d255 Alternative notation for 8-bit character (byte) constant
(decimal)
\o000 - \o377 8-bit character constant (octal)
\x00 - \xff 8-bit character constant (hexadecimal)
\%a - \%z Scalar variable, evaluated recursively.
\%0 - \%9 Macro argument, scalar, evaluated recursively.
\&a - \%& Array name
\&a[x] Array reference, evaluated recursively (x is any constant or
variable)
\v(name) Built-in scalar variable, evaluated one level deep.
\m(name) User-defined scalar variable, evaluated one level deep.
\$(name) An environment variable, evaluated one level deep.
\s(name[n:m]) Compact substring notation, evaluated one level deep.
\fname(args...) Built-in function with zero or more arguments.
\\ Literal backslash
\N OUTPUT command only: NUL, ASCII 0
\B OUTPUT command only: BREAK (250ms, for serial connections)
\L OUTPUT command only: Long BREAK (1.5sec, ditto)
Variable names in Kermit are case-independent. The simplifications in
the table are that the notation for decimal and octal bytes can have
from one to three digits, and can include braces to separate them from
text digits, e.g. \7, \{123}, \o{50}. Hex bytes too, except they must
always have exactly two hex digits, 0-9a-f. Array indices must be, or
must evaluate to, numbers (floating point numbers are truncated).
Associative arrays are also available (dynamic arrays with arbitrary
text as subscript), but they are really just a variation on \m()
variables (read about associative arrays [63]here). Also, there are
some alternative notations for compact substring notation.
We didn't want to have lots of "distinguished" characters, as the UNIX
shell does; one is enough, clarity over brevity. Although the notation
can be a bit cumbersome, we can use the \m(name) form to circumvent the
overevaluation in most contexts. But macro arguments are always
assigned to the \%0-9 variables, and thus always evaluated recursively,
making it difficult and confusing to pass (e.g.) Windows pathnames as
arguments to macros. The same is true for array elements, especially in
contexts where they are used to return results from built-in functions
(for example, \fsplit() used to return the elements of a
[64]comma-separated value list if any of the values contained
backslashes). An even worse scenario is when macro arguments are passed
from one macro to another; for some graphic illustrations see
[65]Taming the Wild Backslash - Part Deux from the [66]C-Kermit 7.0
Update Notes.
We can't just change how variables are evaluated because that would
break existing scripts. But we can always add Yet Another SET Command:
SET COMMAND VARIABLE-EVALUATION { RECURSIVE, SIMPLE }
This applies only to \%a-z and \%0-9 variables and to \&a-z[] arrays
(since all other kinds of variables are evaluated only one level deep).
The default, of course, for backwards compatibility, is RECURSIVE.
SIMPLE forces the evaluation of these variables to return their literal
contents, without further evaluation:
* An exception is made in the case of array subscripts, because
changing how they are evaluated could break a lot of scripts, and
anyway there should never be any harm in evaluating them
recursively because their final value is always (or should be)
numeric, not some string that might contain backslashes.
* The VARIABLE-EVALUATION setting is on the command stack. Thus you
can give this command in a macro, command file, or user-defined
function without affecting the calling environment.
* The new \frecurse() function forces recursive evaluation of its
argument regardless of the VARIABLE-EVALUATION setting. The
argument can be any string (or nothing at all); all the variables
in the string, even \m() ones, are evaluated recursively:
def \%a 1 \%b 3
def \%b 2
def xx easy as \%a
show mac xx
echo \frecurse(\m(xx))
easy as 1 2 3
echo \frecurse(it's as easy as \m(xx))
it's as easy as easy as 1 2 3
* The new \v(vareval) built-in variable contains the current setting
(recursive or simple) at the current command-stack level.
Here's a short script for illustration:
define path c:\users\fdc\somefile.txt
define test1 { # Normal recursive argument evaluation
echo \%0: arg=\%1
}
define test2 { # Simple argument evaluation
set var simple
echo \%0: arg=\%1
}
test1 \m(path)
test2 \m(path)
exit
And here's the result:
?<ERROR:NO_SUCH_FUNCTION:\fdc\somefile.txt()>
test2: arg=c:\users\fdc\somefile.txt
The first line might seem surprising, but under the normal rules (see
table above) \f indicates a function call, with the letters following
the 'f' being the name of the function. But there is no function by
that name... and if there were, you probably didn't intend to call it!
SET COMMAND VARIABLE-EVALUATION SIMPLE has no effect on constants, only
on variables. Note how \m(path) is defined. The DEFINE command assigns
the literal value of its argument to the named variable (see Table 3
below), thus in this case no special syntax is needed. But in other
contexts, you must double the backslashes or use the \fliteral()
function to use literal backslashes in data:
test2 c:\\users\\fdc\\somefile.txt
test2 \fliteral(c:\users\fdc\somefile.txt)
C-Kermit 9.0 adds a new notation for \fliteral() which also has certain
advantages over it: \q(string):
test2 \q(c:\users\fdc\somefile.txt)
Since \fliteral() is a function, its argument list (the text within
parentheses) has special syntax of its own, in which commas and braces
are treated specially and introduce another set of quoting problems.
\q(string) doesn't have these problems. The only consideration is that
parentheses must be balanced or else quoted (preceded by backslash), or
represented as numeric character entities (left paren = \40, (right
paren = \41).
Or else hold the value in a simple variable as we did with \\m(path)
above.
SET COMMAND VARIABLE-EVALUATION SIMPLE is a big change and might have
repercussions that didn't show up in the initial tests; a lot more
testing is needed.
On the topic of variables, let's summarize in one place the ways in
which values can be explicitly assigned to variables. There is nothing
new here except the table itself:
CAPTION: Table 2. Variable Assignment in Kermit
Command Shorthand Explanation
DEFINE name value .name = value The literal value becomes the contents
of the named variable; variables names in the value are copied without
evaluation. This command is for defining macros that take parameters,
as well as for defining simple variables, especially if the values
contain backslashes.
_DEFINE name value Like DEFINE but the name is evaluated before use.
ASSIGN name value .name := value The value is evaluated and the result
becomes the contents of the named variable.
_ASSIGN name value Like ASSIGN but the name is evaluated before use.
EVALUATE name expression .name ::= value The expression (in regular
algebraic notation) is evaluated arithmetically and the result becomes
the contents of the named variable. If the expression contains any
variables they are evaluated first.
_EVALUATE name expression Like EVALUATE but the name is evaluated
before use.
INCREMENT name expression Evaluates the variables in the expression,
then evaluates the expression arithmetically, and then adds the value
to the contents of the named variable, which must be a number or an
algebraic expression. If the expression is empty, a value of 1 is used.
_INCREMENT name expression Like INCREMENT but the name is evaluated
before use.
DECREMENT name expression Evaluates the variables in the expression,
then evaluates the expression arithmetically, and then subtracts the
value from the contents of the named variable, which must be a number
or an algebraic expression. If the expression is empty, a value of 1 is
used.
_DECREMENT name expression Like DECREMENT but the name is evaluated
before use.
DECLARE name = list An array declaration can include an initializer
list; items in the list are evaluated before assignment. This can be
defeated by doubling any backslashes or enclosing individual arguments
in \fliteral().
DO name arguments name arguments When invoking a macro with a DO
command (or an implied one), the arguments are evaluated, then assigned
to \%1, \%2, etc, and the macro's name to \%0.
(SETQ name value) Kermit also includes a mini-[67]LISP interpreter
Variables are evaluated automatically in Kermit commands simply by
referencing them, according to rules given in Table 1. The following
functions can be used to change how a a particular variable is
evaluated:
CAPTION: Table 3. Kermit Functions for Evaluating Variables
Function Argument Description
\fcontents() \%x or \&x[y] Evaluates the variable or array element
(which normally would be evaluated recursively) one level deep.
\fdefinition() name If the argument is a \%x variable or an array
element, it is evaluated to get the name; otherwise the argument is the
name. Its definition is returned with no recursion.
\m() name Equivalent to \fdefinition().
\frecurse() \m(name) Forces recursive evaluation of a macro definition
(a.k.a. long variable name). NOTE: \frecurse() can operate on any kind
of variable as well as on any string containing any mixture of
variables.
C-Kermit's RENAME Command
C-Kermit's RENAME command, which is used for changing the names of
local files or for moving files locally, has two basic forms:
RENAME [ optional-switches ] oldfilename newfilename
This form lets you change the name of a single file from
oldfilename to newfilename. Example:
rename thismonth.log lastmonth.log
RENAME [ optional-switches ] filespec directoryname
This form lets you move (without renaming) one or more files
(all the files that match the filespec, which may contain
wildcard characters such as "*") to the given directory.
Example:
rename *.txt ~/textfiles/
Traditionally, the optional switches have been:
RENAME /LIST oldname newname
Display the old and new name for each file while renaming.
Synonyms: /LOG, /VERBOSE. Example:
rename /list *.txt ~/textfiles/
RENAME /NOLIST oldname newname
Don't display the old and new name for each file while renaming.
This is the default behavior. Synonyms: /NOLOG, /QUIET. Example:
rename /nolist *.txt ~/textfiles/
Reminder: Every switch starts with a slash (/) and must be preceded by
a space.
New RENAME Features for C-Kermit 9.0
A series of new options (switches) have been added to let you change
the names of multiple files at once by case conversion, string
substitution, or character-set conversion, and optionally also move
them to a different directory:
/LOWER: Convert the filename to lowercase
/UPPER: Convert the filename to uppercase
/CONVERT: Change the filename's character encoding
/REPLACE: Do string substitutions on the filename
If the source-file specification includes a path or directory, any
changes are applied to the filenames only, not to the directory or path
specification.
Since name changes, when applied to many files at once, can have
consequences that are not easily undone, there are also some new
controls, safeguards, and conveniences:
RENAME /SIMULATE
This switch tells Kermit to show you what the RENAME command
would do without actually doing it. /SIMULATE implies /LIST.
RENAME /COLLISION:{FAIL,SKIP,OVERWRITE}
This switch governs Kermit's behavior when renaming multiple
files, and any of the names would collide with the name of a
file that already exists. The default, for compatibility with
earlier releases of C-Kermit, is OVERWRITE, i.e. write over the
existing file. The other two protect existing files. SKIP means
to skip (not rename) the file that would cause the collision,
and proceed to the next file, if any. FAIL means that no files
will be renamed if there would be any collisions; for this
Kermit makes two passes, checking each new name it constructs
for existence before starting the second pass (however, there is
no guarantee that in the second pass, it won't create the same
new name for more than one file; in that case, it will stop
before executing the second rename). Example:
rename /simulate /collision:proceed * ~/tmp/
Reminder: In switches such as /COLLISION that take arguments
(operands), the switch name and its argument(s) are separated by a
colon (:) with no intervening spaces. Also remember that Kermit
keywords can always be abbreviated by leaving off characters from the
right, as long as the result is still unique in its context. Thus "ren
/col:f" would be equivalent to "rename /collision:fail".
You can change the following preferences for the RENAME command with
the new SET RENAME command:
SET RENAME LIST { ON, OFF }
Tells the RENAME command whether to list its actions if you
don't include a /LIST or /NOLIST or equivalent switch.
SET RENAME COLLISION { FAIL, OVERWRITE, SKIP }
Tells the RENAME command how to handle filename collisions in
the absence of a /COLLISION switch. That is, it replaces the
default action of OVERWRITE with action of your choosing, which
is then used in any RENAME command that does not include an
explicit /COLLISION switch.
SHOW RENAME
Displays the current SET RENAME settings.
Changing the Case of Filenames
RENAME /UPPER:{ALL,LOWER} filespec [ directory ]
RENAME /LOWER:{ALL,UPPER} filespec [ directory ]
These switches let you change the alphabetic case of letters in
all the files whose names match the filespec. If a directory
name is given after the filespec, then the files are also moved
to the given directory.
By default, all files that match the given filespec have their names
changed (if necessary). This is what the ALL argument means, e.g.:
RENAME /LOWER:ALL *
RENAME /LOWER *
You can use either form: RENAME /LOWER is equivalent to RENAME
/LOWER:ALL. The other argument (/LOWER:UPPER or /UPPER:LOWER) means to
leave mixed-case filenames alone, and rename only those files whose
names contain letters of only the given case. Examples:
RENAME /UPPER:ALL foo.bar
Changes the filename to FOO.BAR.
RENAME /UPPER foo.bar
Same as "rename /upper:all foo.bar".
RENAME /UPPER foo.bar ~/old/
Renames foo.bar to FOO.BAR and moves it to the user's old
directory (Unix).
RENAME /LOWER *
Changes the names of all files to have only lowercase letters.
RENAME /LOWER:UPPER *
Changes the names of only those files whose names contain no
lowercase letters to have only lowercase letters. For example,
FOO.BAR would be changed, Foo.Bar would not be changed. foo.bar
would not be changed either because it's already all lowercase.
RENAME /LOWER:UPPER * ~/new/
Same as the previous example, but also moves each file to the
user's new directory (whether it was renamed or not).
Case conversion works reliably for ASCII characters only. Kermit uses
the C library for this, which on any given platform might or might not
handle non-ASCII letters, and if it does, then how it works would
normally depend on your locale definitions (the LC_CTYPE and/or LANG
environment variable in Unix). When non-ASCII letters are not handled
by the C library, the RENAME command does change their case. For
example, Olga_Tañón.txt might become OLGA_TAñóN.TXT.
String Replacement in Filenames
The RENAME command also lets you change filenames by string
substitution.
RENAME /FIXSPACES[:String] filespec [ directory ]
Replaces all spaces in each matching filename by the given
string, if any, or if none is given, by underscore. Examples:
RENAME /FIX *
RENAME /FIXSPACES:_ *
RENAME /FIXSPACES:"" *
RENAME /FIXSPACES:<040> *
The first two are equivalent, replacing each space with
underscore; a file called "My Favorite Photo.jpg" becomes
"My_Favorite_Photo.jpg". The third example removes all spaces
("MyFavoritePhoto.jpg"). The fourth replaces each space with the
string "<040>" ("My<040>Favorite<040>Photo.jpg").
RENAME /REPLACE:{{String1}{String2}} filespec [ directory ]
Renames each matching file by changing occurrences of String1 in
its name to String2. If a directory specification is included,
the file is also moved to the given directory (even if the name
was not changed). Note that in this case, the curly braces are
part of the command. Example:
RENAME /REPLACE:{{.jpeg}{.jpg}} *
changes all *.jpeg files to *.jpg.
By default, RENAME /REPLACE changes all occurrences of String1 in each
filename to String2 so, for example, if you had a file called
abcjpegxyz.jpeg, the command just shown would change its name to
abcjpgxyz.jpg.
For greater control and flexibility, the /REPLACE: switch argument can
take several distinct forms:
RENAME /REPLACE:String1 filespec [ directory ]
This means to remove all occurrences of String1 from the given
filenames name. It is equivalent to /REPLACE:{{String1}{}}. A
handy use for this option is to remove spaces from filenames.
RENAME /REPLACE:{{String1}{String2}} filespec [ directory ]
As already noted, this replaces every occurrence of String1 with
String2 in each filename. Alphabetic case in string matching is
done according to the current SET CASE setting.
RENAME /REPLACE:{{ }{_}} filespec [ directory ]
This replaces all spaces in the given filenames with underscore,
equivalent to RENAME /FIXSPACES.
RENAME /REPLACE:{{String1}{String2}{Options}} filespec [ directory ]
Options can be included that add more control to the process.
The option string is a sequence of characters; each character in
the string is an option. The choices are:
A String matching is to be case-sensitive, regardless of SET CASE.
a String matching is to be case-independent, regardless of SET CASE.
^ String replacement will occur only at the beginning of the filename.
$ String replacement will occur only at the end of the filename.
1 Only the first occurrence of the string will be replaced.
2 Only the second occurrence of the string will be replaced.
3 4 5 6 7 8 ...
9 Only the ninth occurrence of the string will be replaced.
- (hyphen, minus sign) Before a digit: occurrences will be counted from
the right.
~ (tilde) Before digit or minus sign: all occurrences but the given one
will be replaced.
The tilde modifier works only with single-byte character sets such as
ASCII, CP437, ISO 8859-1, etc, but not with multibyte character sets
such as UCS2, UTF8, or any of the Japanese Kanji sets.
Here are some examples showing how to use the /REPLACE options:
RENAME /REPLACE:{{foo}{bar}{^}} *
For all files whose names start with "foo", replaces the "foo"
at the beginning with "bar".
RENAME /REPLACE:{{}{New-}{^}} *
Prepends "New-" to the name of each file.
RENAME /REPLACE:{{.jpeg}{.jpg}{$}} *
Replaces ".jpeg" at the end of each filename with ".jpg".
RENAME /REPLACE:{{}{-Old}{$}} *
Appends "-Old" to the name of each file.
RENAME /REPLACE:{{foo}{bar}{a}} *
Replaces "foo", "FOO", "Foo", "fOO", etc, with "bar" in each
filename.
RENAME /REPLACE:{{foo}{bar}{A}} *
Replaces only (lowercase) "foo" in filenames with "bar".
RENAME /REPLACE:{{a}{XX}} *
Changes every "a" to "XX". For example a file called "a.a.a.a"
would become "XX.XX.XX.XX".
RENAME /REPLACE:{{a}{X}{2}}
Changes only the second "a" to "X". For example a file called
"a.a.a.a" would become "a.X.a.a".
RENAME /REPLACE:{{a}{X}{-1}}
Changes only the final "a" in the filename (it doesn't have to
be at the end) to "X". For example a file called "a.b.a.c.a.d"
would become "a.b.a.c.X.d".
RENAME /REPLACE:{{foo}{NOTFOO}{-2}}
Changes the second-to-last "foo" (if any) in the filename to
"NOTFOO".
RENAME /REPLACE:{{foo}{}{-2}}
Deletes the second-to-last "foo" (if any) from the filename.
RENAME /REPLACE:{{.}{_}{~1}}
Changes all but the first period to an underscore; for example,
"a.b.c.d.e" would become "a.b_c_d_e".
RENAME /REPLACE:{{.}{_}{~-1}}
Changes all but the final period to an underscore; for example,
"a.b.c.d.e" would become "a_b_c_d.e".
In the Options field, digits (and their modifiers), ^, and $ are
mutually exclusive. If you include more than one of these in the option
string, only the last one is used. Similarly for 'a' and 'A':
RENAME /REPLACE:{{foo}{bar}{Aa2$^}} *
This replaces "foo" with "bar" no matter what combination of
upper and lower case letters are used in "foo" ('a' overrides
'A' in the option string), but only if "foo" is at the beginning
of the filename ('^' overrides '$' and '2').
If you give an /UPPER or /LOWER switch and a /REPLACE switch in the
same RENAME command, the /REPLACE action occurs first, then the case
conversion:
RENAME /REPLACE:{{foo}{bar}} /UPPER * /tmp
For each file: changes all occurrences of "foo" in the name to
"bar", then converts the result to uppercase, and then moves the
file to the /tmp directory. So (for example) "foot.txt" would
become "/tmp/BART.TXT".
Changing the Character Encoding of Filenames
As you know, text is represented on the computer as a series of
numbers, with a given number corresponding to a given character
according to some convention or standard. Filenames are represented the
same way. The trouble is, different computers, or even different
applications on the same computer, might use different standards or
conventions ("character sets") for representing the same characters.
Usually ASCII is safe, but anything beyond that -- non-ASCII characters
such as accented or non-Roman letters -- is likely to vary. Sometimes
you have text that's in the "wrong" character set and you need to
convert it to something you can can use. Kermit has always been able to
handle this as part of file transfer and terminal emulation, as well as
being able to convert text files locally with its TRANSLATE command.
Now there's a way to convert filenames too, for example after copying
files from a CD that uses a different encoding:
RENAME /CONVERT:charset1:charset2 filespec [ directory ]
Converts filenames from the first character set to the second
one. The two character sets can be chosen from the SET FILE
CHARACTER-SET list; for complete details see [68]this page. For
example suppose you have a file called "Olga_Tañón.txt" on a
computer where ISO 8859-1 Latin Alphabet 1 is used, and you have
transported it (e.g. on CDROM) to another computer where the
text encoding is UTF8. Maybe you also have a lot of other files
with similar names in the same directory. You can convert the
filenames to UTF8 like this:
RENAME /CONVERT:latin1:utf8 *
/CONVERT can not be combined with /UPPER, /LOWER, or /REPLACE.
You should NOT use UCS2 for filenames since this encoding is not
compatible with C strings used in Unix and elsewhere.
RENAME /CONVERT affects only the filename, not the file's contents. You
can use the TRANSLATE command to convert the encoding of the contents
of a text file.
Other New Features
See the [69]C-Kermit Daily Builds page for details. Very briefly:
* Perhaps most important, modernized makefile targets for the major
Unix platforms: Linux, Mac OS X, AIX, Solaris, etc. These are
somewhat automated; not autoconf exactly, but they cut down
significantly on redundant targets. For example, one single "linux"
target works on many (hopefully all) different Linux
configurations, where before different targets were required for
different combinations of (e.g.) curses / ncurses / no curses;
32-bit / 64-bit; different feature sets and library locations.
(Separate targets are still required for Kerberos and/or SSL
builds, but they are "subroutinized".)
* Bigger buffers, more storage for commands, macros, scripts,
strings, and filename expansion in 64-bit versions and in 32-bit
versions that support large files.
* User-settable FTP timeout, works on both the data and control
connection.
* FTP access to ports higher than 16383.
* Built-in FTP client for VMS. This is the [70]same FTP client Unix
C-Kermit has had since version 8.0, minimally adapted to VMS by
SMS, supporting binary and Stream_LF file transfer only (in other
words, nothing to handle RMS files), but otherwise fully functional
(and scriptable) and theoretically capable of making connections
secured by SSL (at least it compiles and links OK with SSL - HP SSL
1.3 in this case).
* Large file support in VMS, also by SMS. Alpha and Itanium only (not
VAX). VMS C-Kermit was already able to transfer large files, but
the file-transfer display (numbers and progress bar) and statistics
were wrong because they used ints. In the present Alpha test
release, this is an optional feature requested by including the "f"
option in P1.
* New PUTENV command that allows Kermit to pass environment variables
to subprocesses (Unix only, "help putenv").
* New TOUCH command, many file selection options ("help touch").
* New DIRECTORY command options and switches (/TOP, /COUNT;
HDIRECTORY, WDIRECTORY...). To see the ten biggest files in the
current directory: "dir /top:10 /sort:size /reverse *" or
equivalently, "hdir /top:10 *". WDIR lists files in reverse
chronological order, shorthand for "dir /sort:date /reverse".
* New command FSEEK /FIND:string-or-pattern, seeks to the first line
in an FOPEN'd file that contains the given string or matches the
given pattern. Example: Suppose you have a file of lines like this:
quantity description...
in which the first "word" is a number, followed by a description
(for example, the name of an item). Here is how to use FSEEK to
quickly get the total quantity of any given item, which is passed
as a parameter (either a literal string or a pattern) on the
command line:
#!/usr/local/bin/kermit +
if not def \%1 exit 1 Usage: \fbasename(\%0) string-or-pattern
.filename = /usr/local/data/items.log # Substitute the actual filename
set case off # Searches are case-independent
fopen /read \%c \m(filename) # Open the file
if fail exit 1 "\m(filename): \v(errstring)" # Fail: exit with error message
.total = 0 # OK: Initialize the total
echo Searching "\%1"...
while true {
fseek /line /relative /find:\%1 \%c 0 # Get next line that has target
if fail break # Failure indicates EOF
fread /line \%c line # Read it
if fail break # (shouldn't happen)
increment total \fword(\m(line),1) # Increment the total
}
fclose \%c # Close the file
echo Total for "\%1" : \m(total) # Print the result
exit 0
The syntax of the FSEEK command in this example indicates that each
search should start relative to the current file line. Since Kermit
is an interpretive language, FSEEK is a lot faster than FREAD'ing
each line and checking it for the target, especially for big files.
An especially handy use for FSEEK is for use with potentially huge
sequentially timestamped logs, to seek directly to the date-time
where you want to start processing. Some other improvements for the
FOPEN/FREAD/FWRITE/FCLOSE family of commands are included also
(performance, bug fixes, convenience features), listed in the
[71]change log. (Prior to 9.0.299 Alpha.02, the FSEEK /FIND:
command always started from the top.)
* MIME synonyms for character-set names: A new equivalence between
MIME names and Kermit names for character sets, with a new table
showing the supported sets [72]HERE (this feature is also
illustrated in the [73]Weblog script).
* Unix C-Kermit SET TERMINAL TYPE now passes its arguments to
subprocesses as an environment variable.
* SET SESSION-LOG TEXT now strips out ANSI escape sequences from the
session log.
* For interacting with POP servers over clear-text or SSL-secured
connections:
+ New SSL and TLS "raw" connections (no Telnet protocol).
+ New INPUT command options for reading and capturing (perhaps
while scanning) continuous incoming text, such as INPUT
/NOWRAP (explained [74]HERE).
+ New \femailaddress() command to extract the e-mail address
from an Internet mail message To: or From: line, used in
fetching mail from POP servers.
+ Improved date parsing commands and functions for parsing the
different date formats that can appear in e-mail.
+ Production scripts for fetching mail from a secure POP server,
available [75]HERE.
* Various features added to make Kermit more useful for writing CGI
scripts such as INPUT /COUNT:n to INPUT exactly n characters
(useful for reading form data).
* New \fpictureinfo() function for getting orientation and dimensions
of JPG and GIF images, described [76]HERE.
* New \fgetpidinfo() function for testing whether a given process
exists.
* \fkwdvalue() function fixed to allow multiword values.
* New function \fcount(s1,s2) to tell the number of occurrences of s1
in s2.
* New \flopx() function returns rightmost field from string (such as
a file's extension).
* New function \ffunction(s1) to tell whether a built-in s1 function
exists.
* New \fsqueeze(s1) function removes leading and trailing whitespace
from string s1, changes tabs to spaces, squeezing each run of
repeated whitespace characters to a single space.
* Compact substring notation: \s(somestring[12:18]) is the same as
\fsubstring(\m(somestring),12,18), i.e. the substring starting at
position 12, 18 characters long. \s(somestring[12_18]) means
characters 12 through 18 of the string (7 characters). Also,
\s(somestring[17.]) returns character number 17 of somestring.
* The string indexing functions now accept an optional trailing
argument specifying the occurrence number of the target string.
Likewise, \fword() can fetch words from the right as well as the