BSD 4_3 development
[unix-history] / usr / contrib / kermit / ckuus3.c
CommitLineData
ee2abe03
C
1/* C K U U S 3 -- "User Interface" for Unix Kermit, part 3 */
2
3/*
4 Author: Frank da Cruz (SY.FDC@CU20B),
5 Columbia University Center for Computing Activities, January 1985.
6 Copyright (C) 1985, Trustees of Columbia University in the City of New York.
7 Permission is granted to any individual or institution to use, copy, or
8 redistribute this software so long as it is not sold for profit, provided this
9 copyright notice is retained.
10*/
11
12/* SET and REMOTE commands; screen, debug, interrupt, and logging functions */
13
14/* Includes */
15
16#include "ckcdeb.h"
17#include <stdio.h>
18#include <ctype.h>
19#include "ckcker.h"
20#include "ckucmd.h"
21#include "ckuusr.h"
22
23/* Variables */
24
25extern int size, spsiz, rpsiz, npad, timint, rtimo, speed, local, server,
26 image, flow, displa, binary, fncnv, delay, parity, deblog, escape, xargc,
27 turn, duplex, cxseen, czseen, nfils, ckxech, pktlog, seslog, tralog, stdouf,
28 turnch, chklen, bctr, bctu, dfloc, mdmtyp, keep,
29 rptflg, ebqflg, warn, quiet, cnflg, timef, spsizf, mypadn;
30
31extern long filcnt, tlci, tlco, ffc, tfc, fsize;
32
33extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
34extern char *cmarg, *cmarg2, **xargv, **cmlist;
35extern CHAR stchr, mystch, sstate, padch, mypadc, eol, seol, ctlq;
36extern CHAR filnam[], ttname[];
37char *strcpy();
38
39/* Declarations from cmd package */
40
41extern char cmdbuf[]; /* Command buffer */
42
43/* From main ckuser module... */
44
45extern char line[100], *lp; /* Character buffer for anything */
46extern char debfil[50], /* Debugging log file name */
47 pktfil[50], /* Packet log file name */
48 sesfil[50], /* Session log file name */
49 trafil[50]; /* Transaction log file name */
50
51extern int tlevel; /* Take Command file level */
52extern FILE *tfile[]; /* Array of take command fd's */
53\f
54
55/* Keyword tables for SET commands */
56
57
58/* Block checks */
59
60struct keytab blktab[] = {
61 "1", 1, 0,
62 "2", 2, 0,
63 "3", 3, 0
64};
65
66/* Duplex keyword table */
67
68struct keytab dpxtab[] = {
69 "full", 0, 0,
70 "half", 1, 0
71};
72
73struct keytab filtab[] = {
74 "display", XYFILD, 0,
75 "names", XYFILN, 0,
76 "type", XYFILT, 0,
77 "warning", XYFILW, 0
78};
79int nfilp = (sizeof(filtab) / sizeof(struct keytab));
80
81/* Send/Receive Parameters */
82
83struct keytab srtab[] = {
84 "end-of-packet", XYEOL, 0,
85 "packet-length", XYLEN, 0,
86 "pad-character", XYPADC, 0,
87 "padding", XYNPAD, 0,
88 "start-of-packet", XYMARK, 0,
89 "timeout", XYTIMO, 0
90};
91int nsrtab = (sizeof(srtab) / sizeof(struct keytab));
92
93/* Flow Control */
94
95struct keytab flotab[] = {
96 "none", 0, 0,
97 "xon/xoff", 1, 0
98};
99int nflo = (sizeof(flotab) / sizeof(struct keytab));
100\f
101/* Handshake characters */
102
103struct keytab hshtab[] = {
104 "bell", 007, 0,
105 "cr", 015, 0,
106 "esc", 033, 0,
107 "lf", 012, 0,
108 "none", 999, 0, /* (can't use negative numbers) */
109 "xoff", 023, 0,
110 "xon", 021, 0
111};
112int nhsh = (sizeof(hshtab) / sizeof(struct keytab));
113
114struct keytab fntab[] = { /* File naming */
115 "converted", 1, 0,
116 "literal", 0, 0
117};
118
119struct keytab fttab[] = { /* File types */
120 "binary", 1, 0,
121 "text", 0, 0
122};
123
124extern struct keytab mdmtab[] ; /* Modem types (in module ckudia.c) */
125extern int nmdm;
126
127/* Parity keyword table */
128
129struct keytab partab[] = {
130 "even", 'e', 0,
131 "mark", 'm', 0,
132 "none", 0, 0,
133 "odd", 'o', 0,
134 "space", 's', 0
135};
136int npar = (sizeof(partab) / sizeof(struct keytab));
137
138
139/* On/Off table */
140
141struct keytab onoff[] = {
142 "off", 0, 0,
143 "on", 1, 0
144};
145
146/* Incomplete File Disposition table */
147
148struct keytab ifdtab[] = {
149 "discard", 0, 0,
150 "keep", 1, 0
151};
152\f
153/* D O P R M -- Set a parameter. */
154/*
155 Returns:
156 -2: illegal input
157 -1: reparse needed
158 0: success
159*/
160doprm(xx) int xx; {
161 int x, y, z;
162 char *s;
163
164switch (xx) {
165
166
167case XYEOL: /* These have all been moved to set send/receive... */
168case XYLEN: /* Let the user know what to do. */
169case XYMARK:
170case XYNPAD:
171case XYPADC:
172case XYTIMO:
173 printf("...Use 'set send' or 'set receive' instead.\n");
174 printf("Type 'help set send' or 'help set receive' for more info.\n");
175 return(0);
176
177case XYIFD: /* Incomplete file disposition */
178 if ((y = cmkey(ifdtab,2,"","discard")) < 0) return(y);
179 if ((x = cmcfm()) < 0) return(x);
180 keep = y;
181 return(0);
182
183case XYLINE:
184 if ((x = cmtxt("Device name",dftty,&s)) < 0) return(x);
185 ttclos(); /* close old line, if any was open */
186
187 x = strcmp(s,dftty) ? -1 : dfloc; /* Maybe let ttopen figure it out... */
188 if (ttopen(s,&x,mdmtyp) < 0 ) { /* Can we open the new line? */
189 perror("Sorry, can't open line");
190 return(-2); /* If not, give bad return */
191 }
192 if (x > -1) local = x; /* Set local/remote status. */
193 strcpy(ttname,s); /* OK, copy name into real place. */
194 if (!local) speed = -1; /* If remote, say speed unknown. */
195 debug(F111,"set line ",ttname,local);
196 return(0);
197
198case XYCHKT:
199 if ((y = cmkey(blktab,3,"","1")) < 0) return(y);
200 if ((x = cmcfm()) < 0) return(x);
201 bctr = y;
202 return(0);
203
204case XYDEBU:
205 return(seton(&deblog));
206
207case XYDELA:
208 y = cmnum("Number of seconds before starting to send","5",10,&x);
209 debug(F101,"XYDELA: y","",y);
210 return(setnum(&delay,x,y));
211
212case XYDUPL:
213 if ((y = cmkey(dpxtab,2,"","full")) < 0) return(y);
214 if ((x = cmcfm()) < 0) return(x);
215 duplex = y;
216 return(0);
217
218case XYESC:
219 y = cmnum("Decimal ASCII code for escape character","",10,&x);
220 return(setcc(&escape,x,y));
221\f
222case XYFILE:
223 if ((y = cmkey(filtab,nfilp,"File parameter","")) < 0) return(y);
224 switch (y) {
225 int z;
226 case XYFILD: /* Display */
227 y = seton(&z);
228 if (y < 0) return(y);
229 quiet = !z;
230 return(0);
231
232 case XYFILN: /* Names */
233 if ((x = cmkey(fntab,2,"how to handle filenames","converted")) < 0)
234 return(x);
235 if ((z = cmcfm()) < 0) return(z);
236 fncnv = x;
237 return(0);
238
239 case XYFILT: /* Type */
240 if ((x = cmkey(fttab,2,"type of file","text")) < 0)
241 return(x);
242 if ((z = cmcfm()) < 0) return(z);
243 binary = x;
244 return(0);
245
246 case XYFILW: /* Warning/Write-Protect */
247 return(seton(&warn));
248
249 default:
250 printf("?unexpected file parameter\n");
251 return(-2);
252 }
253
254case XYFLOW: /* Flow control */
255 if ((y = cmkey(flotab,nflo,"","xon/xoff")) < 0) return(y);
256 if ((x = cmcfm()) < 0) return(x);
257 flow = y;
258 return(0);
259
260case XYHAND: /* Handshake */
261 if ((y = cmkey(hshtab,nhsh,"","none")) < 0) return(y);
262 if ((x = cmcfm()) < 0) return(x);
263 turn = (y > 0127) ? 0 : 1 ;
264 turnch = y;
265 return(0);
266
267case XYMODM:
268 if ((x=cmkey(mdmtab,nmdm,"type of modem, direct means none","direct")) < 0)
269 return(x);
270 if ((z = cmcfm()) < 0) return(z);
271 mdmtyp = x;
272 return(0);
273\f
274case XYPARI: /* Parity */
275 if ((y = cmkey(partab,npar,"","none")) < 0) return(y);
276 if ((x = cmcfm()) < 0) return(x);
277
278/* If parity not none, then we also want 8th-bit prefixing */
279
280 if (parity = y) ebqflg = 1; else ebqflg = 0;
281 return(0);
282
283case XYPROM:
284 if ((x = cmtxt("Program's command prompt","C-Kermit>",&s)) < 0) return(x);
285 if (*s == '\42') { /* Quoted string? */
286 x = strlen(s) - 1; /* Yes, strip quotes. */
287 if (*(s+x) == '\42') /* This allows leading or trailing */
288 *(s+x) = '\0'; /* blanks. */
289 s++;
290 }
291 cmsetp(s);
292 return(0);
293
294
295/* SET SEND/RECEIVE... */
296
297case XYRECV:
298case XYSEND:
299 if (xx == XYRECV)
300 strcpy(line,"Parameter for inbound packets");
301 else
302 strcpy(line,"Parameter for outbound packets");
303
304 if ((y = cmkey(srtab,nsrtab,line,"")) < 0) return(y);
305 switch (y) {
306
307case XYEOL:
308 y = cmnum("Decimal ASCII code for packet terminator","0",10,&x);
309 if ((y = setcc(&z,x,y)) < 0) return(y);
310 if (xx == XYRECV) eol = z; else seol = z;
311 return(y);
312
313case XYLEN:
314 y = cmnum("Maximum number of characters in a packet","90",10,&x);
315 if ((y = setnum(&z,x,y)) < 0) return(y);
316 if (xx == XYRECV) { /* Receive... */
317 rpsiz = z; /* Just set it. */
318 } else { /* Send... */
319 spsiz = z; /* Set it and flag that it was set */
320 spsizf = 1; /* to allow overriding Send-Init. */
321 }
322 return(y);
323
324case XYMARK:
325 y = cmnum("Decimal ASCII code for packet-start character","1",10,&x);
326 if ((y = setcc(&z,x,y)) < 0) return(y);
327 if (xx == XYRECV) stchr = z; else mystch = z;
328 return(y);
329\f
330case XYNPAD: /* Padding */
331 y = cmnum("How many padding characters for inbound packets","0",10,&x);
332 if ((y = setnum(&z,x,y)) < 0) return(y);
333 if (xx == XYRECV) mypadn = z; else npad = z;
334 return(y);
335
336case XYPADC: /* Pad character */
337 y = cmnum("Decimal ASCII code for inbound pad character","0",10,&x);
338 if ((y = setcc(&z,x,y)) < 0) return(y);
339 if (xx == XYRECV) mypadc = z; else padch = z;
340 return(y);
341
342case XYTIMO:
343 y = cmnum("Interpacket timeout interval","5",10,&x);
344 if ((y = setnum(&z,x,y)) < 0) return(y);
345 if (xx == XYRECV) {
346 timef = 1;
347 timint = z;
348 } else rtimo = z;
349 return(y);
350
351 }
352
353case XYSPEE:
354 if (!local) {
355 printf("\nSpeed setting can only be done on an external line\n");
356 printf("You must 'set line' before issuing this command\n");
357 return(0);
358 }
359 lp = line;
360 sprintf(lp,"Baud rate for %s",ttname);
361 if ((y = cmnum(line,"",10,&x)) < 0) return(y);
362 if (y = (cmcfm()) < 0) return(y);
363 y = chkspd(x);
364 if (y < 0)
365 printf("?Unsupported line speed - %d\n",x);
366 else {
367 speed = y;
368 printf("%s: %d baud\n",ttname,speed);
369 }
370 return(0);
371
372default:
373 if ((x = cmcfm()) < 0) return(x);
374 printf("Not working yet - %s\n",cmdbuf);
375 return(0);
376 }
377}
378\f
379/* C H K S P D -- Check if argument is a valid baud rate */
380
381chkspd(x) int x; {
382 switch (x) {
383 case 0:
384 case 110:
385 case 150:
386 case 300:
387 case 600:
388 case 1200:
389 case 1800:
390 case 2400:
391 case 4800:
392 case 9600:
393 return(x);
394 default:
395 return(-1);
396 }
397}
398
399/* S E T O N -- Parse on/off (default on), set parameter to result */
400
401seton(prm) int *prm; {
402 int x, y;
403 if ((y = cmkey(onoff,2,"","on")) < 0) return(y);
404 if ((x = cmcfm()) < 0) return(x);
405 *prm = y;
406 return(0);
407}
408
409/* S E T N U M -- Set parameter to result of cmnum() parse. */
410/*
411 Call with x - number from cnum parse, y - return code from cmnum
412*/
413setnum(prm,x,y) int x, y, *prm; {
414 debug(F101,"setnum","",y);
415 if (y < 0) return(y);
416 if (x > 94) {
417 printf("\n?Sorry, 94 is the maximum\n");
418 return(-2);
419 }
420 if ((y = cmcfm()) < 0) return(y);
421 *prm = x;
422 return(0);
423}
424
425/* S E T C C -- Set parameter to an ASCII control character value. */
426
427setcc(prm,x,y) int x, y, *prm; {
428 if (y < 0) return(y);
429 if ((x > 037) && (x != 0177)) {
430 printf("\n?Not in ASCII control range - %d\n",x);
431 return(-2);
432 }
433 if ((y = cmcfm()) < 0) return(y);
434 *prm = x;
435 return(0);
436}
437\f
438/* D O R M T -- Do a remote command */
439
440dormt(xx) int xx; {
441 int x;
442 char *s, sbuf[50], *s2;
443
444 if (xx < 0) return(xx);
445 switch (xx) {
446
447case XZCWD: /* CWD */
448 if ((x = cmtxt("Remote directory name","",&s)) < 0) return(x);
449 debug(F111,"XZCWD: ",s,x);
450 *sbuf = NUL;
451 s2 = sbuf;
452 if (*s != NUL) { /* If directory name given, */
453 /* get password on separate line. */
454 if (tlevel > -1) { /* From take file... */
455
456 *line = NUL;
457 if (fgets(sbuf,50,tfile[tlevel]) == NULL)
458 ermsg("take file ends prematurely in 'remote cwd'");
459 debug(F110," pswd from take file",s2,0);
460
461 } else { /* From terminal... */
462
463 printf(" Password: "); /* get a password */
464 while (((x = getchar()) != NL) && (x != CR)) { /* with no echo */
465 if ((x &= 0177) == '?') {
466 printf("? Password of remote directory\n Password: ");
467 s2 = sbuf;
468 *sbuf = NUL;
469 }
470 else if (x == ESC) /* Mini command line editor... */
471 putchar(BEL);
472 else if (x == BS || x == 0177)
473 s2--;
474 else if (x == 025) {
475 s2 = sbuf;
476 *sbuf = NUL;
477 }
478 else
479 *s2++ = x;
480 }
481 *s2 = NUL;
482 putchar('\n');
483 }
484 s2 = sbuf;
485 } else s2 = "";
486 debug(F110," password",s2,0);
487 sstate = setgen('C',s,s2,"");
488 return(0);
489\f
490case XZDEL: /* Delete */
491 if ((x = cmtxt("Name of remote file(s) to delete","",&s)) < 0) return(x);
492 return(sstate = rfilop(s,'E'));
493
494case XZDIR: /* Directory */
495 if ((x = cmtxt("Remote directory or file specification","",&s)) < 0)
496 return(x);
497 return(sstate = setgen('D',s,"",""));
498
499case XZHLP: /* Help */
500 if (x = (cmcfm()) < 0) return(x);
501 sstate = setgen('H',"","","");
502 return(0);
503
504case XZHOS: /* Host */
505 if ((x = cmtxt("Command for remote system","",&cmarg)) < 0) return(x);
506 return(sstate = 'c');
507
508case XZPRI: /* Print */
509 if ((x = cmtxt("Remote file(s) to print on remote printer","",&s)) < 0)
510 return(x);
511 return(sstate = rfilop(s,'S'));
512
513case XZSPA: /* Space */
514 if ((x = cmtxt("Confirm, or remote directory name","",&s)) < 0) return(x);
515 return(sstate = setgen('U',s,"",""));
516
517case XZTYP: /* Type */
518 if ((x = cmtxt("Remote file specification","",&s)) < 0) return(x);
519 return(sstate = rfilop(s,'T'));
520
521case XZWHO:
522 if ((x = cmtxt("Remote user name, or carriage return","",&s)) < 0)
523 return(x);
524 return(sstate = setgen('W',s,"",""));
525
526default:
527 if (x = (cmcfm()) < 0) return(x);
528 printf("not working yet - %s\n",cmdbuf);
529 return(-2);
530 }
531}
532
533
534
535/* R F I L O P -- Remote File Operation */
536
537rfilop(s,t) char *s, t; {
538 if (*s == NUL) {
539 printf("?File specification required\n");
540 return(-2);
541 }
542 debug(F111,"rfilop",s,t);
543 return(setgen(t,s,"",""));
544}
545\f
546/* S C R E E N -- Screen display function */
547
548/* screen(f,c,n,s)
549 f - argument descriptor
550 c - a character or small integer
551 n - a long integer
552 s - a string.
553 Fill in this routine with the appropriate display update for the system.
554 This version is for a dumb tty.
555*/
556screen(f,c,n,s) int f; long n; char c; char *s; {
557 static int p = 0; /* Screen position */
558 int len; /* Length of string */
559 char buf[80]; /* Output buffer */
560 len = strlen(s); /* Length of string */
561 if (!displa || quiet) return; /* No update if display flag off */
562
563 switch (f) {
564
565case SCR_FN: /* filename */
566 conoll(""); conol(s); conoc(SP); p = len + 1; return;
567
568case SCR_AN: /* as-name */
569 if (p + len > 75) { conoll(""); p = 0; }
570 conol("=> "); conol(s); if ((p += (len + 3)) > 78) { conoll(""); p = 0; }
571 return;
572
573case SCR_FS: /* file-size */
574 sprintf(buf,", Size: %ld",n); conoll(buf); p = 0; return;
575
576case SCR_XD: /* x-packet data */
577 conoll(""); conoll(s); p = 0; return;
578
579case SCR_ST: /* File status */
580 switch (c) {
581 case ST_OK: /* Transferred OK */
582 if ((p += 5) > 78) { conoll(""); p = 0; }
583 conoll(" [OK]"); p += 5; return;
584
585 case ST_DISC: /* Discarded */
586 if ((p += 12) > 78) { conoll(""); p = 0; }
587 conoll(" [discarded]"); p += 12; return;
588
589 case ST_INT: /* Interrupted */
590 if ((p += 14) > 78) { conoll(""); p = 0; }
591 conoll(" [interrupted]"); p += 14; return;
592
593 case ST_SKIP: /* Skipped */
594 conoll("");
595 conol("Skipping "); conoll(s); p = 0;
596 return;
597
598 default:
599 conoll("*** screen() called with bad status ***"); p = 0; return;
600 }
601\f
602case SCR_PN: /* Packet number */
603 sprintf(buf,"%s: %ld",s,n); conol(buf); p += strlen(buf); return;
604
605case SCR_PT: /* Packet type or pseudotype */
606 if (c == 'Y') return; /* Don't bother with ACKs */
607 if (c == 'D') { /* Only show every 4th data packet */
608 if (n % 4) return;
609 c = '.';
610 }
611 if (p++ > 78) { /* If near right margin, */
612 conoll(""); /* Start new line */
613 p = 0; /* and reset counter. */
614 }
615 conoc(c); /* Display the character. */
616 return;
617
618case SCR_TC: /* transaction complete */
619 conoc(BEL); return;
620
621case SCR_EM: /* Error message */
622 conoll(""); conoc('?'); conoll(s); p = 0; return; /* +1 */
623
624case SCR_WM: /* Warning message */
625 conoll(""); conoll(s); p = 0; return;
626
627case SCR_TU: /* Undelimited text */
628 if ((p += len) > 78) { conoll(""); p = len; }
629 conol(s); return;
630
631case SCR_TN: /* Text delimited at beginning */
632 conoll(""); conol(s); p = len; return;
633
634case SCR_TZ: /* Text delimited at end */
635 if ((p += len) > 78) { conoll(""); p = len; }
636 conoll(s); return;
637
638case SCR_QE: /* Quantity equals */
639 sprintf(buf,"%s: %ld",s,n);
640 conoll(buf); p = 0; return;
641
642default:
643 conoll("*** screen() called with bad object ***"); p = 0; return;
644 }
645}
646\f
647/* I N T M S G -- Issue message about terminal interrupts */
648
649intmsg(n) long n; {
650 extern char *chstr();
651 char buf[80];
652
653 if ((!displa) || (quiet)) return;
654#ifdef UXIII
655 (void) conchk(); /* clear out pending escape-signals in ckxbsd.c */
656#endif
657 if (n == 1) {
658#ifdef UXIII
659 /* we need to signal before kb input */
660 sprintf(buf,"Type escape (%s) followed by:",chstr(escape));
661 screen(SCR_TN,0,0l,buf);
662#endif
663 screen(SCR_TN,0,0l,"CTRL-F to cancel file, CTRL-R to resend current packet");
664 screen(SCR_TN,0,0l,"CTRL-B to cancel batch, CTRL-A for status report: ");
665 }
666 else screen(SCR_TU,0,0l," ");
667}
668\f
669/* C H K I N T -- Check for console interrupts */
670
671/*** should rework not to destroy typeahead ***/
672
673chkint() {
674 int ch, cn;
675
676 if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
677 cn = conchk(); /* Any input waiting? */
678 debug(F101,"conchk","",cn);
679
680 while (cn > 0) { /* Yes, read it. */
681 cn--;
682 /* give read 5 seconds for interrupt character */
683 if ((ch = coninc(5)) < 0) return(0);
684 switch (ch & 0177) {
685 case 0001: /* CTRL-A */
686 screen(SCR_TN,0,0l,"^A Status report:");
687 screen(SCR_TN,0,0l," file type: ");
688 if (binary) screen(SCR_TZ,0,0l,"binary");
689 else screen(SCR_TZ,0,0l,"text");
690 screen(SCR_QE,0,(long)filcnt," file number");
691 screen(SCR_QE,0,(long)ffc, " characters ");
692 screen(SCR_QE,0,(long)bctu, " block check");
693 screen(SCR_QE,0,(long)rptflg," compression");
694 screen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
695 continue;
696 case 0002: /* CTRL-B */
697 screen(SCR_TN,0,0l,"^B - Cancelling Batch ");
698 czseen = 1;
699 continue;
700 case 0006: /* CTRL-F */
701 screen(SCR_TN,0,0l,"^F - Cancelling File ");
702 cxseen = 1;
703 continue;
704 case 0022: /* CTRL-R */
705 screen(SCR_TN,0,0l,"^R - Resending ");
706 resend();
707 return(1);
708 default: /* Anything else, just ignore */
709 screen(SCR_TU,0,0l," [Ignored] ");
710 continue;
711 }
712 }
713 return(0);
714}
715\f
716/* D E B U G -- Enter a record in the debugging log */
717
718/*
719 Call with a format, two strings, and a number:
720 f - Format, a bit string in range 0-7.
721 If bit x is on, then argument number x is printed.
722 s1 - String, argument number 1. If selected, printed as is.
723 s2 - String, argument number 2. If selected, printed in brackets.
724 n - Int, argument 3. If selected, printed preceded by equals sign.
725
726 f=0 is special: print s1,s2, and interpret n as a char.
727*/
728#ifdef DEBUG
729debug(f,s1,s2,n) int f, n; char *s1, *s2; {
730 static char s[200];
731 char *sp = s;
732
733 if (!deblog) return; /* If no debug log, don't */
734 switch (f) {
735 case F000: /* 0, print both strings, */
736 sprintf(sp,"%s%s%c\n",s1,s2,n); /* and interpret n as a char */
737 zsout(ZDFILE,s);
738 break;
739 case F001: /* 1, "=n" */
740 sprintf(sp,"=%d\n",n);
741 zsout(ZDFILE,s);
742 break;
743 case F010: /* 2, "[s2]" */
744 sprintf(sp,"[%s]\n",s2);
745 zsout(ZDFILE,"");
746 break;
747 case F011: /* 3, "[s2]=n" */
748 sprintf(sp,"[%s]=%d\n",s2,n);
749 zsout(ZDFILE,s);
750 break;
751 case F100: /* 4, "s1" */
752 zsoutl(ZDFILE,s1);
753 break;
754 case F101: /* 5, "s1=n" */
755 sprintf(sp,"%s=%d\n",s1,n);
756 zsout(ZDFILE,s);
757 break;
758 case F110: /* 6, "s1[s2]" */
759 sprintf(sp,"%s[%s]\n",s1,s2);
760 zsout(ZDFILE,s);
761 break;
762 case F111: /* 7, "s1[s2]=n" */
763 sprintf(sp,"%s[%s]=%d\n",s1,s2,n);
764 zsout(ZDFILE,s);
765 break;
766 default:
767 sprintf(sp,"\n?Invalid format for debug() - %d\n",n);
768 zsout(ZDFILE,s);
769 }
770}
771#endif
772\f
773#ifdef TLOG
774/* T L O G -- Log a record in the transaction file */
775/*
776 Call with a format and 3 arguments: two strings and a number:
777 f - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
778 s1,s2 - String arguments 1 and 2.
779 n - Int, argument 3.
780*/
781tlog(f,s1,s2,n) int f; long n; char *s1, *s2; {
782 static char s[200];
783 char *sp = s; int x;
784
785 if (!tralog) return; /* If no transaction log, don't */
786 switch (f) {
787 case F000: /* 0 (special) "s1 n s2" */
788 sprintf(sp,"%s %ld %s\n",s1,n,s2);
789 zsout(ZTFILE,s);
790 break;
791 case F001: /* 1, " n" */
792 sprintf(sp," %ld\n",n);
793 zsout(ZTFILE,s);
794 break;
795 case F010: /* 2, "[s2]" */
796 x = strlen(s2);
797 if (s2[x] == '\n') s2[x] = '\0';
798 sprintf(sp,"[%s]\n",s2);
799 zsout(ZTFILE,"");
800 break;
801 case F011: /* 3, "[s2] n" */
802 x = strlen(s2);
803 if (s2[x] == '\n') s2[x] = '\0';
804 sprintf(sp,"[%s] %ld\n",s2,n);
805 zsout(ZTFILE,s);
806 break;
807 case F100: /* 4, "s1" */
808 zsoutl(ZTFILE,s1);
809 break;
810 case F101: /* 5, "s1: n" */
811 sprintf(sp,"%s: %ld\n",s1,n);
812 zsout(ZTFILE,s);
813 break;
814 case F110: /* 6, "s1 s2" */
815 x = strlen(s2);
816 if (s2[x] == '\n') s2[x] = '\0';
817 sprintf(sp,"%s %s\n",s1,s2);
818 zsout(ZTFILE,s);
819 break;
820 case F111: /* 7, "s1 s2: n" */
821 x = strlen(s2);
822 if (s2[x] == '\n') s2[x] = '\0';
823 sprintf(sp,"%s %s: %ld\n",s1,s2,n);
824 zsout(ZTFILE,s);
825 break;
826 default:
827 sprintf(sp,"\n?Invalid format for tlog() - %ld\n",n);
828 zsout(ZTFILE,s);
829 }
830}
831#endif