home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / pep21.arc / MAIN.C < prev    next >
C/C++ Source or Header  |  1989-12-29  |  22KB  |  614 lines

  1. /* main.c  1989 december 28 [gh]
  2. +-----------------------------------------------------------------------------
  3. | Abstract:
  4. |    General purpose filter and file cleaning program.  9 out 10 hackers
  5. |    prefer pep to any other soap. It is named after an excellent Norwegian
  6. |    detergent.
  7. |
  8. | Authorship:
  9. |    Copyright (c) 1988, 1989 Gisle Hannemyr.
  10. |    Permission is granted to hack, make and distribute copies of this program
  11. |    as long as this notice and the copyright notices are not removed.
  12. |    If you intend to distribute changed versions of this program, please make
  13. |    an entry in the "history" log (below) and mark the hacked lines with your
  14. |    initials. I maintain the program, and shall appreiciate copies of bug
  15. |    fixes and new versions.
  16. |    Flames, bug reports, comments and improvements to:
  17. |       snail: Gisle Hannemyr, Brageveien 3A, 0452 Oslo, Norway
  18. |       email: EAN:  gisle@nr.uninett
  19. |              Inet: gisle@ifi.uio.no
  20. |              UUCP: ...!mcvax!ifi!gisle
  21. |              (and several BBS mailboxes in the Oslo area).
  22. |
  23. | Acknowledgments:
  24. |    SYS V.2 rename courtesy of Robert Andersson (ra@isncr.is.se)
  25. |    VMS rename courtesy of Bjorn Larsen.
  26. |    Thanks to Inge Arnesen for finding & fixing a bug, (and to Nils-Eivind
  27. |    Naas for bringing it to my attention).
  28. |
  29. | History:
  30. |    2.1 29 dec 89 [gh] Fixed pipe bug, added -v option, misc. speedups
  31. |    2.0 22 jan 89 [gh] Made it a filter, environment lookup, fixed pathbug.
  32. |    1.6  7 nov 88 [gh] Added ANSI interpretation.
  33. |    1.5  6 aug 88 [gh] Hacked it to not clobber original date.
  34. |    1.4  7 jul 88 [gh] Added general purpose conversion table.
  35. |    1.3 13 nov 87 [gh] Fixed find first so it works on true blue too.
  36. |    1.2 11 nov 87 [gh] Compensated for Turbo-C bug (isspace > 128 is bogus)
  37. |    1.1 31 aug 87 [gh] Added VMS.
  38. |    1.0 30 aug 87 [gh] Wrote it.
  39. |
  40. | Portability:
  41. |    So far, PEP has been tested under CP/M, MS-DOS, BSD and VMS.
  42. |    The implementation dependencies are:
  43. |      * How the compiler identify itself and the operating system.
  44. |      * How microcomputer compilers simulate the UNIX text line terminator.
  45. |      * How operating systems folds command lines (i.e. CP/M folds).
  46. |      * How operating systems expands command line wildcards (ie. UNIX does).
  47. |
  48. |    This dependencies are implemented using IFDEFs. You should make sure that
  49. |    exactly one of the following symbols (macro names) are defined:
  50. |     * __CPM86__  -- For CP/M, MP/M, C-DOS and derivatives
  51. |     * __MSDOS__  -- For MS-DOS and derivatives
  52. |     * __UNIX__   -- For BSD UNIX (SYS V.3 and generic too?)
  53. |     * __VMS__    -- For VMS
  54. |
  55. |    In addition, the following symbols may be twiddled if desired:
  56. |     * STRICMP    -- Define this if linker complains about missing "stricmp"
  57. |     * SYSV2      -- For SYS V.2 UNIX    (if no "rename" in standard lib)
  58. |     * __TURBOC__ -- For Borlands TURBOC (undefine it if you want PEP to
  59. |                     change the date on the files it filters).
  60. |     * VMSV1      -- For VAX C V.1.x VMS (if no "rename" in standard lib)
  61. |
  62. |    Most compilers already predefines a macro that identify the target oper-
  63. |    ating system.  Unfortunately, different vendors uses slightly different
  64. |    symbols.  Please add to the section headlined  "canonize predefined
  65. |    macroes" (below) if your compiler requires it.
  66. |
  67. |    Note: PEP makes some assumptions about standard headers.  See the file
  68. |          "header.txt" for details.
  69. |
  70. |    Btw. -- these are the compilers I have used to make pep:
  71. |     * MS-DOS,    Microsoft C ver. 5.1
  72. |           Turbo C ver. 2.0
  73. |     * BSD UNIX,  SunOS Release 4.0
  74. |     * SVID UNIX, NCR Tower System V.2
  75. |     * VMS,       VAX C release 2.4
  76. |
  77. | Environment:
  78. |    PEP -- should point to directory with conversion tables.
  79. |
  80. | Bugs:
  81. |    * I do not recompile PEP on all operating systems at each release.
  82. |      Software rot may cause a particular version to need some tweaking.
  83. |      Please mail me if you experience this -- but please read the enclosed
  84. |      file "header.txt" first.
  85. +---------------------------------------------------------------------------*/
  86.  
  87.  
  88. /*---( Includes )-----------------------------------------------------------*/
  89.  
  90. #define  MAIN
  91.  
  92. #include <stdio.h>
  93. #include "pep.h"
  94. #include <string.h>
  95. #include <ctype.h>
  96. #ifdef __VMS__
  97. #include <types.h>
  98. #include <stat.h>
  99. #else
  100. #include <sys/types.h>
  101. #include <sys/stat.h>
  102. #endif
  103. #if __CPM86__ || __MSDOS__
  104. #include <dos.h>
  105. #include "bdmg.h"
  106. #endif
  107. #ifdef __MSDOS__
  108. #include <fcntl.h>
  109. #include <io.h>
  110. #endif
  111. #ifdef __UNIX__
  112. #include <malloc.h>
  113. #else
  114. #include <stdlib.h>
  115. #endif
  116. #ifdef VMSV1
  117. #include <descrip.h>
  118. #endif
  119.  
  120.  
  121. /*---( defines )------------------------------------------------------------*/
  122.  
  123. #define VERSION     "2.1"        /* Version number.                  */
  124. #define TEMPFIL     "PEP.TMP"           /* Tempfile.                        */
  125.  
  126.  
  127. /*---( constants )----------------------------------------------------------*/
  128.  
  129. static char about1[] = "\n\
  130. Pep is a program that converts almost anything into plain text files.\n\
  131. Permission is granted to make and distribute copies of this program as\n\
  132. long as the copyright and this notice appears; and that all the files\n\
  133. in the distribution is included.  ( The files in the distribution is\n\
  134. documented in the release note file \"aaread.me\". )\n\n";
  135.  
  136. static char about2[] = "\
  137. Bug reports, improvements, comments, suggestions and flames to:\n\
  138.    snail: Gisle Hannemyr, Brageveien 3A, 0452 Oslo, Norway\n\
  139.    email: EAN:  gisle@nr.uninett;\n\
  140.           Inet: gisle@ifi.uio.no;\n\
  141.           UUCP: ...!mcvax!ifi!gisle\n\
  142.           (and several BBS mailboxes).\n";
  143.  
  144. static char usage1[] = "   Usage: pep [options] [filename ...]\n\
  145.    Valid options:\n\
  146. \t-a        -- about pep\n\
  147. \t-b        -- remove non ASCII-codes\n\
  148. \t-c[size]  -- compress spaces to tabs\n\
  149. \t-d+/-     -- convert to/from DEC 8 bit charset\n\
  150. \t-e[guard] -- interprete ANSI escape sequences\n\
  151. \t-g<file>  -- get conversion table from file\n\
  152. \t-h        -- print this quick summary\n\
  153. \t-i+/-     -- convert to/from IBM-PC charset\n\
  154. \t-k+/-     -- convert to/from \"Kman\" charset\n\
  155. \t-m+/-     -- convert to/from Macintosh charset\n";
  156.  
  157. char usage2[] = "\
  158. \t-o[b]     -- write output to named files\n\
  159. \t-p        -- display transformations and pause\n\
  160. \t-s[size]  -- extract strings\n\
  161. \t-t[size]  -- expand tabstops\n\
  162. \t-u<term>  -- use special line terminator\n\
  163. \t-v        -- terminate only paragraphs\n\
  164. \t-w+/-     -- convert to/from WS document mode\n\
  165. \t-x        -- expand non printing chars\n\
  166. \t-z        -- zero parity bit\n";
  167.  
  168.  
  169. /*---( variables )----------------------------------------------------------*/
  170.  
  171. static int  cright = TRUE;                  /* Flag copyright undisplayed   */
  172. static int  guardl = 0;                     /* ANSI overwrite guard level   */
  173.  
  174. long LCount = 0L;                /* Global line count            */
  175. int  LineXx = 0;                /* Horisontal position on line. */
  176. int  ITabSz = 8;                /* Input  tabulator size.       */
  177. int  OTabSz = 8;                /* Output tabulator size.       */
  178. int  StrSiz = 4;                /* String size for strings.     */
  179. #if __UNIX__ || __VMS__
  180. int  EndOLn = '\n';                /* Under UNIX, default is LF;   */
  181. #else
  182. int  EndOLn = -1;                /* else, the default is CRLF.   */
  183. #endif
  184.  
  185. static    int  backup = FALSE;                   /* Keep backup copy.            */
  186.     int  bflagb = FALSE;            /* Binary wash.                 */
  187.     int  cflagc = FALSE;            /* Compress                     */
  188.     int  dflagd = FALSE;            /* DEC character set.           */
  189. static    int  eflage = FALSE;            /* ANSI escape sequences.       */
  190.     int  gflagg = FALSE;            /* General fold table           */
  191.     int  iflagi = FALSE;            /* IBM character set.           */
  192.     int  kflagk = FALSE;            /* Kman character set.          */
  193.     int  mflagm = FALSE;            /* MAC character set.           */
  194. #ifdef __VMS__
  195. static    int  oflago = TRUE;            /* VMS has no pipes.        */
  196. #else
  197. static    int  oflago = FALSE;            /* Write output on files.        */
  198. #endif
  199. static    int  pflagp = FALSE;              /* Pause.                       */
  200.     int  sflags = FALSE;            /* String extraction.           */
  201.     int  tflagt = FALSE;            /* Tab expansion                */
  202. static    int  uflagu = FALSE;            /* Use special line terminator. */
  203.     int  vflagv = FALSE;            /* Terminate only paragraphs.   */
  204.     int  wflag0 = FALSE;            /* From WS doc. mode to 7-bit.  */
  205.     int  wflag1 = FALSE;            /* From 7-bit to WS doc. mode.  */
  206.     int  xflagx = FALSE;
  207.     int  zflagz = FALSE;
  208.  
  209.  
  210. /*---( housekeeping )-------------------------------------------------------*/
  211.  
  212.  
  213. /*
  214. | Abs: Write control or meta character ii on stderr using standard conventions.
  215. */
  216. static void fputctl(ii)
  217. int ii;
  218. {
  219.    if ((ii < 0) || (ii > 255)) fputs("<BOGUS>",stderr);
  220.    else if (ii == 255) fputs("M-del",stderr);
  221.    else if (ii == 127) fputs("DEL",stderr);
  222.    else {
  223.       if (ii >= 128) { fputc('M',stderr); fputc('-',stderr); ii -= 128; }
  224.       if (ii <  ' ') { fputc('^',stderr); ii += '@'; }
  225.       fputc(ii,stderr);
  226.    } /* else */
  227. } /* fputctl */
  228.  
  229.  
  230. /*
  231. | Abs: Display copyright notice.
  232. | Sef: Sets the cright flag FALSE so that we only displays it once.
  233. */
  234. void showcright()
  235. {
  236.    fprintf(stderr,"pep  ver. %s; Copyright (c) 1989 Gisle Hannemyr\n",VERSION);
  237.    cright = FALSE;
  238. } /* showcright */
  239.  
  240.  
  241. /*
  242. | Abs: Display message and abort.
  243. */
  244. void mess(err)
  245. int err;
  246. {
  247.    if (cright) showcright();
  248.    fputs("pep: ",stderr);
  249.    switch(err) {
  250.       case  1: fputs("incompatible options",       stderr); break;
  251.       case  2: fputs("missing '+' or '-'",         stderr); break;
  252.       case  3: fputs("bad guard digit",            stderr); break;
  253.       case  4: fputs("invalid line terminator",    stderr); break;
  254.       case  5: fputs("no more room",               stderr); break;
  255.       case  6: fputs("bad conversion table",       stderr); break;
  256.       case  7: fputs("no matching files",          stderr); break;
  257.       case  8: fputs("cannot pause reading stdin", stderr); break;
  258.       case  9: fputs("sorry, not yet implemented", stderr); break;
  259.       default: fputs("unknown error",              stderr); break;
  260.    } /* switch */
  261.    putc('\n',stderr);
  262.    exit(ERROR_EXIT);
  263. } /* mess */
  264.  
  265.  
  266. void showprogress()
  267. {
  268.    LCount++;
  269.    if (oflago && ((LCount % 64) == 0)) fprintf(stderr,"\r%ld ",LCount);
  270. } /* showprogress */
  271.  
  272.  
  273. /*
  274. | Abs: Parse desired line terminator.
  275. | Des: r        = CR
  276. |      n        = NL
  277. |      s        = RS
  278. |      #        = CRLF
  279. |      -        = none
  280. |      <number> = use this as the terminator
  281. | Sef: IFrst, ILast, ILimit.
  282. */
  283. void getterm(ss)
  284. char *ss;
  285. {
  286.    if       (*ss == 'n')  EndOLn = '\n';
  287.    else if  (*ss == 'r')  EndOLn = '\r';
  288.    else if  (*ss == 's')  EndOLn =   30;
  289.    else if  (*ss == '#')  EndOLn =   -1;
  290.    else if  (*ss == '-')  EndOLn =   -2;
  291.    else if (isdigit(*ss)) EndOLn = atoi(ss);
  292.    else mess(4);
  293. } /* getterm */
  294.  
  295.  
  296. /*
  297. | Abs: Check toggle.
  298. | Ret: TRUE if toggle is on, else off.
  299. */
  300. BOOL swchk(dd)
  301. char dd;
  302. {
  303.    if ((dd != '+') && (dd != '-')) mess(2);
  304.    return(dd == '+');
  305. } /* swchk */
  306.  
  307.  
  308. /*
  309. | Abs: Check fold direction and set up direction flags.
  310. | Des: IFrst set to 1 if folding to 8 bit character set.
  311. | Sef: IFrst, ILast, ILimit.
  312. */
  313. void folddir(dd)
  314. char dd;
  315. {
  316.    if (swchk(dd)) { IFrst = 1; ILast = 0; ILimit =  91; }
  317.    else           { IFrst = 0; ILast = 1; ILimit = 128; }
  318. } /* folddir */
  319.  
  320.  
  321. /*
  322. | Abs: Show transformations.
  323. | Imp: Moved from main() coz MS-C don't like big main functions.
  324. */
  325. void showoptions(tabledir,cname)
  326. char *tabledir, *cname;
  327. {
  328.    int  cc;
  329.  
  330.    fputs("Transformations:\n",stderr);
  331.    if (!vflagv) fputs(" * stripping all trailing spaces;\n",stderr);
  332.  
  333.    if (gflagg) {
  334.       fprintf(stderr," * translating using table in file \"%s\";\n",cname);
  335.       readtable(tabledir,cname,TRUE);
  336.    } /* if gflagg */
  337.  
  338. #ifdef __TURBOC__
  339.    fputs(" * preserving file dates;\n",stderr);
  340. #endif
  341.    if (oflago) fputs(" * output file is input file (not stdout);\n",stderr);
  342.    if (backup) fputs(" * creating .BAK copies of input file;\n",stderr);
  343.    if (bflagb) fprintf(stderr," * %sing non ASCII-codes;\n", xflagx ? "expand" : "remov");
  344.    if (dflagd || iflagi || mflagm) {
  345.       char *machine;
  346.       if      (dflagd) machine = "DEC";
  347.       else if (iflagi) machine = "IBM";
  348.       else if (mflagm) machine = "MAC";
  349.       if (IFrst) fprintf(stderr," * Norwegian 7-bit ==> 8-bit %s charset", machine);
  350.       else       fprintf(stderr," * 8-bit %s charset ==> norwegian 7-bit", machine);
  351.       if (kflagk) fputs(",\n   using \\\\ for Norwegian \"OE\";\n",stderr);
  352.       else        fputs(";\n",stderr);
  353.    } /* if (dflagd || iflagi || mflagm) */
  354.    if (sflags) fprintf(stderr," * extracting strings >= %d characters;\n",StrSiz);
  355.    if (cflagc && tflagt) {
  356.       fputs(" * optimizing out spaces from tabulation;\n",stderr);
  357.       if (ITabSz != OTabSz) fprintf(stderr," * repacking tabs, size: %d --> %d;\n",ITabSz,OTabSz);
  358.    } else {
  359.       if (tflagt) fprintf(stderr," * expanding tabs, size: %d;\n",ITabSz);
  360.       if (cflagc) fprintf(stderr," * inserting tabs, size: %d;\n",OTabSz);
  361.    }
  362.    if (eflage) fputs(" * interpreting ANSI escape sequences;\n",stderr);
  363.  
  364.    if (wflag0) fputs(" * WS doc. mode ==> 7-bit text files;\n",stderr);
  365.    if (wflag1) fputs(" * 7-bit text files ==> WS doc. mode;\n",stderr);
  366.    else {
  367.       if (EndOLn ==  -2 ) fputs(" * removing line terminators",stderr);
  368.       else {
  369.          if (vflagv) fputs(" * terminating paragraphs only with ",stderr);
  370.          else        fputs(" * terminating lines with ",stderr);
  371.          if      (EndOLn ==  -1 ) fputs("CRLF",stderr);
  372.          else if (EndOLn == '\n') fputs("LF",  stderr);
  373.          else if (EndOLn == '\r') fputs("CR",  stderr);
  374.          else if (EndOLn ==  30 ) fputs("RS",  stderr);
  375.          else fputctl(EndOLn);
  376.       } /* if EndOLn != -2 */
  377.    } /* if else not WS */
  378. #ifdef __VMS__
  379.    fputs(" (Stream_LF);\n",stderr);
  380. #else
  381.    fputs(";\n",stderr);
  382. #endif
  383.  
  384.    if (zflagz) fputs(" * zeroing parity bit;\n",stderr);
  385.    fprintf(stderr," * %sing control characters.\n", xflagx ? "expand" : "remov");
  386.    if (pflagp) {
  387.       fputs("\nHit CTRL-C to abort, RETURN continue. ",stderr);
  388.       cc = getc(stdin);
  389.       if (cc == 3) exit(ERROR_EXIT);   /* Not necessary for cooked microes. */
  390.    } /* if */
  391. } /* showoptions */
  392.  
  393.  
  394. /*
  395. | Abs: Do a complete file.
  396. | Sef: Zero line cont.
  397. */
  398. void dofile(eflage)
  399. int eflage;
  400. {
  401. #ifndef __VMS__
  402.    /* Speed things up using a bigger I/O buffer. */
  403.    if (setvbuf(Fdi,NULL,_IOFBF,16384) || setvbuf(Fdo,NULL,_IOFBF,16384))
  404.       mess(5); /* No more room */
  405. #endif
  406.    LCount = 0L;
  407.    if (eflage) doansi(guardl); else doplain();
  408. } /* dofile */
  409.  
  410.  
  411. /*---( main )---------------------------------------------------------------*/
  412.  
  413. main(argc, argv)
  414. int  argc;
  415. char **argv;
  416. {
  417.    struct stat statbuf;
  418.    unsigned int statype;
  419.    unsigned int statmod;
  420.    char *tabledir;
  421.    char *cname, *nname, *ss;
  422.    int  cc;
  423.    char dd;
  424. #if __CPM86__ || __MSDOS__
  425.    char *cp;
  426.    struct DIRLIST *first, *last;
  427. #endif
  428. #ifdef __TURBOC__
  429.    struct ftime *filtim;
  430.    int hh;
  431. #endif
  432.  
  433. #ifdef __MSDOS__
  434.    _fmode = O_BINARY;         /* Tell MS-C, Turbo not to do CRLF expansion. */
  435.    tabledir = argv[0];        /* Look for tables in startup-directory.      */
  436. #else
  437.    tabledir = NULL;           /* No such startup convention for other OS's. */
  438. #endif
  439.  
  440.    inittable();
  441.  
  442.    argc--; argv++;           /* skip program name  */
  443.    while (argc && (**argv == '-')) {
  444.       (*argv)++;             /* skip initial '-'   */
  445.       cc = **argv;         /* option letter      */
  446. #ifdef __CPM86__
  447.       cc = tolower(cc);
  448. #endif
  449.       (*argv)++;             /* skip option letter */
  450.       dd = **argv;           /* arg argument       */
  451.       switch (cc) {
  452.          case 'a': showcright(); fputs(about1, stderr); fputs(about2, stderr);
  453.                    exit(NORML_EXIT);
  454.          case 'b': bflagb++; break;
  455.          case 'c': cflagc++; if (**argv != '\0') OTabSz = atoi(*argv); break;
  456.          case 'd': dflagd++; folddir(dd); break;
  457.          case 'e': eflage++; if (**argv != '\0') guardl = atoi(*argv);
  458.                    tflagt++;
  459.                    break;
  460.          case 'g': gflagg++; cname = *argv; break;
  461.          /*   'h': OK to fall thru' to default */
  462.          case 'i': iflagi++; folddir(dd); break;
  463.          case 'k': kflagk++; folddir(dd); break;
  464.          case 'm': mflagm++; folddir(dd); break;
  465.          case 'o': oflago++; if (dd == 'b') backup++; break;
  466.          case 'p': pflagp++; break;
  467.          case 's': sflags++; if (**argv != '\0') StrSiz = atoi(*argv); break;
  468.          case 't': tflagt++; if (**argv != '\0') ITabSz = atoi(*argv); break;
  469.          case 'u': uflagu++; if (**argv != '\0') getterm(*argv); else mess(4); break;
  470.          case 'v': vflagv++; break;
  471.          case 'w': if (swchk(dd))  tflagt = wflag1 = TRUE;
  472.                    else            zflagz = wflag0 = TRUE;
  473.                    break;
  474.          case 'x': xflagx++; break;
  475.          case 'z': zflagz++; break;
  476.          default : showcright();
  477.                fputs(usage1,stderr); fputs(usage2,stderr);
  478.                exit(NORML_EXIT);
  479.       } /* switch */
  480.       argc--; argv++;
  481.    } /* while options */
  482.  
  483.    if (pflagp && !argc) mess(8);
  484.    if ((dflagd + gflagg + iflagi + mflagm + zflagz) > 1) mess(1);
  485.    if ((guardl < 0) || (guardl > 2)) mess(3);
  486.    if (kflagk && !(dflagd + mflagm)) iflagi++;
  487.    if (!uflagu && dflagd && IFrst) EndOLn = '\n'; /* To DEC (Dec uses LF as terminator) */
  488.    if (!uflagu && iflagi && IFrst) EndOLn = -1;   /* To IBM (Uses  CRLF  as terminator) */
  489.    if (!uflagu && mflagm && IFrst) EndOLn = '\r'; /* To Mac (Mac uses CR as terminator) */
  490.  
  491.    Fdi = stdin;              /* Default */
  492.    Fdo = stdout;
  493. #ifdef __MSDOS__
  494.    setmode(fileno(Fdi),_fmode); /* Make sure that even braindamaged  MS-DOS */
  495.    setmode(fileno(Fdo),_fmode); /*    are transparent when redirecting i/o. */
  496. #endif
  497.    if (!argc) { /* Doing standard input */
  498.       if      (pflagp) showoptions(tabledir,cname);
  499.       else if (gflagg) readtable(tabledir,cname,FALSE);
  500.       if      (oflago) mess(7);
  501.       dofile(eflage);
  502.    } else {
  503.       showcright();
  504.       showoptions(tabledir,cname);
  505. #if __CPM86__ || __MSDOS__
  506.       first = expwildcard(argv);
  507.       if (!first) mess(7);
  508.       /* Inv: first now points to a start of linked list of files. */
  509.       last = first;
  510.       while (last) {
  511.          cname = last->fnam;
  512.      if (oflago) {
  513.         putc('\r',stderr);
  514.         putc('\n',stderr);
  515. #else
  516.       while (argc) {
  517.          cname = *argv;
  518.      if (oflago) {
  519.         putc('\n',stderr);
  520. #endif
  521.         fputs(cname,stderr);
  522.      } /* if oflago */
  523.  
  524. #ifdef __UNIX__
  525.      if (lstat(cname,&statbuf)) {
  526. #else
  527.      if (stat(cname,&statbuf)) {
  528. #endif
  529.         if (!oflago) fputs(cname,stderr);
  530.             fputs(": can't access\n", stderr);
  531.             goto cont;
  532.      } /* if not stat */
  533.      statmod = statbuf.st_mode;
  534.      statype = statbuf.st_mode &  S_IFMT;
  535.  
  536.      if (statype != S_IFREG) {
  537.         if (!oflago) fputs(cname,stderr);
  538.             if      (statype == S_IFDIR) fputs(": directory\n", stderr);
  539. #ifdef __UNIX__
  540.             else if (statype == S_IFLNK) fputs(": symbolic link\n", stderr);
  541. #endif
  542.         else                         fputs(": special file\n", stderr);
  543.             goto cont;
  544.      } /* if not a regular file */
  545.  
  546.          if ((Fdi = fopen(cname,"r")) == NULL) {
  547.         if (!oflago) fputs(cname,stderr);
  548.             fputs(": can't open\n", stderr);
  549.             goto cont;
  550.          }
  551.          if (oflago) if ((Fdo = fopen(TEMPFIL,"w")) == NULL) {
  552.             fputs(": can't create tmpfile\n",stderr); exit(ERROR_EXIT);
  553.          }
  554. #ifdef __TURBOC__
  555.          if (!(filtim = (struct ftime *)malloc(sizeof(struct ftime))))
  556.             mess(5); /* No more room */
  557.          getftime(fileno(Fdi),filtim);
  558. #endif
  559.          if (oflago) putc('\n',stderr);
  560.          dofile(eflage);
  561.          if (oflago) fprintf(stderr,"\r   Done. %ld lines written.",LCount);
  562.  
  563.          if (ferror(Fdi) || ferror(Fdo)) {
  564.             fputs("\npep: I/O error, file unchanged\n", stderr);
  565.          } else {
  566.             fclose(Fdi);
  567.             if (oflago) {
  568.            fclose(Fdo);
  569.            if (chmod(TEMPFIL,statmod)) fputs("\npep: could not set mode\n",stderr);
  570. #ifdef __TURBOC__
  571.                if ((hh  = _open(TEMPFIL,O_RDONLY)) != -1) setftime(hh,filtim);
  572.                _close(hh);
  573. #endif
  574.             } /* if (oflago) */
  575.  
  576.             cc = 0; /* error flag */
  577.             if (backup) {
  578.                if (!(nname = (char *)malloc(strlen(cname)+5))) mess(5);
  579.                strcpy(nname,cname);
  580.                if (ss = strrchr(nname,'.')) *ss = '\0';
  581.                strcat(nname,".BAK");
  582.                unlink(nname);
  583. #ifdef __UNIX__
  584.                if (strcmp(nname,cname)) {  /* UNIX names are case sensitive */
  585. #else
  586.                if (stricmp(nname,cname)) { /*    other filenames are not.   */
  587. #endif
  588.                   if (rename(cname,nname)) cc++;
  589.                } /* if same names */
  590.             } else {
  591.                if (oflago) if (unlink(cname)) cc++;
  592.             } /* if .. else no backup */
  593.             if (oflago) if (rename(TEMPFIL,cname)) cc++;
  594.             if (cc) {
  595.                fprintf(stderr, "\npep: error creating %s, file is %s\n",cname,TEMPFIL);
  596.                exit(ERROR_EXIT);
  597.             } /* if error */
  598.          } /* if .. else close file */
  599. cont:
  600. #if __CPM86__ || __MSDOS__
  601.          last = last->next;
  602.       } /* while */
  603.    dispwildcard(first);
  604. #else
  605.          argc--; argv++;
  606.       } /* while */
  607.       if (oflago) putc('\n',stderr);
  608. #endif
  609.    } /* if .. else read named files */
  610.    exit(NORML_EXIT);
  611. }  /* main */
  612.  
  613. /* EOF */
  614.