home *** CD-ROM | disk | FTP | other *** search
- /*
- filterfile.c: Pipe a file through a filter into another file.
-
- This program is an obnoxious example of how to check return codes.
- */
-
- static char filterfileauthor[] =
- "filterfile was written by Daniel J. Bernstein.\n\
- Internet address: brnstnd@acf10.nyu.edu.\n";
-
- static char filterfileversion[] =
- "filterfile version 1.201, October 28, 1989.\n\
- Copyright (c) 1989, Daniel J. Bernstein.\n\
- All rights reserved.\n";
-
- static char filterfilecopyright[] =
- "filterfile version 1.201, October 28, 1989.\n\
- Copyright (c) 1989, Daniel J. Bernstein.\n\
- All rights reserved.\n\
- \n\
- You are granted the following rights: A. To make copies of this work in\n\
- original form, so long as (1) the copies are exact and complete; (2) the\n\
- copies include the copyright notice, this paragraph, and the disclaimer\n\
- of warranty in their entirety. B. To distribute this work, or copies made\n\
- under the provisions above, so long as (1) this is the original work and\n\
- not a derivative form; (2) you do not charge a fee for copying or for\n\
- distribution; (3) you ensure that the distributed form includes the\n\
- copyright notice, this paragraph, and the disclaimer of warranty in their\n\
- entirety. These rights are temporary and revocable upon written, oral, or\n\
- other notice by Daniel J. Bernstein. This copyright notice shall be\n\
- governed by the laws of the state of New York.\n\
- \n\
- If you have questions about filterfile or about this copyright notice,\n\
- or if you would like additional rights beyond those granted above,\n\
- please feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- on the Internet.\n";
-
- static char filterfilewarranty[] =
- "To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
- all warranties, explicit or implied, including but not limited to the\n\
- implied warranties of merchantability and fitness for a particular purpose.\n\
- Daniel J. Bernstein is not and shall not be liable for any damages,\n\
- incidental or consequential, arising from the use of this program, even\n\
- if you inform him of the possibility of such damages. This disclaimer\n\
- shall be governed by the laws of the state of New York.\n\
- \n\
- In other words, use this program at your own risk.\n\
- \n\
- If you have questions about filterfile or about this disclaimer of warranty,\n\
- please feel free to contact the author at brnstnd@acf10.nyu.edu\n\
- on the Internet.\n";
-
- static char filterfileusage[] =
- "Usage: filterfile [ -dDpPtTACHUVW ] [ -oout ] [ -eext ]\n\
- file /path/filter [ arg ... ]\n\
- Help: filterfile -H\n";
-
- static char filterfilehelp[] =
- "filterfile applies a filter to a file, placing the output in a new file.\n\
- \n\
- filterfile -A: print authorship notice\n\
- filterfile -C: print copyright notice\n\
- filterfile -H: print this notice\n\
- filterfile -U: print short usage summary\n\
- filterfile -V: print version number\n\
- filterfile -W: print disclaimer of warranty\n\
- \n\
- filterfile [ -dDpPtT ] [ -oout ] [ -eext ]\n\
- file /path/filter [ arg ... ]: apply filter to file\n\
- -d: delete input file\n\
- -D: do not delete input file (default)\n\
- -p: preserve protection of file\n\
- -P: do not preserve protection of file (default)\n\
- -t: preserve access and modification times of file\n\
- -T: do not preserve times (default)\n\
- -eext: sent output to file.ext, or if ext begins with . remove it from name\n\
- -oout: send output to out (overrides -e)\n\
- \n\
- If you have questions about or suggestions for filterfile, please feel free\n\
- to contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu\n\
- on the Internet.\n";
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/file.h>
- #ifdef BSD
- #include <limits.h>
- #endif
- #include <sys/wait.h>
- #include <sys/time.h>
-
- extern char *getenv();
- extern char *malloc();
-
- int flagdelete = 0;
- int flagprotect = 0;
- int flagtimes = 0;
-
- int flagunappend = 0;
-
- char *fnout = 0;
- char *fnin = 0;
- char **filter = 0;
- char *fnappend = 0;
-
- main(argc,argv,envp)
- int argc;
- char *argv[];
- char *envp[];
- {
- char *s;
- int f;
- int fdin;
- int fdout;
- union wait wstat;
- struct stat stinold;
- struct stat stoutold;
- struct stat stin;
- struct stat stout;
- struct timeval tvp[2];
-
- fnappend = getenv("FILTERFILEEXT");
-
- while (*(++argv))
- if (**argv == '-')
- while (*(++(*argv)))
- switch(**argv)
- {
- case 'd': flagdelete = 1; break;
- case 'D': flagdelete = 0; break;
- case 'p': flagprotect = 1; break;
- case 'P': flagprotect = 0; break;
- case 't': flagtimes = 1; break;
- case 'T': flagtimes = 0; break;
- case 'e': fnappend = *argv + 1;
- while (*(++(*argv))) /* null */ ;
- --(*argv); break; /* we really want breakbreak here */
- case 'o': fnout = *argv + 1;
- while (*(++(*argv))) /* null */ ;
- --(*argv); break; /* we really want breakbreak here */
- case 'A': printf(filterfileauthor); exit(0);
- case 'C': printf(filterfilecopyright); exit(0);
- case 'V': printf(filterfileversion); exit(0);
- case 'W': printf(filterfilewarranty); exit(0);
- case 'H': printf(filterfilehelp); exit(0);
- case 'U': printf(filterfileusage); exit(0);
- default: ;
- }
- else
- if (fnin == 0)
- fnin = *argv;
- else
- if (filter == 0)
- {
- filter = argv;
- break;
- }
-
- if ((fnin == 0) || (filter == 0))
- {
- printf(filterfileusage); exit(1);
- }
- if (fnout == 0)
- {
- flagunappend = (*fnappend == '.');
- for (s = fnappend;*s;s++)
- if (*s == '/')
- *s = '.';
- fnout = malloc((unsigned) (strlen(fnin) + strlen(fnappend) + 2));
- if (fnout == 0)
- {
- fprintf(stderr,"filterfile: fatal: cannot create output file name: \
- out of memory\n");
- exit(1);
- }
- (void) strcpy(fnout,fnin);
- if (flagunappend && (strlen(fnout) > strlen(fnappend)) &&
- (strcmp(fnout + strlen(fnout) - strlen(fnappend),fnappend) == 0))
- fnout[strlen(fnout) - strlen(fnappend)] = 0;
- else
- {
- (void) strcat(fnout,".");
- if (fnappend != NULL)
- (void) strcat(fnout,fnappend);
- }
- }
-
- /* Okay. Now we have fnin, fnout, and filter. */
-
- fdin = open(fnin,O_RDONLY);
- if (fdin == -1)
- { fprintf(stderr,"filterfile: fatal: cannot open input file ");
- perror(fnin); exit(1); }
- if (fstat(fdin,&stinold) == -1)
- { perror("filterfile: fatal: cannot stat input file"); exit(1); }
- if (flagdelete && (stinold.st_nlink > 1))
- { fprintf(stderr,"filterfile: fatal: will not proceed: \
- input file %s has extra links\n",fnin); exit(1); }
-
- tvp[0].tv_sec = stinold.st_atime;
- tvp[0].tv_usec = 0;
- tvp[1].tv_sec = stinold.st_mtime;
- tvp[1].tv_usec = 0;
-
- fdout = open(fnout,O_WRONLY | O_CREAT | O_EXCL,0600);
- if (fdout == -1)
- { fprintf(stderr,"filterfile: fatal: cannot create output file ");
- perror(fnout); exit(1); }
- if (fstat(fdout,&stoutold) == -1)
- { perror("filterfile: fatal: cannot stat output file"); exit(1); }
-
- if (flagprotect)
- if (fchmod(fdout,stinold.st_mode & 0777) == -1)
- perror("filterfile: warning: cannot change protections of output file");
-
- if ((f = fork()) == 0) /* child */
- {
- if (dup2(fdin,0) == -1)
- { perror("filterfile: fatal: cannot prepare input"); exit(1); }
- if (dup2(fdout,1) == -1)
- { perror("filterfile: fatal: cannot prepare output"); exit(1); }
- execvp(*filter,filter);
- fprintf(stderr,"filterfile: fatal: cannot execute filter\n");
- exit(1);
- }
- else if (f == -1) /* fork failed */
- { perror("filterfile: fatal: cannot fork"); exit(1); }
-
- /* parent */
- close(fdin);
- close(fdout);
- if (wait(&wstat) == -1)
- { perror("filterfile: fatal: can't find filter process"); exit(1); }
- if (wstat.w_T.w_Termsig)
- exit(1);
- if (wstat.w_T.w_Retcode)
- exit((int) wstat.w_T.w_Retcode);
- if (wstat.w_T.w_Coredump)
- exit(1);
-
- /* Filter exited happily. */
-
- if (flagdelete)
- {
- /* Race! Race! Race! */
- fdin = open(fnin,O_RDONLY);
- if (fdin == -1)
- { fprintf(stderr,"filterfile: fatal: cannot reopen input file ");
- perror(fnin); exit(1); }
- if (fstat(fdin,&stin) == -1)
- { fprintf(stderr,"filterfile: fatal: cannot restat input file ");
- perror(fnin); exit(1); }
- if ((stin.st_dev != stinold.st_dev) || (stin.st_ino != stinold.st_ino))
- { fprintf(stderr,"filterfile: fatal: will not delete input file %s: \
- it has been moved\n",fnin); exit(1); }
- if (stin.st_nlink > 1)
- { fprintf(stderr,"filterfile: fatal: will not delete input file %s: \
- it has extra links\n",fnin); exit(1); }
- /* Race! Race! Race! */
- if (unlink(fnin) == -1)
- { fprintf(stderr,"filterfile: fatal: cannot delete input file ");
- perror(fnin); exit(1); }
- (void) close(fdin);
- }
-
- if (flagtimes)
- {
- /* Race! Race! Race! */
- fdout = open(fnout,O_RDONLY);
- if (fdout == -1)
- { fprintf(stderr,"filterfile: fatal: cannot reopen output file ");
- perror(fnout); exit(1); }
- if (fstat(fdout,&stout) == -1)
- { perror("filterfile: fatal: cannot restat output file"); exit(1); }
- if ((stout.st_dev != stoutold.st_dev) || (stout.st_ino != stoutold.st_ino))
- { fprintf(stderr,"filterfile: warning: will not set times of \
- output file %s: it has been moved\n",fnout); exit(1); }
- /* Race! Race! Race! */
- if (utimes(fnout,tvp) == -1)
- { fprintf(stderr,"filterfile: warning: cannot set times of output file ");
- perror(fnout); exit(1); }
- }
-
- exit(0);
- }
-