joemu@nscpdc.NSC.COM (Joe Mueller) (12/19/86)
The following is a utility that I wrote to update my C workbench disk whenever Commodore would update my operating system software. It can be used to create a new disk as well. It differs from the update command that Commodore provides in that it can strip C header files of comments and unnecessary whitespace. It compiles under lattice C with a simple cc -o update myupdate.c #!/bin/sh-----cut here-----cut here-----cut here-----cut here----- # shar: Shell Archiver # Run the following text with /bin/sh to create: # myupdate.c # myupdate.doc echo shar: extracting myupdate.c cat - << \SHAR_EOF > myupdate.c /* * myupdate.c * (C) 1986 Software Solution, all rights reserved */ /* Myupdate is patterned after the Commodore update command. It takes as * its arguments a source directory and a destination directory. By default * it acts just like the update command, if the file exists in both the * source and destination directories, the file from the source directory is * copied to the destination directory. The program does not pay attention * to file dates. If the -c flag is used, the program will copy all files * from the source directory to the destination directory without checking * to see if the file exists in the destination directory. If the -s flag * is specified the files in the source directory are stripped of excess * whitespace as they are copied to the destination directory. Files in the * source directory are unmodified. This option is intended for use when * updating the include header files in a C development disk. The -i flag * is used to have the program inquire before updating each file. The -v * flag is the verbose flag and causes the program to print out the name * of each file as it's processed. * * Bug reports or suggestions should be sent to: * The Software Solution * 16850 S.W. Timberland Dr. * Aloha, Oregon 97007 */ #include <stdio.h> #include "libraries/dos.h" #include "libraries/dosextens.h" #include "exec/memory.h" extern struct FileLock *Lock(), *CurrentDir(), *CreateDir(); extern struct FileHandle *Open(); void update(), do_update(), strip(), copy(); struct FileLock *src_dir_lock; /* Lock on source dir */ struct FileLock *dst_dir_lock; /* Lock on destination dir */ int s_flag = 0; /* strip files of comments and excess white space */ int c_flag = 0; /* create files if they don't exist in dest dir */ int i_flag = 0; /* inquire for each file before action is taken */ int v_flag = 0; /* verbose mode */ struct file_info { struct FileHandle *fh; unsigned char buf[BUFSIZ]; unsigned char *bp, *endp; int mode; }; /* input and output file information */ struct file_info *myopen(); void myclose(); char *myname; /* name by which this command has been called i.e."myupdate" */ main(argc, argv) int argc; char *argv[]; { int i, j; char *srcdir, *dstdir; /* source and destination directory names */ struct InfoData *src_id, *dst_id; struct FileLock *startlock; /* lock on the current directory */ myname = argv[0]; if(argc < 3) { goto usage; } /* parse the arguments, and get source and destination directory */ i = 1; while (i < (argc - 2)) { /* last two arguments are src and dst dirs */ if (argv[i][0] == '-') { /* option */ j = 1; /* start past the "-" character */ while (argv[i][j]) { switch (argv[i][j++]) { case 'c': case 'C': c_flag++; /* copy all files */ break; case 's': case 'S': s_flag++; /* strip whitespace */ break; case 'v': case 'V': v_flag++; /* verbose mode */ break; case 'i': case 'I': i_flag++; /* inquire first */ break; default: goto usage; } } } else { /* screw up */ goto usage; } i++; } srcdir = argv[i]; dstdir = argv[i+1]; /* Get a lock on the source directory */ src_dir_lock = Lock(srcdir,ACCESS_READ); dst_dir_lock = Lock(dstdir,ACCESS_WRITE); if (src_dir_lock == NULL) { fprintf(stderr,"%s: unable to lock %s\n",myname,srcdir); exit(1); } if (dst_dir_lock == NULL) { fprintf(stderr,"%s: unable to lock %s\n",myname,dstdir); UnLock(src_dir_lock); exit(1); } /* Move into source directory and save current directory for later */ startlock = CurrentDir(src_dir_lock); /* InfoData MUST BE LONGWORD ALIGNED, so allocate it */ src_id = (struct InfoData *)AllocMem(sizeof(struct InfoData),MEMF_CLEAR); dst_id = (struct InfoData *)AllocMem(sizeof(struct InfoData),MEMF_CLEAR); if (src_id != NULL) { /* Get info to see if disk is write protected */ if (Info(src_dir_lock, src_id)) { if (src_id->id_DiskType == ID_NO_DISK_PRESENT || src_id->id_DiskType == ID_UNREADABLE_DISK) { fprintf(stderr,"%s: unable to access %s\n",myname,srcdir); UnLock(src_dir_lock); UnLock(dst_dir_lock); dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); if (dst_id != NULL) { FreeMem(dst_id, sizeof(struct InfoData)); } exit(1); } } else { fprintf(stderr,"%s: unable to get info about %s\n",myname,srcdir); UnLock(src_dir_lock); UnLock(dst_dir_lock); dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); if (dst_id != NULL) { FreeMem(dst_id, sizeof(struct InfoData)); } exit(1); } } else { fprintf(stderr,"%s: unable to allocate memory for diskinfo\n",myname); UnLock(src_dir_lock); UnLock(dst_dir_lock); dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); if (dst_id != NULL) { FreeMem(dst_id, sizeof(struct InfoData)); } exit (1); } if (dst_id != NULL) { if (Info(dst_dir_lock, dst_id)) { if(dst_id->id_DiskState == ID_WRITE_PROTECTED) { fprintf(stderr,"%s: %s is write protected\n",myname,dstdir); UnLock(src_dir_lock); UnLock(dst_dir_lock); dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); FreeMem(dst_id, sizeof(struct InfoData)); exit(1); } } else { fprintf(stderr,"%s: unable to get info about %s\n",myname,dstdir); UnLock(src_dir_lock); UnLock(dst_dir_lock); dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); FreeMem(dst_id, sizeof(struct InfoData)); exit(1); } } else { fprintf(stderr,"%s: unable to allocate memory for diskinfo\n",myname); UnLock(src_dir_lock); UnLock(dst_dir_lock); dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); exit (1); } update(src_dir_lock, dst_dir_lock); /* do the actual work */ UnLock(src_dir_lock); UnLock(dst_dir_lock); /* put current directory back to where it was */ dst_dir_lock = CurrentDir(startlock); FreeMem(src_id, sizeof(struct InfoData)); FreeMem(dst_id, sizeof(struct InfoData)); exit (0); usage: fprintf(stderr,"%s: usage %s [-c] [-i] [-s] [-v] source destination\n", argv[0], argv[0]); exit (1); } void update(sl, dl) register struct FileLock *sl; register struct FileLock *dl; /* source and destination file locks */ { register struct FileInfoBlock *fib; register struct FileLock *nsl, *ndl; /* new source and destination locks for subdirectories */ fib = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR); if (fib == NULL) { fprintf(stderr,"%s: unable to allocate space for fileinfo block\n",myname); return; } if (Examine(sl,fib)) { /* take a look at the source directory */ while (ExNext(sl, fib)) { /* found a file or directory */ if (fib->fib_DirEntryType > 0) { /* found a subdirectory */ nsl = Lock(fib->fib_FileName, ACCESS_READ); if (nsl == NULL) { fprintf(stderr,"%s: unable to lock %s\n", myname, fib->fib_FileName); continue; } CurrentDir(dl); /* change dirs to destination */ ndl = Lock(fib->fib_FileName, ACCESS_WRITE); if (ndl == 0) { ndl = CreateDir(fib->fib_FileName); } if (v_flag) fprintf(stdout,"Changing directories to %s\n", fib->fib_FileName); CurrentDir(nsl); if (ndl) update(nsl, ndl); /* recurse */ CurrentDir(sl); /* change back to original source lock */ UnLock(nsl); if (ndl) { UnLock(ndl); } else fprintf(stderr,"%s: unable to create %s\n", myname, fib->fib_FileName); } else { /* normal file */ if (c_flag || exists(dl,fib->fib_FileName)) do_update(sl,dl,fib->fib_FileName); } } FreeMem(fib, sizeof(struct FileInfoBlock)); return; } } /* * exists returns nonzero if file named fn exists in directory locked by dl */ exists(dl, fn) struct FileLock *dl; char *fn; { struct FileLock *ol, *tl; int retval; ol = CurrentDir(dl); tl = Lock(fn, ACCESS_READ); if (tl) retval = 1; else retval = 0; if (tl) { UnLock(tl); } CurrentDir(ol); /* change back directory */ return retval; } void do_update (sl,dl,fn) struct FileLock *sl, *dl; /* source and destination file locks */ char *fn; /* name of file in question */ { int c; struct file_info *ifi, *ofi; struct FileLock *ofl; if (i_flag) { fprintf(stdout,"Update %s? (y/n)...", fn); c = getchar(); if (c != 'y' && c != 'Y') return; } if (v_flag) { fprintf(stdout," %s\n",fn); } ofl = CurrentDir(sl); ifi = myopen(fn, MODE_OLDFILE); if (ifi == NULL) { fprintf(stderr, "%s: unable to open %s for reading\n", myname, fn); CurrentDir(ofl); return; } CurrentDir(dl); ofi = myopen(fn, MODE_NEWFILE); if (ofi == NULL) { fprintf(stderr, "%s: unable to open %s for writing\n", myname, fn); myclose(ifi); CurrentDir(ofl); return; } if (s_flag) strip(ifi, ofi); else copy(ifi, ofi); myclose(ifi); myclose(ofi); } void strip(ifi, ofi) register struct file_info *ifi, *ofi; { register int c, in_comment, doing_white, non_white_found; in_comment = 0; doing_white = 0; non_white_found = 0; while ((c = mygetc(ifi)) != EOF) { if (in_comment) { chk_com: if (c == '*') { c = mygetc(ifi); if (c == '/') { in_comment = 0; if (!doing_white) { /* convert comment to one white space */ if (myputc(' ', ofi) == EOF) { return; } doing_white = 1; } continue; } else goto chk_com; } else continue; } if (c == '/') { c = mygetc(ifi); if (c == '*') { in_comment = 1; continue; } if(myputc('/', ofi) == EOF) { return; } if (c == EOF) break; } if (isspace(c)) { if (c == '\n') { if (non_white_found) if (myputc('\n', ofi) == EOF) { return; } doing_white = 1; non_white_found = 0; continue; } if (doing_white) continue; else { /* colapse white space to single char */ if (myputc(' ', ofi) == EOF) { return; } doing_white = 1; continue; } } else { doing_white = 0; non_white_found = 1; } if (myputc(c, ofi) == EOF) { return; } } } void copy(ifi, ofi) register struct file_info *ifi, *ofi; { register int c; while ((c = mygetc(ifi)) != EOF) { if (myputc(c,ofi) == EOF) { fprintf(stderr,"%s: file I/O error\n", myname); return; } } } struct file_info * myopen(name,mode) char *name; int mode; { register struct file_info *fi; fi = (struct file_info *)AllocMem(sizeof(struct file_info),MEMF_CLEAR); if (fi == NULL) return NULL; fi->fh = Open(name,mode); if (fi->fh == 0) { FreeMem(fi, sizeof(struct file_info)); return NULL; } fi->mode = mode; fi->bp = fi->buf; fi->endp = fi->buf; return fi; } void myclose(fi) register struct file_info *fi; { if (fi->mode == MODE_NEWFILE) { /* open for writing? */ if (fi->bp > fi->buf) /* flush any buffers */ Write(fi->fh, fi->buf, fi->bp - fi->buf); } Close(fi->fh); FreeMem(fi, sizeof(struct file_info)); } int mygetc(fi) register struct file_info *fi; { int actual; if (fi->bp >= fi->endp) { actual = Read(fi->fh, fi->buf, BUFSIZ); fi->bp = fi->buf; fi->endp = fi->buf + actual; if (actual == 0) return EOF; if (actual > 0) return ((int)*fi->bp++); else { fprintf(stderr,"%s: input error %d\n", myname, IoErr()); return EOF; } } return ((int)*fi->bp++); } int myputc(c, fi) int c; register struct file_info *fi; { int actual; *(fi->bp++) = c; if (fi->bp >= fi->buf + BUFSIZ) { actual = Write(fi->fh, fi->buf,BUFSIZ); fi->bp = fi->buf; } if (actual < BUFSIZ) { if (actual == -1) fprintf(stderr,"%s: output error %d\n", myname, IoErr()); else fprintf(stderr,"%s: short write, actual = %d, error %d\n", myname, actual, IoErr()); return EOF; } else return c; } SHAR_EOF echo shar: extracting myupdate.doc cat - << \SHAR_EOF > myupdate.doc Format: MYUPDATE [-C][-I][-S][-V] <source> <destination> Template: MYUPDATE "-C/S,-I/S,-S/S,-V/S,SOURCE/A,DESTINATION/A" Purpose: To update workbench disks with system software Specification: MYUPDATE without any switches will copy a file from the source directory to the destination directory only if the file exists in the destination directory. It is designed to update software within a workbench disk without increasing the number of existing files on customized workbench disks. If the -C switch is used, the command will copy files from the source to the destination directories without checking for the existence of the destination file. If the -I switch is used, the command will run in interactive mode and query you before each file is updated. If the -S switch is used the file will be stripped of unnecessary whitespace as it is copied to the destination directory. Its primary use is for updating and stripping C language include files. The -V switch is used to put the command into verbose mode and notify you as each file is updated. All the switches may be used together or separately to achieve the desired effects. Examples: MYUPDATE df1:c df0:c updates files that exist in df0:c with files from df1:c. MYUPDATE -c -s -v df1:include df0:include or MYUPDATE -csv df1:include df0:include copies and strips files from df1:include to df0:include without checking for the existence of the destination file. The command will notify you as each file is processed. SHAR_EOF