/* * scopy * * Replace the named files with identical copies such that the * replacement file has "vanilla RMS" file attributes. * The -a option cleans up random ascii. * */ /*)BUILD */ #ifdef DOCUMENTATION title scopy Make file standard RMS index Make file standard RMS synopsis scopy [-a] file_list description Scopy creates an identical copy of the named input files (the file_list may contain wild cards), creating output files with standard file attributes (record type = variable length, record format = implied carriage control). If there are no arguments, scopy prompts for the option and then for each file. If the -a option is given, scopy will "clean up" the input line, removing extraneous carriage returns and other junk. diagnostics Scopy does not run on RSTS, RT11, or Unix as these operating systems do not support multiple versions of the same file. author Martin Minow bugs #endif #include #define FALSE 0 #define TRUE 1 #define EOS 0 #ifndef nomacarg #include #endif #ifdef tolower #undef tolower #endif static int verbose = TRUE; static char filename[81]; /* Just file name */ static char text[81]; /* Work buffer for interactive */ static char record[2048 + 1]; /* Work buffer for file copy */ static FILE *infd; static FILE *outfd; static int aflag = FALSE; /* True to clean up ascii */ #ifdef vms /* * This creates files in vanilla RMS on VMS (VAX-11C) */ #define CREATE(f, m) fdopen(creat(f, 0, "rat=cr", "rfm=var"), m) #else #define CREATE fopen #endif main(argc, argv) int argc; char *argv[]; { register int c; register int i; register char *ap; /* * scopy will overwrite files if there are no version numbers */ #ifdef unix fprintf(stderr, "This program must not be used on Unix\n"); exit(2); #endif #ifdef rt11 fprintf(stderr, "This program must not be used on RT11\n"); exit(IO_ERROR); #endif #ifdef rsx extern int $$rsts; if ($$rsts) { fprintf(stderr, "This program must not be used on RSTS/E\n"); exit(IO_ERROR); } #endif if (argc <= 1) { interactive(); } else { for (i = 1; i < argc; i++) { if (*(ap = argv[i]) == '-') { while ((c = tolower(*++ap)) != 0) { switch (c) { case 'a': aflag++; break; default: fprintf(stderr, "Unknown option '%c', ignored\n", *ap); break; } } argv[i] = NULL; } } for (i = 1; i < argc; i++) { if (argv[i] != NULL) { dofiles(argv[i]); } } } } interactive() /* * Prompt for files to do */ { register char *tp; fprintf(stderr, "Replace file by an identical copy, changing output\n"); fprintf(stderr, "file attributes to variable-length, implied carriage control\n"); fprintf(stderr, "File names may contain wild-cards\n"); if (!aflag) { for (;;) { fprintf(stderr, "Clear out extraneous junk characters (Yes/No) ? "); fflush(stderr); if (gets(text) == NULL) return; if (match(text, "yes")) { aflag = TRUE; break; } else if (text[0] == EOS || match(text, "no")) { aflag = FALSE; break; } else { fprintf(stderr, "Can't understand \"%s\", please answer Yes or No\n", text); } } } while (!feof(stdin)) { fprintf(stderr, "File: "); fflush(stderr); gets(text); if (feof(stdin)) break; if (text[0] != EOS) dofiles(text); } } dofiles(wildname) char *wildname; /* * Do all files for this wild_card argument */ { register int nfiles; register long nrecords; extern char *readrecord(); if ((infd = fwild(wildname, "r")) == NULL) { fprintf(stderr, "Illegal (wild-card) file name: \"%s\"\n", wildname); return; } for (nfiles = 0; fnext(infd) != NULL; nfiles++) { setname(infd); if ((outfd = CREATE(filename, "w")) == NULL) { perror(filename); continue; } nrecords = 0; while (readrecord(infd) != NULL) { nrecords++; cleanup(aflag); fputs(record, outfd); } if (ferror(infd) || ferror(outfd)) { perror(filename); } fclose(outfd); if (verbose) { printf("%8ld records: %s\n", nrecords, filename); } } if (nfiles == 0) { fprintf(stderr, "No files matching \"%s\"\n", wildname); } } char * readrecord(fd) register FILE *fd; /* * Read a line, watch out for garbage. */ { register char *rp; register int c; if (feof(fd)) return (NULL); for (rp = record; (c = getc(fd)) != EOF;) { if ((c &= 0177) == 0 || c == 0177) continue; *rp++ = c; if (c == '\n' || rp >= &record[(sizeof record) - 1]) break; } *rp = EOS; return (record); } cleanup(flag) int flag; /* TRUE if all junk goes */ /* * Remove junk from the record */ { register char *ip; register char *op; register int c; for (ip = op = record; ((c = *ip++) & 0177) != EOS;) { if (c < ' ') { switch (c) { case '\f': case '\b': case '\t': case '\n': case '\007': /* BELL */ break; case '\r': if (*ip == '\n') continue; /* Ignore in */ else break; /* Accept if naked */ default: if (flag) continue; /* Flag set? Ignore controls */ else break; /* Flag clear? Keep controls */ } } else if (c == 0177) /* Drop rubout */ continue; *op++ = c; /* Keep the character */ } *op = EOS; } setname(fd) FILE *fd; /* * Put output file name into filename buffer */ { register char *ptr; fgetname(fd, filename); if ((ptr = strchr(filename, ';')) != NULL) *ptr = EOS; /* Remove version number */ } int match(arg, value) register char *arg; register char *value; /* * Return TRUE if arg matches leftmost part of value. * Value must be in lowercase. */ { register char c; while ((c = tolower(*arg++)) != EOS) { if (c != *value++) return (FALSE); } return (TRUE); } #ifdef unix int tolower(c) register int c; /* * Incorrect on Venix */ { return (isupper(c) ? c + ('a' - 'A') ? c); } #endif bug(severity, mess, arg) char *severity; char *mess; char *arg; /* * Error messages */ { fprintf(stderr, "?SCAT-%s-%s", severity, mess); if (arg != NULL) fprintf(stderr, ": \"%s\"", arg); fprintf(stderr, "\n"); if (*severity != 'W') error("?SCAT-F-Can't continue"); }