callback-rxcon-move-20040602
[openafs.git] / src / config / util_cr.c
1 /* crlf.c : Defines the entry point for the console application.*/
2
3 /* Copyright 2000, International Business Machines Corporation and others.
4         All Rights Reserved.
5  
6         This software has been released under the terms of the IBM Public
7         License.  For details, see the LICENSE file in the top-level source
8         directory or online at http://www.openafs.org/dl/license10.html
9
10 */
11
12 #undef _CRTDBG_MAP_ALLOC
13 #include "stdio.h"
14 #include "io.h"
15 #include <assert.h>
16 #include "string.h"
17 #include "process.h"
18 #include "windows.h"
19 #include "malloc.h"
20 #include "time.h"
21 #include "stdlib.h"
22 #include "windows.h"
23
24 #ifndef  intptr_t
25 #define intptr_t long
26 #endif
27
28 void
29 usuage()
30 {
31     printf("util_cr file ;remove cr (from crlf)\n\
32         OR util_cr } ProductVersion in_filename out_filename ; substitute for %%1-%%5 in file\n\
33            %%1=Major version, %%2=Minor version, %%3=Patch(first digit) %%4=(last two digits) %%5=Version display string \n\
34            ProductVersion=maj.min.pat.pat2 ;maj=numeric, min=numeric pat,pat2 are not more than 3 digits or 1-2 digits and one alpha \n\
35            e.g 1.0.4.1, 1.0.4 a 1.0.401, 1.0.4a  all represent the same version\n\
36         OR util_cr + file ;add cr\n \
37         OR util_cr * \"+[register key value] x=y\" ; add register key value\n\
38         OR util_cr * \"-[register key value]\" ; aremove register key value\n\
39         OR util_cr @ file.ini \"[SectionKey]variable=value\" ; update ini-ipr-pwf file\n\
40         OR util_cr @ file.ini \"[SectionKey]variable=value*DatE*\" ; update ini-ipr-pwf file, insert date\n\
41         OR util_cr ~  ;force error\n\
42         OR util_cr _del  [/q=quiet /s=recurese] [*. *. *.] ;delete \n\
43         OR util_cr _cpy [/q=quiet ] [*. *. *.] destinationFolder;\n\
44         OR util_cr _isOS [nt xp 98 9x w2] ;test for OS, return 1 if match else 0\n\
45         OR util_cr _dir !build type!source!object! set current directory in file->home base is used for offset\n\
46         OR unil_cr _ver return compiler version\n");
47     exit(0xc000);
48 }
49
50 struct TRANSLATION {
51     WORD langID;                // language ID
52     WORD charset;               // character set (code page)
53 };
54
55 int
56 CheckVersion(int argc, char *argv[])
57 {
58     OSVERSIONINFO VersionInfo;
59     int i;
60     memset(&VersionInfo, 0, sizeof(VersionInfo));
61     VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
62     if (!GetVersionEx(&VersionInfo)) {
63         return 0XC000;
64     }
65     for (i = 2; i < argc; i++) {
66         if (stricmp(argv[i], "nt") == 0) {
67             if ((VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
68                 && (VersionInfo.dwMajorVersion == 4)
69                 && (VersionInfo.dwMinorVersion == 0))
70                 return 1;
71         }
72         if (stricmp(argv[i], "xp") == 0) {
73             if ((VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
74                 && (VersionInfo.dwMajorVersion == 5)
75                 && (VersionInfo.dwMinorVersion == 1))
76                 return 1;
77         }
78         if (stricmp(argv[i], "w2") == 0) {
79             if ((VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
80                 && (VersionInfo.dwMajorVersion == 5)
81                 && (VersionInfo.dwMinorVersion == 0))
82                 return 1;
83         }
84         if (stricmp(argv[i], "98") == 0) {
85             if ((VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
86                 && (VersionInfo.dwMinorVersion == 10))
87                 return 1;
88         }
89         if (stricmp(argv[i], "95") == 0) {
90             if ((VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
91                 && (VersionInfo.dwMinorVersion == 0))
92
93                 return 1;
94         }
95         if (stricmp(argv[i], "9x") == 0) {
96             if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
97                 return 1;
98         }
99         if (stricmp(argv[i], "_") == 0)
100             return 0;
101     }
102     return 0;
103 }
104
105 void
106 Addkey(const char *hkey, const char *subkey, const char *stag,
107        const char *sval)
108 {
109     DWORD disposition, result;
110     HKEY kPkey, kHkey = 0;
111     if (strcmp(hkey, "HKEY_CLASSES_ROOT") == 0)
112         kHkey = HKEY_CLASSES_ROOT;
113     if (strcmp(hkey, "HKEY_CURRENT_USER") == 0)
114         kHkey = HKEY_CURRENT_USER;
115     if (strcmp(hkey, "HKEY_LOCAL_MACHINE") == 0)
116         kHkey = HKEY_LOCAL_MACHINE;
117     if (kHkey == 0)
118         usuage();
119     result = (RegCreateKeyEx(kHkey      /*HKEY_LOCAL_MACHINE */
120                              , subkey, 0, NULL, REG_OPTION_NON_VOLATILE,
121                              KEY_ALL_ACCESS, NULL, &kPkey,
122                              &disposition) == ERROR_SUCCESS);
123     if (!result) {
124         printf("AFS Error - Could Not create a registration key\n");
125         exit(0xc000);
126     }
127     if (stag == NULL)
128         return;
129     if ((sval) && (strlen(sval))) {
130         if (*stag == '@')
131             result =
132                 RegSetValueEx(kPkey, "", 0, REG_SZ, (CONST BYTE *) sval,
133                               strlen(sval));
134         else
135             result =
136                 RegSetValueEx(kPkey, stag, 0, REG_SZ, (CONST BYTE *) sval,
137                               strlen(sval));
138     } else {
139
140         if (*stag == '@')
141             result =
142                 (RegSetValueEx(kPkey, "", 0, REG_SZ, (CONST BYTE *) "", 0));
143         else
144             result =
145                 (RegSetValueEx(kPkey, stag, 0, REG_SZ, (CONST BYTE *) "", 0));
146     }
147     if (result != ERROR_SUCCESS) {
148         printf("AFS Error - Could Not create a registration key\n");
149         exit(0xc000);
150     }
151 }
152
153 void
154 Subkey(const char *hkey, const char *subkey)
155 {
156     DWORD result;
157     HKEY kHkey = 0;
158     if (strcmp(hkey, "HKEY_CLASSES_ROOT") == 0)
159         kHkey = HKEY_CLASSES_ROOT;
160     if (strcmp(hkey, "HKEY_CURRENT_USER") == 0)
161         kHkey = HKEY_CURRENT_USER;
162     if (strcmp(hkey, "HKEY_LOCAL_MACHINE") == 0)
163         kHkey = HKEY_LOCAL_MACHINE;
164     if (kHkey == 0)
165         usuage();
166     result = RegDeleteKey(kHkey, subkey);
167     if (result != ERROR_SUCCESS) {
168         printf("AFS Error - Could Not create a registration key\n");
169         exit(0xc000);
170     }
171 }
172
173 void
174 doremove(BOOL bRecurse, BOOL bQuiet, char *argv)
175 {
176     char *pParm;
177     char parm[MAX_PATH + 1];
178     char basdir[MAX_PATH + 1];
179     strcpy(parm, argv);
180     pParm = parm;
181     GetCurrentDirectory(sizeof(basdir), basdir);
182     if (strrchr(parm, '\\') != NULL) {  /*jump to base directory */
183         pParm = strrchr(parm, '\\');
184         *pParm = 0;
185         if (!SetCurrentDirectory(parm))
186             return;
187         pParm++;
188     }
189     if (!bRecurse) {
190         struct _finddata_t fileinfo;
191         intptr_t hfile;
192         BOOL bmore;
193         char basdir[MAX_PATH + 1];
194         GetCurrentDirectory(sizeof(basdir), basdir);
195         hfile = _findfirst(pParm, &fileinfo);
196         bmore = (hfile != -1);
197         while (bmore) {
198             if ((DeleteFile(fileinfo.name) == 1) && (!bQuiet))
199                 printf("Remove %s\\%s\n", basdir, fileinfo.name);
200             bmore = (_findnext(hfile, &fileinfo) == 0);
201         }
202         _findclose(hfile);
203     } else {
204         /*RECURSIVE LOOP - SCAN directories */
205         struct _finddata_t fileinfo;
206         intptr_t hfile;
207         BOOL bmore;
208         doremove(FALSE, bQuiet, pParm);
209         hfile = _findfirst("*.*", &fileinfo);
210         bmore = (hfile != -1);
211         while (bmore) {
212             if (fileinfo.attrib & _A_SUBDIR) {
213                 if ((strcmp(fileinfo.name, ".") != 0)
214                     && (strcmp(fileinfo.name, "..") != 0)) {
215                     if (SetCurrentDirectory(fileinfo.name))
216                         doremove(TRUE, bQuiet, pParm);
217                     SetCurrentDirectory(basdir);
218                 }
219             }
220             bmore = (_findnext(hfile, &fileinfo) == 0);
221         }
222         _findclose(hfile);
223     }
224     SetCurrentDirectory(basdir);
225 }
226
227 void
228 gencurdir(char *val)
229 {
230     char bld[MAX_PATH + 1], parm[MAX_PATH + 1], src[MAX_PATH + 1],
231         obj[MAX_PATH + 1], dir[MAX_PATH + 1], curdir[MAX_PATH + 1];
232     char *p, *po;
233     FILE *f;
234     BOOL isObjAbs, isSrcAbs;    /* two flags to determine if either string is not relative */
235     strcpy(bld, val + 1);       /*it better be checked or free */
236     strcpy(src, strchr(bld, '!') + 1);
237     strcpy(obj, strchr(src, '!') + 1);
238     *strchr(bld, '!') = 0;
239     *strchr(obj, '!') = 0;
240     *strchr(src, '!') = 0;
241     isObjAbs = ((*obj == '\\') || (strstr(obj, ":")));
242     isSrcAbs = ((*src == '\\') || (strstr(src, ":")));
243     GetCurrentDirectory(MAX_PATH, dir);
244     strlwr(bld);
245     strlwr(dir);
246     strlwr(src);
247     strlwr(obj);
248     strcpy(curdir, dir);
249     strcat(curdir, "\\ \n");
250     if (GetTempPath(MAX_PATH, parm) == 0)
251         exit(0xc000);
252     strcat(parm, "home");
253     if ((f = fopen(parm, "w")) == NULL)
254         exit(0xc000);
255     __try {
256         __try {
257             if (obj[strlen(obj) - 1] != '\\')
258                 strcat(obj, "\\");
259             if (src[strlen(src) - 1] != '\\')
260                 strcat(src, "\\");
261             do {                /* try to match src or obj */
262                 if ((p = strstr(dir, src)) && isSrcAbs) {
263                     po = p;
264                     p += strlen(src);
265                 } else if ((p = strstr(dir, src)) && !isSrcAbs
266                            && *(p - 1) == '\\') {
267                     po = p;
268                     p += strlen(src);
269                 } else if ((p = strstr(dir, obj)) && isObjAbs) {
270                     po = p;
271                     p += strlen(obj);
272                 } else if ((p = strstr(dir, obj)) && !isObjAbs
273                            && *(p - 1) == '\\') {
274                     po = p;
275                     p += strlen(obj);
276                 }
277             } while (strstr(p, src) || strstr(p, obj));
278             if (isObjAbs) {
279                 sprintf(parm, "OJT=%s%s\\%s \n", obj, bld, p);
280             } else {
281                 *po = 0;
282                 sprintf(parm, "OJT=%s%s%s\\%s \n", dir, obj, bld, p);
283             }
284             if (strcmp(curdir, parm + 4) == 0)  /* current directory is object */
285                 strcpy(parm, "OJT= \n");
286             fwrite(parm, strlen(parm), 1, f);
287             if (isSrcAbs) {
288                 sprintf(parm, "SRT=%s%s\\ \n", src, p);
289             } else {
290                 *(p - strlen(src)) = 0;
291                 sprintf(parm, "SRT=%s%s%s\\ \n", dir, src, p);
292             }
293             if (strcmp(curdir, parm + 4) == 0)  /* current directory is object */
294                 strcpy(parm, "SRT= \n");
295             fwrite(parm, strlen(parm), 1, f);
296             /* now lets set the AFS_LASTCMP environment variable */
297             sprintf(parm, "AFS_LASTCMP=%s\\%s", src, p);
298         }
299         __except(EXCEPTION_EXECUTE_HANDLER) {
300             exit(0xc000);
301         }
302     }
303     __finally {
304         fclose(f);
305     }
306 }
307
308 int
309 isequal(char *msg1, char *msg2, char *disp)
310 {
311     strlwr(msg1);
312     strlwr(msg2);
313     if (strcmp(msg1, msg2) != 0)
314         return 0;
315     printf("ERROR -- %s \n", disp);
316     exit(0xc000);
317 }
318
319 int
320 SetSysEnv(int argc, char *argv[])
321 {
322     DWORD dwResult;
323     printf("assignment %s %s\n", argv[2], argv[3]);
324     Addkey("HKEY_LOCAL_MACHINE",
325            "System\\CurrentControlSet\\Control\\Session Manager\\Environment",
326            argv[2]
327            , argv[3]
328         );
329     SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
330                        (DWORD) "Environment", SMTO_NORMAL, 1, &dwResult);
331     return 0;
332 }
333
334 int
335 main(int argc, char *argv[])
336 {
337 /*      typedef char * CHARP;*/
338     char fname[128];
339     FILE *file;
340     int l, i;
341     char **pvar, *ch, *save;
342     long len;
343     BOOL bRecurse = FALSE;
344     BOOL bQuiet = FALSE;
345     if (argc < 2)
346         usuage();
347
348    /* RSM4: Add an "ECHO" that doesn't append a new line... */
349    if (strcmp(argv[1], "_echo") == 0) {
350       if(argc<3)
351          usuage();
352       printf("%s",argv[2]);
353       return 0;
354    }
355
356     if (strcmp(argv[1], "_sysvar") == 0) {
357         if (argc < 4)
358             usuage();
359         return (SetSysEnv(argc, argv));
360
361     }
362     if (strnicmp(argv[1], "_dir", 4) == 0) {    /*get current directory routine */
363         gencurdir(argv[1]);
364         return 0;
365     }
366     if (strnicmp(argv[1], "_isequal", 4) == 0) {        /*get current directory routine */
367         return isequal(argv[2], argv[3], argv[4]);
368     }
369     if (stricmp(argv[1], "_del") == 0) {        /*DELETE routine */
370         int iargc = 2;
371         if ((argc > iargc) && (stricmp(argv[iargc], "/s") == 0)) {
372             iargc++;
373             bRecurse = TRUE;
374         }
375         if ((argc > iargc) && (stricmp(argv[iargc], "/q") == 0)) {
376             iargc++;
377             bQuiet = TRUE;
378         }
379         if ((argc > iargc) && (stricmp(argv[iargc], "/s") == 0)) {
380             iargc++;
381             bRecurse = TRUE;
382         }
383         while (iargc < argc) {
384             doremove(bRecurse, bQuiet, argv[iargc]);
385             iargc++;
386         }
387         return 0;
388     }
389     if (strcmp(argv[1], "_ver") == 0) {
390         return _MSC_VER;
391     }
392     if (argc < 3)
393         usuage();
394     if (strcmp(argv[1], "_isOS") == 0)
395         return CheckVersion(argc, argv);
396     if (strcmp(argv[1], "}") == 0) {
397         char v1[4], v2[4], v3[4], v4[4];
398         char v5[132];
399         char *ptr = NULL;
400         char *buf;
401         int maj;
402         int min;
403         int pat, pat2;
404         strcpy(v5, argv[2]);
405         if (argc < 5)
406             usuage();
407         if ((ptr = strtok(argv[2], ". \n")) == NULL)
408             return 0;
409         maj = atoi(ptr);
410         if ((ptr = strtok(NULL, ". \n")) == NULL)
411             return 0;
412         min = atoi(ptr);
413         if ((ptr = strtok(NULL, ". \n")) == NULL)
414             return 0;
415         pat2 = -1;
416         switch (strlen(ptr)) {
417         case 0:
418             usuage();
419         case 1:
420             pat = atoi(ptr);
421             if (isdigit(*ptr) != 0)
422                 break;
423             usuage();
424         case 2:         //ONLY 1.0.44 is interpreted as 1.0.4.4 or 1.0.4a as 1.0.4.a
425             if (isdigit(*ptr) == 0)
426                 usuage();
427             pat = *ptr - '0';
428             ptr++;
429             if (isalpha(*ptr) == 0) {
430                 pat2 = atoi(ptr);
431             } else if (isalpha(*ptr) != 0) {
432                 pat2 = tolower(*ptr) - 'a' + 1;
433             } else
434                 usuage();
435             break;
436         case 3:         //1.0.401 or 1.0.40a are the same; 
437             if ((isdigit(*ptr) == 0)    // first 2 must be digit
438                 || (isdigit(*(ptr + 1)) == 0)
439                 || (*(ptr + 1) != '0' && isdigit(*(ptr + 2)) == 0)      // disallow 1.0.4b0  or 1.0.41a 
440                 )
441                 usuage();
442             pat = *ptr - '0';
443             ptr++;
444             pat2 = atoi(ptr);
445             ptr++;
446             if (isalpha(*ptr))
447                 pat2 = tolower(*ptr) - 'a' + 1;
448             break;
449         default:
450             usuage();
451         }
452         // last can be 1-2 digits or one alpha (if pat2 hasn't been set)
453         if ((ptr = strtok(NULL, ". \n")) != NULL) {
454             if (pat2 >= 0)
455                 usuage();
456             switch (strlen(ptr)) {
457             case 1:
458                 pat2 = (isdigit(*ptr)) ? atoi(ptr) : tolower(*ptr) - 'a' + 1;
459                 break;
460             case 2:
461                 if (isdigit(*ptr) == 0 || isdigit(*(ptr + 1)) == 0)
462                     usuage();
463                 pat2 = atoi(ptr);
464                 break;
465             default:
466                 usuage();
467             }
468         }
469         file = fopen(argv[3], "r");
470         if (file == NULL)
471             usuage();
472         len = filelength(_fileno(file));
473         save = (char *)malloc(len + 1);
474         buf = save;
475         len = fread(buf, sizeof(char), len, file);
476         buf[len] = 0;           //set eof
477         fclose(file);
478         file = fopen(argv[4], "w");
479         if (file == NULL)
480             usuage();
481         sprintf(v1, "%i", maj);
482         sprintf(v2, "%i", min);
483         sprintf(v3, "%i", pat);
484         sprintf(v4, "%02i", pat2);
485         while (1) {
486             ptr = strstr(buf, "%");
487             fwrite(buf, 1, (ptr) ? ptr - buf : strlen(buf), file);      //write file if no % found or up to %
488             if (ptr == NULL)
489                 break;
490             switch (*(ptr + 1)) //skip first scan if buf="1...."
491             {
492             case '1':
493                 fwrite(v1, 1, strlen(v1), file);
494                 ptr++;
495                 break;
496             case '2':
497                 fwrite(v2, 1, strlen(v2), file);
498                 ptr++;
499                 break;
500             case '3':
501                 fwrite(v3, 1, strlen(v3), file);
502                 ptr++;
503                 break;
504             case '4':
505                 fwrite(v4, 1, strlen(v4), file);
506                 ptr++;
507                 break;
508             case '5':
509                 fwrite(v5, 1, strlen(v5), file);
510                 ptr++;
511                 break;
512             default:
513                 fwrite("%", 1, 1, file);        //either % at end of file or no %1...
514                 break;
515             }
516             buf = ptr + 1;
517         }
518         fclose(file);
519         free(save);
520         return 0;
521     }
522     if (strcmp(argv[1], "~") == 0) {    //check for file presence
523         if (fopen(argv[2], "r"))
524             return (0);
525         if (argc < 4)
526             printf("ERROR --- File not present %s\n", argv[2]);
527         else
528             printf("Error---%s\n", argv[3]);
529         exit(0xc000);
530     }
531     if (strcmp(argv[1], "*") == 0) {    /* "[HKEY_CLASSES_ROOT\CLSID\{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}]  @=AFS Client Shell Extension" */
532         if (argc < 3)
533             usuage();
534         for (i = 2; argc >= 3; i++) {
535             char *ssub = strtok(argv[i], "[");
536             BOOL option;
537             char *skey = strtok(NULL, "]");
538             char *sval, *stag;
539             if ((ssub == NULL) || (skey == NULL)) {
540                 printf("format error parameter %s\n", argv[i]);
541                 exit(0xc000);
542             }
543             option = (*ssub == '-');
544             stag = strtok(NULL, "\0");
545             if (stag)
546                 while (*stag == ' ')
547                     stag++;
548             ssub = strtok(skey, "\\");
549             ssub = strtok(NULL, "\0");
550             sval = strtok(stag, "=");
551             sval = strtok(NULL, "\0");
552             switch (option) {
553             case 0:
554                 Addkey(skey, ssub, stag, sval);
555                 break;
556             default:
557                 if (stag)
558                     Addkey(skey, ssub, stag, "");
559                 else
560                     Subkey(skey, ssub);
561                 break;
562             }
563
564             argc -= 1;
565         }
566         return 0;
567     }
568     if (strcmp(argv[1], "@") == 0) {
569         char msg[256], msgt[256];
570         char *ptr;
571         if (argc < 4)
572             usuage();
573         for (i = 3; argc >= 4; i++) {
574
575             char *ssect = strstr(argv[i], "[");
576             char *skey = strstr(ssect, "]");
577             char *sval;
578             if ((ssect == NULL) || (skey == NULL)) {
579                 printf("format error parameter %s\n", argv[i]);
580                 exit(0xc000);
581             }
582             ssect++;
583             *skey = 0;
584             if ((strlen(skey + 1) == 0) || (strlen(ssect) == 0)) {
585                 printf("format error parameter %s\n", argv[i]);
586                 exit(0xc000);
587             }
588             while (*++skey == ' ');
589             sval = strstr(skey, "=");
590             if (sval == NULL) {
591                 printf("format error parameter %s\n", argv[i]);
592                 exit(0xc000);
593             }
594             ptr = sval;
595             while (*--ptr == ' ');
596             *(ptr + 1) = 0;
597             while (*++sval == ' ');
598             if (ptr = strstr(sval, "*DatE*")) { // ok so lets substitute date in this string;
599                 char tmpbuf[32];
600                 *(ptr) = 0;
601                 strcpy(msg, sval);
602                 _tzset();
603                 _strdate(tmpbuf);
604                 strcat(msg, tmpbuf);
605                 strcat(msg, ptr + 6);
606                 sval = msg;
607             }
608             if (ptr = strstr(sval, "*TimE*")) {
609                 char tmpbuf[32];
610                 *(ptr) = 0;
611                 strcpy(msgt, sval);
612                 _strtime(tmpbuf);
613                 strncat(msgt, tmpbuf, 5);
614                 strcat(msgt, ptr + 6);
615                 sval = msgt;
616             }
617             if (WritePrivateProfileString(ssect, skey, sval, argv[2]) == 0) {
618                 LPVOID lpMsgBuf;
619                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
620                               FORMAT_MESSAGE_FROM_SYSTEM |
621                               FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
622                               GetLastError(), MAKELANGID(LANG_NEUTRAL,
623                                                          SUBLANG_DEFAULT),
624                               (LPTSTR) & lpMsgBuf, 0, NULL);
625                 printf("Error writing profile string - %s", lpMsgBuf);
626                 LocalFree(lpMsgBuf);
627                 exit(0xc000);
628             }
629             argc -= 1;
630         }
631         return 0;
632     }
633     strcpy(fname, argv[2]);
634     if (strcmp(argv[1], "+") == 0) {
635         file = fopen(fname, "rb");
636         if (file == NULL)
637             exit(0xc000);
638         len = filelength(_fileno(file));
639         save = (char *)malloc(len + 2);
640         ch = save;
641         *ch++ = 0;              /* a small hack to allow matching /r/n if /n is first character */
642         len = fread(ch, sizeof(char), len, file);
643         file = freopen(fname, "wb", file);
644         while (len-- > 0) {
645             if ((*ch == '\n') && (*(ch - 1) != '\r')) { /*line feed alone */
646                 fputc('\r', file);
647             }
648             fputc(*ch, file);
649             ch++;
650         }
651         fclose(file);
652         free(save);
653         return 0;
654     }
655     if (strcmp(argv[1], "-") == 0) {
656         strcpy(fname, argv[2]);
657         file = fopen(fname, "rb");
658         if (file == NULL)
659             exit(0xc000);
660         len = filelength(_fileno(file));
661         save = (char *)malloc(len + 1);
662         ch = save;
663         len = fread(ch, sizeof(char), len, file);
664         file = freopen(fname, "wb", file);
665         while (len-- > 0) {
666             if (*ch != '\r')
667                 fputc(*ch, file);
668             ch++;
669         }
670         fclose(file);
671         free(save);
672         return 0;
673     }
674     if (strstr(fname, ".et") == NULL)
675         strcat(fname, ".et");
676     file = fopen(fname, "rb");
677     if (file == NULL)
678         exit(0xc000);
679     len = filelength(_fileno(file));
680     save = (char *)malloc(len + 1);
681     ch = save;
682     len = fread(ch, sizeof(char), len, file);
683     file = freopen(fname, "wb", file);
684     while (len-- > 0) {
685         if (*ch != '\r')
686             fputc(*ch, file);
687         ch++;
688     }
689     fclose(file);
690     pvar = (char **)malloc(argc * sizeof(char *));
691     for (i = 1; i < argc - 1; i++)
692         pvar[i] = argv[i + 1];
693     pvar[argc - 1] = NULL;
694     pvar[0] = argv[1];
695     (void)_spawnvp(_P_WAIT, argv[1], pvar);
696     if (save)
697         free(save);
698     if (pvar)
699         free(pvar);
700     return 0;
701 }