char *ckzv = "VRX/VE file support, 4E(038) 30 May 90"; /* C K U F I 2 -- Kermit file system support for VRX/VE systems */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* ****************************************************************** DO NOT COMPILE THIS MODULE WITH #include THIS INCLUDE CAUSES A PERFORMANCE DEGRADATION PEG May 04, 1990 ********************************************************************* */ /* ********************************************************************* May 9, 1990 The following features were removed from the user display and disabled from use. add-linenum id-fields line-numbers renumber May 21, 1990 We added reset logic for errno == EMINR. This (?)error appends spaces characters to line end. Earlier releases we treated this as corruption. This release (V-KERMIT 2.01) we are treating it as normal for the VRX / VE file systems. I did not test for errno (EMINR) directly, I reset it when say an fputs terminates normally, and errno != EMINR. *********************************************************************/ /* Includes */ #include "ckcker.h" /* Kermit definitions */ #include "ckcdeb.h" /* Typedefs, debug formats, etc */ #include "vrx.h" /* VRX SPUR File definitions */ #include /* Character types */ #include /* Standard i/o */ #include /* String routines */ #include #include char *ckzsys = " NCR VRX/VE"; /* Functions (n is one of the predefined file numbers from ckermi.h): zopeni(n,name) -- Opens an existing file for input. zopeno(n,name) -- Opens a new file for output. zclose(n) -- Closes a file. zchin(n,&c) -- Gets the next character from an input file. zsout(n,s) -- Write a null-terminated string to output file, buffered. zsoutl(n,s) -- Like zsout, but appends a line terminator. zsoutx(n,s,x) -- Write x characters to output file, unbuffered. zchout(n,c) -- Add a character to an output file, unbuffered. zchki(name) -- Check if named file exists and is readable, return size. zchko(name) -- Check if named file can be created. znewn(name,s) -- Make a new unique file name based on the given name. zdelet(name) -- Delete the named file. zxpand(string) -- Expands the given wildcard string into a list of files. znext(string) -- Returns the next file from the list in "string". zxcmd(cmd) -- Execute the command in a lower fork. zclosf() -- Close input file associated with zxcmd()'s lower fork. zrtol(n1,n2) -- Convert remote filename into local form. zltor(n1,n2) -- Convert local filename into remote form. zchdir(dirnam) -- Change working directory. zhome() -- Return pointer to home directory name string. zkself() -- Kill self, log out own job. */ /* Some systems define these symbols in include files, others don't... */ #ifndef MAXNAMLEN #define MAXNAMLEN 14 /* If still not defined... */ #endif #define MAXWLD 500 #define SRCLNLEN 82 /* source or control string max line length March 8, 1990 */ #define OPEN 1 /* resetopen processing */ #define CLOSE 0 /* Declarations */ extern long time(); extern int debug(); extern int fncnv, send_id, recv_id, send_num, recv_num, recv_renum, keep; extern int server, recv_addnum, send_addnum, send_renum, deblog, binary; extern char *sys_errlist[]; extern int sys_nerr; extern void perror(); /* ^ extern int errno already declared in errno.h. | why they didnot declare these three are anyone's | guess. March 7, 1990 */ /* forward declarations */ void errhdlr(), resetopen(); int lenchk(); FILE *fp[ZNFILS] = { /* File pointers */ NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static int list_count; /* # matches file names == 1 */ static int pid = 0; /* pid of child fork */ static int fcount; /* Number of files in wild group */ static char nambuf[MAXNAMLEN+2]; /* Buffer for a filename */ char *malloc(), *strcpy(); /* System functions */ static char *mtchs[MAXWLD], /* Matches found for filename */ **mtchptr; /* Pointer to current match */ static char file_type[9]; /* type of current file */ static int char_count; /* number of characters written */ static int spur_type; /* 1=NCRL 2=BASIC 3=FORTB 4=FORTI 5=FORTF 6=FORTV 7=NEAT/3 */ /* 8=NEAT/VS 9=NEAT/C 10=COBOL 11=COBOL/6 12=COBOL/7 13=COBOL/8 */ /* 14=HEADCS 15=PROC,16=PROCN,17=COBOL1,18=COBOL1/6 19=COBOL1/7 */ /* 20=COBOL1/8 21=COBOL4 */ static char language[7]; static int suffix; static int spur_eof = 0; static int linenumber; static char spur_data[400]; /* Area to hold packet data */ static char *nxtspur_data; static char pcard[100]; /* VRX Control String header record */ static int objopen = CLOSE; /* incomplete object files left open by aborted transfers */ static char fn_temp[10]; /* to DELETE incomplete files leftover from interuptions */ /* Z K S E L F -- Kill Self: log out own job, if possible. */ /* Note, should get current pid, but if your system doesn't have */ /* getppid(), then just kill(0,9)... */ zkself() { /* For "bye", but no guarantee! */ return(0); } /* Z O P E N I -- Open an existing file for input. */ zopeni(n, name) int n; char *name; { char buff[100]; if (deblog) { debug(F111, " zopeni", name, n); debug(F101, " fp", "", (int) fp[n]); } if (n == ZIFILE) resetopen(); if (access(name, 0) != 0) { errhdlr("zopeni"); fprintf(stderr,"file does not exist: %s\n",name); return(-1); } if ((suffix == BINARY || suffix == L_BINARY) && !(binary) && (n == ZIFILE)) { errhdlr("file mismatch see STDERR"); fprintf(stderr,"FILE TYPE is set to TEXT\n"); fprintf(stderr,"BINARY file type requested\n"); fprintf(stderr,"set file type to binary 8\n"); fprintf(stderr,"file transport will proceed\n"); return(-1); } if (chkfn(n) != 0) return(0); if (n == ZSYSFN || n == ZSTDIO) /* Input from a system function or stdio */ return(0); /* VRX invailid */ /* * VKERMIT code: * Special handling open required for object files on NCR's VRX/E */ if (*file_type == 'O' && n == ZIFILE) { /* note difference in return numbers for voopen and zopen */ if (voopeni(n, name) == 0) { /* OK */ fp[n] = (FILE *) 1; /* bogus fp to keep ckermit happy */ strcpy(fn_temp, name); objopen = OPEN; fprintf(stderr, "downloading to PC\n"); return(1); } else { errhdlr("zopeni vopeni bad outcome"); return(0); } } /* end VKERMIT code */ if (binary) fp[n] = fopen(name, "rb"); /* Real binary file. */ else fp[n] = fopen(name, "r"); /* Real file. */ if (fp[n] == NULL) { errhdlr("zopeni fp NULL see STDERR"); fprintf(stderr,"input file open failure: %s\n",name); if (binary) { fprintf(stderr,"check V-Kermit set up...an input text file\n"); fprintf(stderr,"can not be opened as a binary file\n"); fprintf(stderr,"text files include source, control\n"); fprintf(stderr,"string, and data file types...\n"); } } else { spur_data[0] = '\0'; nxtspur_data = &spur_data[0]; linenumber = INCREMENT; spur_eof = 0; strcpy(fn_temp, name); fprintf(stderr, "downloading to PC\n"); } if (deblog) debug(F111, " zopeni", name, (int) fp[n]); return((fp[n] != NULL) ? 1 : 0); } /* Z O P E N O -- Open a new file for output. */ zopeno(n, name) int n; char *name; { if (deblog) debug(F111, " zopeno", name, n); if (n == ZOFILE) resetopen(); if ((suffix == BINARY || suffix == L_BINARY) && !(binary) && (n == ZOFILE)) { errhdlr("file mismatch see STDERR"); fprintf(stderr,"FILE TYPE is set to TEXT\n"); fprintf(stderr,"BINARY file type requested\n"); fprintf(stderr,"set file type to binary 8\n"); fprintf(stderr,"file transport will proceed\n"); return(-1); } if (chkfn(n) != 0) return(0); if ((n == ZCTERM) || (n == ZSTDIO) || (n == ZSFILE)) /* Terminal or standard output */ /* or SESIONLOG */ return (0); /* Invalid for VRX */ /* * VKERMIT code: * Use special open for object files on NCR's VRX/E */ if (*file_type == 'O' && n == ZOFILE) { /* note difference in return numbers in voopen and zopen */ if (voopeno(n, name) == 0) { /* OK */ /* bogus file pointer to keep ckermit happy */ fp[n] = (FILE *) 1; strcpy(fn_temp, name); objopen = OPEN; fprintf(stderr, "uploading from PC\n"); return(1); } else { errhdlr("voopeno can't open"); fprintf(stderr, "Error opening upload file %s\n", name); return(0); } } /* end VKERMIT code */ /* FCL references for the log files April 5, 1990 */ switch (n) { char vtmp [45]; case ZTFILE: { sprintf(vtmp, "LOGTRANS(NAME=%s)", name); fp[n] = fopen(vtmp, "w"); } break; case ZDFILE: { sprintf(vtmp, "LOGDEBUG(NAME=%s)", name); fp[n] = fopen(vtmp, "w"); } break; case ZPFILE: { sprintf(vtmp, "LOGPACKET(NAME=%s)", name); fp[n] = fopen(vtmp, "w"); } break; default: if (binary && n == ZOFILE) fp[n] = fopen(name, "wb"); else fp[n] = fopen(name, "w"); if (fp[n] != NULL) { strcpy(fn_temp, name); fprintf(stderr, "uploading from PC\n"); } else { errhdlr("zopeno can't open"); fprintf(stderr, "Error opening: %s\n", name); return (0); } break; } if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { fputc(0, fp[n]); /* space count = 0 on pcard */ if (ferror(fp[n]) != 0 && errno != EMAXR && errno != EMINR) { errhdlr("zopeno PCARD"); fprintf(stderr, "write error: space count PCARD\n"); return(0); } else errno = 0; /* reset errno = EMAXR for pcard write no big deal happens half the time errno EMAXR is the message Maximum record length error (line truncated) April 12, 1990 */ if (zsoutl(n, pcard) == -1) return (0); char_count = 0; } spur_data[0] = '\0'; nxtspur_data = &spur_data[0]; linenumber = INCREMENT; if (deblog) debug(F101, " fp[n]", "", (int) fp[n]); return((fp[n] != NULL) ? 1 : 0); } /* Z C L O S E -- Close the given file. */ /* Returns 0 if arg out of range, 1 if successful, -1 if close failed. */ zclose(n) int n; { int x; if (chkfn(n) < 1) return(0); /* Check range of n */ /* * VKERMIT code: * Use special close for NCR's VRX/E object files */ if (*file_type == 'O' && (n == ZIFILE || n == ZOFILE)) { if (voclose(n) == 0) { fp[n] = NULL; /* March 7, 1990 */ objopen = CLOSE; return(1); } else { fp[n] = NULL; objopen = CLOSE; return(-1); } } /* end VKERMIT code */ if ((fp[n] != stdin) && (fp[n] != stdout)) x = fclose(fp[n]); fp[n] = NULL; if (x == EOF) { errhdlr("zclose"); fprintf(stderr,"Can't close file fclose returned: EOF\n"); } strcpy(fn_temp, "\0"); return((x == EOF) ? -1 : 1); } /* Z C H I N -- Get a character from the input file. */ /* Returns -1 if EOF, 0 otherwise with character returned in argument */ /* removes NULL and DEL characters in Control String and Source files */ zchin(n, c) int n; char *c; { int a; int i = 10; if (*file_type == 'S' || *file_type == 'C') { if (*nxtspur_data == '\0') { spur_data[0] = '\0'; switch (zsreci(n)) { case 0: spur_eof++; break; case 1: break; case -1: return(-1); } if ((spur_eof) && (strlen(spur_data) == 0)) return(-1); nxtspur_data = &spur_data[0]; } a = *nxtspur_data++; } else if (*file_type == 'O') { /* VKERMIT code for VRX/E object files */ /* vogetc returns -1 on end of file and also on error conditions after outputing an appropriate error message. */ if ((a = vogetc(n)) == -1) return(-1); } else { if (chkfn(n) < 1) /* check file address */ return(-1); a = getc(fp[n]); /* place character in a */ if (ferror(fp[n]) != 0) { errhdlr("zchin"); fprintf(stderr, "read error: zchin\n"); return(-1); } if (a == EOF) /* if EOF, return -1 */ return(-1); } *c = a & 0xFF; /* strip top bit */ return(0); } /* Z S O U T -- Write a string to the given file, buffered. */ zsout(n, s) int n; char *s; { if (chkfn(n) < 1) return(-1); if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { char *sptr; sptr = s; if (sptr == NULL) return(0); while (*sptr++ != '\0') { if (*sptr == '\n') { if (putc('\377', fp[n]) == EOF) { errhdlr("zsout/377"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (putc('\n', fp[n]) == EOF) { errhdlr("zsout NL"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (putc('\000', fp[n]) == EOF) { errhdlr("zsout/000"); return((ferror(fp[n]) == 0) ? 0 : -1); } } else if (putc(*sptr, fp[n]) == EOF) { errhdlr("zsout/*sptr"); return((ferror(fp[n]) == 0) ? 0 : -1); } } } else if (fputs(s, fp[n]) == NULL) { errhdlr("zsout/fputs"); return((ferror(fp[n]) == 0) ? 0 : -1); } return(0); } /* Z S O U T L -- Write string to file, with line terminator, buffered */ zsoutl(n, s) int n; char *s; { char *ptr; if (chkfn(n) < 1) return(-1); if (lenchk(s, n)) { switch (spur_type) { case 9: case 11: errhdlr("zsoutl: writing ln > max len"); fprintf(stderr, "writing line > %d char\n", SRCLNLEN + 1); fprintf(stderr, "line length was %d\n", strlen(s)); fprintf(stderr, "%s\n", s); return(-1); default: errhdlr("zsoutl: writing ln > max len"); fprintf(stderr, "writing line > %d char\n", SRCLNLEN); fprintf(stderr, "line length was %d\n", strlen(s)); fprintf(stderr, "%s\n", s); return(-1); } } if (fputs(s, fp[n]) == NULL) { errhdlr("zsoutl/fputs"); return(-1); } if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { if (putc('\377', fp[n]) == EOF) { /* end sentinal character */ errhdlr("zsoutl/377"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (putc('\n', fp[n]) == EOF) { errhdlr("zsoutl/LN CS"); return((ferror(fp[n]) == 0) ? 0 : -1); } } else if (putc('\n', fp[n]) == EOF) { errhdlr("zsoutl/LN"); return((ferror(fp[n]) == 0) ? 0 : -1); } return(0); } /* Z S O U T X -- Write x characters to file, unbuffered. */ zsoutx(n, s, x) int n, x; char *s; { int i; if (chkfn(n) < 1) return(-1); if ((i = write(fp[n]->_file, s, x)) == -1) { errhdlr("zsoutx"); return(-1); } else { return(i); } } /* Z C H O U T -- Add a character to the given file. */ /* Should return 0 or greater on success, -1 on failure (e.g. disk full) */ zchout(n, c) int n; char c; { int i; if (chkfn(n) < 1) return(-1); /* April 5, 1990 This switch statement is courtesy of the corruption in ZSFILE (sessionlog). We now check every character we write to verify it is a printable character. If SET FILE TYPE TEXT is set: (int binary == 0) we verify character for ZOFILE (output file) IF a LOG file we verify whether binary set or not. if a nonprintable character is encountered output to stderr return -1 */ switch (n) { char err_tmp[35]; case ZOFILE: if (binary) break; if (c == 0x1A) return(0); if (!(isprint(c) || isspace(c))) { sprintf(err_tmp, "zchout nonprint char: %X", c); errhdlr(err_tmp); return(-1); } break; case ZSFILE: case ZTFILE: case ZDFILE: case ZPFILE: if (!(isprint(c) || isspace(c))) { sprintf(err_tmp, "zchout: nonprint char: %X", c); errhdlr(err_tmp); fprintf(stderr, "error writing log file: %X\n", n); return(-1); } break; default: /* we should never execute this BUT if I do not put in in I'll be sorry later */ errhdlr("zchout dead code"); fprintf(stderr, "Executing in dead code area: %d\n", n); return(-1); } if (n == ZSFILE) /* Use unbuffered for session log */ return(write(fp[n]->_file, &c, 1)); else { /* Buffered for everything else */ if (*file_type == 'O' && n == ZOFILE) return(voputc(c, n)); else if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { if (c == '\n') { if (zsreco(n) == -1) return (-1); spur_data[0] = '\0'; nxtspur_data = &spur_data[0]; } else { *nxtspur_data++ = c; *nxtspur_data = '\0'; } return(0); } else { if (putc(c, fp[n]) == EOF) { /* If true, maybe an error */ errhdlr("ZCHOUT"); /* Check to make sure */ return((ferror(fp[n]) == 0) ? 0 : -1); } } } } /* C H K F N -- Internal function to verify file number is ok */ /* Returns: -1: File number n is out of range 0: n is in range, but file is not open 1: n in range and file is open */ chkfn(n) int n; { switch (n) { case ZCTERM: case ZSTDIO: case ZIFILE: case ZOFILE: case ZDFILE: case ZTFILE: case ZPFILE: case ZSFILE: case ZSYSFN: break; default: if (deblog) debug(F101, "chkfn: file number out of range", "", n); errhdlr("chkfn"); fprintf(stderr, "File number out of range - %d\n", n); return(-1); } return( (fp[n] == NULL) ? 0 : 1 ); } /* Z C H K I -- Check if input file exists and is readable */ /* Returns: >= 0 if the file can be read (returns the size). -1 if file doesn't exist or can't be accessed, -2 if file exists but is not readable (e.g. a directory file). -3 if file exists but protected against read access. */ long zchki(name) char *name; { FILE * fptr; long length; if (access(name, 0) != 0) return(-1); if ((fptr = fopen(name, "r")) != NULL) { fseek(fptr, 0L, 2); length = ftell(fptr); close(fptr); return(length); } else return(-1); } /* Z C H K O -- Check if output file can be created */ /* Returns -1 if write permission for the file would be denied, 0 otherwise. */ zchko(name) char *name; { return(0); } /* Z D E L E T -- Delete the named file. */ zdelet(name) char *name; { unlink(name); } /* Z R T O L -- Convert remote filename into local form */ /* * For VRX, this means: * truncating to 8/10 characters * changing lowercase to upper case * changing periods (.) to underscore (_) * If the filename contains an extension of the form: filename.extension * then the parameter "type" is set the file type. If there is no extension, * "type" is set to type DATA. * possible extensions are: * .OBJ - object files * .BIN - binary data file * .CS - Control String file * .PRO - Procedure file * .DAT - default data file * .NCR - NCRL SPUR file * .BAS - BASIC SPUR file * .FB - Fortran/B SPUR file * .FI - Fortran/I SPUR file * .FF - Fortran/F SPUR file * .FV - Fortran/V SPUR file * .N3 - NEAT/3 SPUR file * .NVS - NEAT/VS SPUR file * .NC - NEAT/C SPUR file * .CO - COBOL/0 SPUR file * .CO6 - COBOL/6 SPUR file * .CO7 - COBOL/7 SPUR file * .CO1 - COBOL1/0 SPUR file * .C16 - COBOL1/6 SPUR file * .C17 - COBOL1/7 SPUR file * .C18 - COBOL1/8 SPUR file * .CO4 - COBOL4 SPUR file * .D100 - fixed length data file with 100 byte records * .D1-100 - variable length data file with 1 to 100 byte records */ #define REC_SIZE(ptr) { for(fptr = ((ptr) + 1); *fptr != '\0'; fptr++) {\ if (*fptr == '-') *fptr = '/';\ else if (*fptr < '0' || *fptr > '9') break;\ }\ if (*fptr == '\0') record_sized++;\ } zrtol(name, name2) char *name, *name2; { char *ftype, *subtype, *fptr, *namep, *strrchr(); int suffix_len, i, n, max, record_sized = 0; long stamp; spur_type = 0; suffix = 0; *name2 = '\0'; if (deblog) debug(F100, "funct: zrtol ", "", 0); /* time stamp stderr output */ /* May 4, 1990 */ stamp = time((long *) 0); fprintf(stderr, "\n%s", ctime(&stamp)); fprintf(stderr, "name = <%s>\n", name); if ((ftype = strrchr(name, '.')) == NULL) { strcpy(file_type, "DATAFILE"); /* peg 0190 */ max = 10; } else { suffix_len = strlen(++ftype); for (i = 0; i < 4; i++) { if (i >= suffix_len) n = 0; else n = ftype[i]; suffix = (suffix << 8) | n; } switch (suffix) { case L_OBJECT: case OBJECT: strcpy(file_type, "OBJFILE"); /* peg 0190 */ max = 8; *(ftype - 1) = '\0'; break; case L_BINARY: case BINARY: strcpy(file_type, "DATAFILE"); /* peg 0190 */ max = 10; *(ftype - 1) = '\0'; break; case L_DATA: case DATA: strcpy(file_type, "DATAFILE"); max = 10; *(ftype - 1) = '\0'; break; case L_NCRL: case NCRL: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 1; strcpy(language, "NCRL "); max = 8; *(ftype - 1) = '\0'; break; case L_BASIC: case BASIC: strcmp(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 2; strcpy(language, "BASIC "); max = 8; *(ftype - 1) = '\0'; break; case L_FORTB: case FORTB: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 3; strcpy(language, "FORT/B"); max = 8; *(ftype - 1) = '\0'; break; case L_FORTI: case FORTI: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 4; strcpy(language, "FORT/I"); max = 8; *(ftype - 1) = '\0'; break; case L_FORTF: case FORTF: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 5; strcpy(language, "FORT/F"); max = 8; *(ftype - 1) = '\0'; break; case L_FORTV: case FORTV: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 6; strcpy(language, "FORT/V"); max = 8; *(ftype - 1) = '\0'; break; case L_NEAT3: case NEAT3: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 7; strcpy(language, "NEAT/3"); max = 8; *(ftype - 1) = '\0'; break; case L_NEATVS: case NEATVS: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 8; strcpy(language, "NEATVS"); max = 8; *(ftype - 1) = '\0'; break; case L_NEATC: case NEATC: strcpy(file_type, "SRCFILE"); spur_type = 9; strcpy(language, "NEAT/C"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL: case COBOL: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 10; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL6: case COBOL6: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 11; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL7: case COBOL7: strcmp(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 12; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL8: case COBOL8: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 13; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_CS: case CS: strcpy(file_type, "CSFILE"); /* peg 0190 */ spur_type = 14; strcpy(language, "HEADCS"); max = 8; *(ftype - 1) = '\0'; break; case L_PROC: case PROC: strcpy(file_type, "CSFILE"); /* peg 0190 */ spur_type = 15; strcpy(language, "HEADCS"); max = 8; *(ftype - 1) = '\0'; break; case L_PROCN: case PROCN: strcmp(file_type, "CSFILE"); /* peg 0190 */ spur_type = 16; strcpy(language, "HEADCS"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL1: case COBOL1: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 17; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL16: case COBOL16: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 18; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL17: case COBOL17: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 19; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL18: case COBOL18: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 20; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL4: case COBOL4: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 21; strcpy(language, "COBOL4"); max = 8; *(ftype - 1) = '\0'; break; default: if (*ftype == 'B' || *ftype == 'b') { suffix = BINARY; if (*(ftype + 1) != '\0') REC_SIZE(ftype); if (record_sized) { *(ftype) = '\0'; } } if ((*ftype == 'd') || (*ftype == 'D')) { if (*(ftype + 1) != '\0') REC_SIZE(ftype); if (record_sized) *(ftype) = '\0'; } strcpy(file_type, "DATAFILE"); max = 10; break; } } /* convert periods to underscores, lowercase to uppercase */ namep = name; for (i = 0; *namep != '\0', i < max; namep++, i++) { if (*namep == '.') *namep = '_'; if (*namep == '~') *namep = 'X'; if (*namep == '$') *namep = '_'; else if (islower(*namep) && fncnv) toupper(*namep); } *namep = '\0'; if (record_sized) { /* first the recordsize is truncated now the displayed name contains additional underscores, this fix truncates everything past the FINAL underscore April 13, 1990 */ char *s_tmp; s_tmp = strrchr(name, '_'); if (s_tmp != NULL) *s_tmp = '\0'; sprintf(name2, "%s(NAME=%s,RECORDSIZE=%s)", file_type, name, (ftype + 1)); } else sprintf(name2, "%s(NAME=%s)", file_type, name); if (*file_type == 'S' || *file_type == 'C') zpcrd(name); if (spur_type != 0) fprintf(stderr, "final name2 = <%s> spur_type=%d\n", name2, spur_type); else fprintf(stderr, "final name2 = <%s>\n", name2); if (deblog) debug(F110, "zrtol:", name2, 0); } /* Z L T O R -- Local TO Remote */ /* Convert filename from local format to common (remote) form. */ zltor(name, name2) char *name, *name2; { char work[100], *cp, *pp; int dc = 0; if (deblog) { debug(F100, "funct: zltor ", "", 0); debug(F110, "zltor", name, 0); } pp = work; for (cp = name; *cp != '\0'; cp++) { /* strip path name */ if (*cp == '/') { dc = 0; pp = work; } else if (islower(*cp)) *pp++ = toupper(*cp); /* Uppercase letters */ else if (*cp == '~') *pp++ = 'X'; /* Change tilde to 'X' */ else if (*cp == '#') *pp++ = 'X'; /* Change number sign to 'X' */ /* else if (*cp == '.') *pp++ = '_'; */ /* & extra dots */ else if (*cp == '$') *pp++ = '_'; else *pp++ = *cp; } *pp = '\0'; /* Tie it off. */ cp = name2; /* If nothing before dot, */ if (*work == '.') *cp++ = 'X'; /* insert 'X' */ strcpy(cp, work); if (deblog) debug(F110, "zltor", name2, 0); } /* Z C H D I R -- Change directory */ zchdir(dirnam) char *dirnam; { /* not implemented */ } /* Z H O M E -- Return pointer to user's home directory */ char * zhome() { return("home"); } /* Z G T D I R -- Return pointer to user's current directory */ char * zgtdir() { return("(directory unknown)"); } /* Z X C M D -- Run a system command so its output can be read like a file */ zxcmd(comand) char *comand; { return(0); /* not implemented */ } /* Z C L O S F - wait for the child fork to terminate and close the pipe. */ zclosf() { int wstat; if (deblog) debug(F100, "funct: zclosf ", "", 0); fclose(fp[ZIFILE]); fp[ZIFILE] = fp[ZSYSFN] = NULL; while ((wstat = WAIT(0)) != pid && wstat != -1) ; return(1); } /* Z X P A N D -- Expand a wildcard string into an array of strings */ /* Returns the number of files that match fn1, with data structures set up so that first file (if any) will be returned by the next znext() call. */ zxpand(fn) char *fn; { mtchs[0] = (char *) malloc(sizeof(char)*strlen(fn)); strcpy(mtchs[0], fn); list_count = 1; return(1); } /* Z N E X T -- Get name of next file from list created by zxpand(). */ /* Returns >0 if there's another file, with its name copied into the arg string, or 0 if no more files in list. */ znext(fn) char *fn; { int temp; temp = list_count; if (list_count) list_count = 0; strcpy(fn, mtchs[0]); return(temp); } /* Z N E W N -- Make a new name for the given file */ znewn(fn, s) char *fn, **s; { } /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */ /* * The path structure is used to represent the name to match. * Each slash-separated segment of the name is kept in one * such structure, and they are linked together, to make * traversing the name easier. */ /* * splitpath: * takes a string and splits the slash-separated portions into * a list of path structures. Returns the head of the list. The * structures are allocated by malloc, so they must be freed. * Splitpath is used internally by the filename generator. * * Input: A string. * Returns: A linked list of the slash-separated segments of the input. */ struct path * splitpath(p) char *p; { } /* * fgen: * This is the actual name generator. It is passed a string, * possibly containing wildcards, and an array of character pointers. * It finds all the matching filenames and stores them into the array. * The returned strings are allocated from a static buffer local to * this module (so the caller doesn't have to worry about deallocating * them); this means that successive calls to fgen will wipe out * the results of previous calls. This isn't a problem here * because we process one wildcard string at a time. * * Input: a wildcard string, an array to write names to, the * length of the array. * Returns: the number of matches. The array is filled with filenames * that matched the pattern. If there wasn't enough room in the * array, -1 is returned. * By: Jeff Damens, CUCCA, 1984. */ fgen(pat, resarry, len) /* VRX version, no expansion of file names */ char *pat, *resarry[]; int len; { } /* traverse: * Walks the directory tree looking for matches to its arguments. * The algorithm is, briefly: * If the current pattern segment contains no wildcards, that * segment is added to what we already have. If the name so far * exists, we call ourselves recursively with the next segment * in the pattern string; otherwise, we just return. * * If the current pattern segment contains wildcards, we open the name * we've accumulated so far (assuming it is really a directory), then read * each filename in it, and, if it matches the wildcard pattern segment, add * that filename to what we have so far and call ourselves recursively on the * next segment. * * Finally, when no more pattern segments remain, we add what's accumulated * so far to the result array and increment the number of matches. * * Input: a pattern path list (as generated by splitpath), a string * pointer that points to what we've traversed so far (this * can be initialized to "/" to start the search at the root * directory, or to "./" to start the search at the current * directory), and a string pointer to the end of the string * in the previous argument. * Returns: nothing. */ traverse(pl, sofar, endcur) struct path *pl; char *sofar, *endcur; { } /* * addresult: * Adds a result string to the result array. Increments the number * of matches found, copies the found string into our string * buffer, and puts a pointer to the buffer into the caller's result * array. Our free buffer pointer is updated. If there is no * more room in the caller's array, the number of matches is set to -1. * Input: a result string. * Returns: nothing. */ addresult(str) char *str; { } iswild(str) char *str; { char c; if (deblog) debug(F100, "funct: iswild ", "", 0); while ((c = *str++) != '\0') if (c == '*' || c == '?') return(1); return(0); } /* * match: * pattern matcher. Takes a string and a pattern possibly containing * the wildcard characters '*' and '?'. Returns true if the pattern * matches the string, false otherwise. * by: Jeff Damens, CUCCA * * Input: a string and a wildcard pattern. * Returns: 1 if match, 0 if no match. */ match(pattern, string) char *pattern, *string; { char *psave, *ssave; /* back up pointers for failure */ psave = ssave = NULL; if (deblog) debug(F100, "funct: matck ", "", 0); while (1) { for (; *pattern == *string; pattern++, string++) /* skip first */ if (*string == '\0') return(1); /* end of strings, succeed */ if (*string != '\0' && *pattern == '?') { pattern++; /* '?', let it match */ string++; } else if (*pattern == '*') { /* '*' ... */ psave = ++pattern; /* remember where we saw it */ ssave = string; /* let it match 0 chars */ } else if (ssave != NULL && *ssave != '\0') { /* if not at end */ /* ...have seen a star */ string = ++ssave; /* skip 1 char from string */ pattern = psave; /* and back up pattern */ } else return(0); /* otherwise just fail */ } } /* Z P C R D -- Make a pcard for a CSFILE or a SRCFILE */ zpcrd(name) char *name; { int i; pcard[0] = '\0'; strcat(pcard, "000000"); if ((spur_type == 14) || (spur_type == 15) || (spur_type == 16)) { if (!recv_num && (spur_type == 16)) spur_type = 15; strcat(pcard, "P"); strcat(pcard, name); for (i = 0; i < (10 - strlen(name)); i++) strcat(pcard, " "); strcat(pcard, language); strcat(pcard, " "); switch (spur_type) { case 14: strcat(pcard, " "); break; case 15: strcat(pcard, "PROC-01"); break; case 16: strcat(pcard, "PROC-07"); break; } strcat(pcard, " "); } else { strcat(pcard, " "); strcat(pcard, "P"); strcat(pcard, name); for (i = 0; i < (10 - strlen(name)); i++) strcat(pcard, " "); strcat(pcard, language); strcat(pcard, " "); switch (spur_type) { case 10: strcat(pcard, "0"); break; case 11: strcat(pcard, "6"); break; case 12: strcat(pcard, "7"); break; default: strcat(pcard, " "); break; } strcat(pcard, " "); } } /* Z S R E C I -- Gather SPUR records for input */ zsreci(n) int n; { char idfield[MAX_FIELD+2]; char line[LINE_LEN]; char tail[TAIL_LEN]; char oldnum[10]; int id_start = spur_info[MAX_SPURTYPE*ID_START + spur_type -1]; int id_len = spur_info[MAX_SPURTYPE*ID_LEN + spur_type -1]; int rec_len = spur_info[MAX_SPURTYPE*REC_LEN + spur_type -1]; int num_field_len = spur_info[MAX_SPURTYPE*NUM_FIELD_LEN + spur_type -1]; int spaces; int length; int i; if (deblog) debug(F111, "zsreci: ", "n", n); /**************************************************************** * Initialize the array 'spur_data' and begin to add to this * * array the "V-Kermit-prepared" records from the file fp[n]. * ****************************************************************/ spur_data[0] = '\0'; while (strlen(spur_data) < 315) { if ((spaces = fgetc(fp[n])) == EOF) { if (deblog) fprintf(stderr, "zsreci: fgetc == EOF\n"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (fgets(line, LINE_LEN, fp[n]) == NULL) { errhdlr("zsreci / NULL"); fprintf(stderr, "zsreci: fgets == NULL\n"); return(-1); } if (lenchk(line, n)) { switch (spur_type) { case 9: case 11: { errhdlr("zsreci"); fprintf(stderr, "reading line > %d char\n", SRCLNLEN+1); fprintf(stderr, "line length was %d\n", strlen(line)); fprintf(stderr, "%s\n", line); return(-1); } default: { errhdlr("zsreci"); fprintf(stderr, "reading line > %d char\n", SRCLNLEN); fprintf(stderr, "line length was %d\n", strlen(line)); fprintf(stderr, "%s\n", line); return(-1); } } } if (strncmp(line, "000000", 6) == 0) { if (deblog) fprintf(stderr, "zsreci: Throwing away Pcard.\n"); /* throw away the Pcard */ continue; } /**************************************************************** * If we get this far, a record was successfully read from the * * file pointer fp[n]. * ****************************************************************/ length = rec_len - spaces; if (deblog) { debug(F111, " ", "record length", length); debug(F111, " ", "id start", id_start); debug(F111, " ", "id len", id_len); } /**************************************************************** * If the file has an id field (i.e. id_start != 0), then * * copy it into 'idfield' and let 'tail' point to the rest * * of the record after the id field. If there is no id field, * * let 'tail' point at the remaining record after the line * * number field. * ****************************************************************/ if (id_start) { strncpy(idfield, &line[id_start], id_len); strcpy(tail, &line[id_start+id_len]); if (deblog) debug(F111, " id field", idfield, 0); } else { strcpy(tail, &line[HEAD_END]); } if (deblog) debug(F110, " tail", tail, 0); /**************************************************************** * If !send_addnum && ...... * * send_num && !send_renum - use the first six * * characters of the * * record. * * send_num && send_renum - replace the first six * * characters of the * * record with a multi- * * ple of INCREMENT. * * !send_num - do not use the first * * six characters of the * * record. * * send_addnum - Add a multiple * ****************************************************************/ if (!send_addnum) { if (send_num) { if (send_renum) { sprintf(line, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(line, " "); linenumber += INCREMENT; } else { line[HEAD_END] = '\0'; } } else { line[0] = '\0'; } } else { strncpy(oldnum, line, HEAD_END); sprintf(line, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(line, " "); linenumber += INCREMENT; strncat(line, oldnum, HEAD_END); length += 6; } if (deblog) debug(F110, " line number", line, 0); /**************************************************************** * Add the data to the line. * ****************************************************************/ strcat(line, tail); /**************************************************************** * If sending the id field, pad the line with spaces and add * * the id field to the end of the line. * ****************************************************************/ if (send_id) { for (i = length - 6 + ((send_addnum || send_num) *6); i < (80 - id_len); i++) line[i] = ' '; line[80-id_len] = '\0'; idfield[id_len] = '\n'; idfield[id_len+1] = '\0'; strcat(line, idfield); } else { line[length-6+((send_addnum || send_num)*6)] = '\n'; line[length-6+((send_addnum || send_num)*6)+1] = 0; } strcat(spur_data, line); } return(1); } /* Z S R E C O -- Prepare data to output into SPUR records */ zsreco(n) int n; { int id_start = spur_info[MAX_SPURTYPE*ID_START + spur_type - 1]; int id_len = spur_info[MAX_SPURTYPE*ID_LEN + spur_type - 1]; int num_field_len = spur_info[MAX_SPURTYPE*NUM_FIELD_LEN+spur_type-1]; char idfield[10]; char linefield[8]; char record[100]; char data[DATA_LEN]; char temp[DATA_LEN]; int number_len, i, len_char, nulls, data_len = strlen(spur_data); /**************************************************************** * Get id field at the end of the line if there is one. * * If the spur_type has an id field and there are no characters * * in columns (80 - id_len) to 80, the new id field will be * * spaces. If recv_id = 0, the new id field will be spaces. * ****************************************************************/ if (deblog) { debug(F111, "zsreco: ", "n", n); debug(F111, " ", "data length", data_len); debug(F111, " ", "id start", id_start); debug(F111, " ", "id len", id_len); } if (id_start) { if ((data_len > 72) && recv_id) { strncpy(idfield, &spur_data[80-id_len], id_len); if ((i = strlen(idfield)) < id_len) { for (; i < id_len; i++) idfield[i] = ' '; } idfield[id_len] = '\0'; } else { for (i = 0; i < id_len; i++) idfield[i] = ' '; idfield[id_len] = '\0'; } spur_data[80-id_len] = '\0'; if (data_len > 6) strncpy(data, &spur_data[NUM_LEN], 80); else data[0] = '\0'; } else { idfield[0] = '\0'; if (data_len > 6) strcpy(data, &spur_data[NUM_LEN]); else data[0] = '\0'; } if (deblog) debug(F110, " id field", idfield, 0); /********************************************************************** * If => !recv_addnum && ..... * * recv_num && !recv_renum - Keep the original first six * * columns from the incoming * * record. * * recv_num && recv_renum - Replace the first six columns * * with linenumber and increment * * by the constant INCREMENT. * * !recv_num - Replace the first six columns * * with spaces. (ASCII 0x20) * * recv_addnum - Insert new line numbers at * * the beginning of every new * **********************************************************************/ linefield[0] = '\0'; if (recv_num && !recv_addnum) { if (recv_renum) { sprintf(linefield, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(linefield, " "); linenumber += INCREMENT; } else { strncpy(linefield, spur_data, NUM_LEN); if ((i = strlen(linefield)) < 6) { for (; i < 6; i++) strcat(linefield, " "); } linefield[NUM_LEN] = 0; } } else if (recv_addnum) { sprintf(linefield, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(linefield, " "); linenumber += INCREMENT; strncpy(temp, spur_data, NUM_LEN); temp[NUM_LEN] = '\0'; strcat(temp, data); strcpy(data, temp); } if (deblog) { debug(F110, " line number", linefield, 0); debug(F110, " data", data, 0); } /********************************************************************** * peel off the spaces at the end of the remaining data unless we * * have a Control String or a Procedure file (spur_type=14,15,16) * **********************************************************************/ if ((spur_type == 14) || (spur_type == 15) || (spur_type == 16)) { i = strlen(data); for (; i < (80 - (6 * recv_num)); i++) data[i] = ' '; data[i] = '\0'; len_char = 0; } else { i = strlen(data); while (i && (data[i-1] == ' ')) i--; data[i] = '\0'; if ((!recv_num) && ((i = strlen(data)) < 6)) { for (; i < 6; i++) strcat(data, " "); } if (recv_num || recv_addnum) number_len = 6; else number_len = 0; len_char = 80 - id_len - strlen(data) - number_len; if (deblog) fprintf(stderr, "zsreco: len_char = %d.\n", len_char); /**************************************************************** * The following must be done since we can not output the ASCII * * characters 0x09 and 0x0a * ****************************************************************/ if (len_char == 9) { if (deblog) fprintf(stderr, "zsreco: app 1 (0x20) on rec end.\n"); strcat(data, " "); len_char = 8; if (deblog) fprintf(stderr, "zsreco: len_char is now %d.\n", len_char); } if (len_char == 10) { if (deblog) fprintf(stderr, "zsreco: app 2 (0x20) on rec end.\n"); strcat(data, " "); len_char = 8; if (deblog) fprintf(stderr, "zsreco: len_char is now %d.\n", len_char); } } /* output the space character to column 1 */ fputc(len_char, fp[n]); if (ferror(fp[n]) != 0) { errhdlr("zsrceo"); fprintf(stderr, "write error: zsrceo len_char\n"); return(-1); } /* build the record and output it */ record[0] = '\0'; if (recv_num || recv_addnum) strcat(record, linefield); else strncat(record, data, NUM_LEN); switch (spur_type) { case 9: case 11: nulls = 2; break; case 12: nulls = 1; break; default: nulls = 0; } for (i = 0; i < nulls; i++) strcat(record, " "); strcat(record, idfield); if (recv_num || recv_addnum) strcat(record, data); else strcat(record, &data[NUM_LEN]); return(zsoutl(n, record)); } /* E R R H D L R - errhdlr for all unpleasant outcomes PEG May 14, 1990 */ void errhdlr(wherefrm) char *wherefrm; { char s[90]; long errclk; int geterr = errno; /* we grab the error number due the timestamp fprintf setting errno to EMINR May 22, 1990 */ /* time stamp stderr output */ /* May 4, 1990 */ errclk = time((long *) 0); fprintf(stderr, "\n%s", ctime(&errclk)); /* we do not want to print anymore EMINR messages */ if ((geterr) && (geterr != EMINR)) { sprintf(s, "%s: %s", wherefrm, sys_errlist[geterr]); perror(wherefrm); if (!server) screen(SCR_EM, 0, 0l, s); else errpkt(s); errno = 0; return; } else { sprintf(s, "Error occured: %s", wherefrm); fprintf(stderr, "%s\n", s); if (!server) screen(SCR_EM, 0, 0l, s); else errpkt(s); errno = 0; return; } } /* errhdlr end */ /* L E N C H K - lenchk: checks spur records after read or before right to verify that they do not exceed maximum values defined by SRCLNLEN */ int lenchk(s, n) char *s; /* string ptr for examing line length */ int n; /* file number... index into fp[] */ { if ((n != ZIFILE && n != ZOFILE) || binary) return(0); if ((*file_type == 'C') || (*file_type == 'S')) { switch (spur_type) { case 9: case 11: { if (strlen(s) > SRCLNLEN + 1) return (-1); else return(0); } default: { if (strlen(s) > SRCLNLEN) return (-1); else return(0); } } } else return(0); } /* end lenchk */ /* R E S E T O P E N resetopen: closes ZOFILE or ZIFILE left open from previous aborted file transfers May 30, 1990 */ void resetopen() { int n; if ((fp[ZOFILE] == NULL) && (fp[ZIFILE] == NULL)) return; if (fp[ZOFILE] != NULL) n = ZOFILE; else n = ZIFILE; if (objopen) { /* March 12, 1990 */ if (voclose(n) == 0) { if ((!keep) && (n == ZOFILE)) { if (unlink(fn_temp) != 0) { errhdlr("resetopen UNLINK"); fprintf(stderr, "unlink failed %s\n", fn_temp); } } } objopen = CLOSE; } else { if (fclose(fp[n]) == EOF) { errhdlr("resetopen fclose error"); fprintf(stderr,"file name: %s\n",fn_temp); } if ((!keep) && (n == ZOFILE)) if (unlink(fn_temp) != 0) { errhdlr("resetopen UNLINK"); fprintf(stderr, "unlink failed %s\n", fn_temp); } } strcpy(fn_temp, "\0"); fp[n] = NULL; return; }