c74a1c1d41c13e183d98c55f6c6a49633a1e3bd4
[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;
342     long len;
343     BOOL bRecurse = FALSE;
344     BOOL bQuiet = FALSE;
345     if (argc < 2)
346         usuage();
347     if (strcmp(argv[1], "_sysvar") == 0) {
348         if (argc < 4)
349             usuage();
350         return (SetSysEnv(argc, argv));
351
352     }
353     if (strnicmp(argv[1], "_dir", 4) == 0) {    /*get current directory routine */
354         gencurdir(argv[1]);
355         return 0;
356     }
357     if (strnicmp(argv[1], "_isequal", 4) == 0) {        /*get current directory routine */
358         return isequal(argv[2], argv[3], argv[4]);
359     }
360     if (stricmp(argv[1], "_del") == 0) {        /*DELETE routine */
361         int iargc = 2;
362         if ((argc > iargc) && (stricmp(argv[iargc], "/s") == 0)) {
363             iargc++;
364             bRecurse = TRUE;
365         }
366         if ((argc > iargc) && (stricmp(argv[iargc], "/q") == 0)) {
367             iargc++;
368             bQuiet = TRUE;
369         }
370         if ((argc > iargc) && (stricmp(argv[iargc], "/s") == 0)) {
371             iargc++;
372             bRecurse = TRUE;
373         }
374         while (iargc < argc) {
375             doremove(bRecurse, bQuiet, argv[iargc]);
376             iargc++;
377         }
378         return 0;
379     }
380     if (strcmp(argv[1], "_ver") == 0) {
381         return _MSC_VER;
382     }
383     if (argc < 3)
384         usuage();
385     if (strcmp(argv[1], "_isOS") == 0)
386         return CheckVersion(argc, argv);
387     if (strcmp(argv[1], "}") == 0) {
388         char v1[4], v2[4], v3[4], v4[4];
389         char v5[132];
390         char *ptr = NULL;
391         char *buf;
392         int maj;
393         int min;
394         int pat, pat2;
395         strcpy(v5, argv[2]);
396         if (argc < 5)
397             usuage();
398         if ((ptr = strtok(argv[2], ". \n")) == NULL)
399             return 0;
400         maj = atoi(ptr);
401         if ((ptr = strtok(NULL, ". \n")) == NULL)
402             return 0;
403         min = atoi(ptr);
404         if ((ptr = strtok(NULL, ". \n")) == NULL)
405             return 0;
406         pat2 = -1;
407         switch (strlen(ptr)) {
408         case 0:
409             usuage();
410         case 1:
411             pat = atoi(ptr);
412             if (isdigit(*ptr) != 0)
413                 break;
414             usuage();
415         case 2:         //ONLY 1.0.44 is interpreted as 1.0.4.4 or 1.0.4a as 1.0.4.a
416             if (isdigit(*ptr) == 0)
417                 usuage();
418             pat = *ptr - '0';
419             ptr++;
420             if (isalpha(*ptr) == 0) {
421                 pat2 = atoi(ptr);
422             } else if (isalpha(*ptr) != 0) {
423                 pat2 = tolower(*ptr) - 'a' + 1;
424             } else
425                 usuage();
426             break;
427         case 3:         //1.0.401 or 1.0.40a are the same; 
428             if ((isdigit(*ptr) == 0)    // first 2 must be digit
429                 || (isdigit(*(ptr + 1)) == 0)
430                 || (*(ptr + 1) != '0' && isdigit(*(ptr + 2)) == 0)      // disallow 1.0.4b0  or 1.0.41a 
431                 )
432                 usuage();
433             pat = *ptr - '0';
434             ptr++;
435             pat2 = atoi(ptr);
436             ptr++;
437             if (isalpha(*ptr))
438                 pat2 = tolower(*ptr) - 'a' + 1;
439             break;
440         default:
441             usuage();
442         }
443         // last can be 1-2 digits or one alpha (if pat2 hasn't been set)
444         if ((ptr = strtok(NULL, ". \n")) != NULL) {
445             if (pat2 >= 0)
446                 usuage();
447             switch (strlen(ptr)) {
448             case 1:
449                 pat2 = (isdigit(*ptr)) ? atoi(ptr) : tolower(*ptr) - 'a' + 1;
450                 break;
451             case 2:
452                 if (isdigit(*ptr) == 0 || isdigit(*(ptr + 1)) == 0)
453                     usuage();
454                 pat2 = atoi(ptr);
455                 break;
456             default:
457                 usuage();
458             }
459         }
460         file = fopen(argv[3], "r");
461         if (file == NULL)
462             usuage();
463         len = filelength(_fileno(file));
464         save = (char *)malloc(len + 1);
465         buf = save;
466         len = fread(buf, sizeof(char), len, file);
467         buf[len] = 0;           //set eof
468         fclose(file);
469         file = fopen(argv[4], "w");
470         if (file == NULL)
471             usuage();
472         sprintf(v1, "%i", maj);
473         sprintf(v2, "%i", min);
474         sprintf(v3, "%i", pat);
475         sprintf(v4, "%02i", pat2);
476         while (1) {
477             ptr = strstr(buf, "%");
478             fwrite(buf, 1, (ptr) ? ptr - buf : strlen(buf), file);      //write file if no % found or up to %
479             if (ptr == NULL)
480                 break;
481             switch (*(ptr + 1)) //skip first scan if buf="1...."
482             {
483             case '1':
484                 fwrite(v1, 1, strlen(v1), file);
485                 ptr++;
486                 break;
487             case '2':
488                 fwrite(v2, 1, strlen(v2), file);
489                 ptr++;
490                 break;
491             case '3':
492                 fwrite(v3, 1, strlen(v3), file);
493                 ptr++;
494                 break;
495             case '4':
496                 fwrite(v4, 1, strlen(v4), file);
497                 ptr++;
498                 break;
499             case '5':
500                 fwrite(v5, 1, strlen(v5), file);
501                 ptr++;
502                 break;
503             default:
504                 fwrite("%", 1, 1, file);        //either % at end of file or no %1...
505                 break;
506             }
507             buf = ptr + 1;
508         }
509         fclose(file);
510         free(save);
511         return 0;
512     }
513     if (strcmp(argv[1], "~") == 0) {    //check for file presence
514         if (fopen(argv[2], "r"))
515             return (0);
516         if (argc < 4)
517             printf("ERROR --- File not present %s\n", argv[2]);
518         else
519             printf("Error---%s\n", argv[3]);
520         exit(0xc000);
521     }
522     if (strcmp(argv[1], "*") == 0) {    /* "[HKEY_CLASSES_ROOT\CLSID\{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}]  @=AFS Client Shell Extension" */
523         if (argc < 3)
524             usuage();
525         for (i = 2; argc >= 3; i++) {
526             char *ssub = strtok(argv[i], "[");
527             BOOL option;
528             char *skey = strtok(NULL, "]");
529             char *sval, *stag;
530             if ((ssub == NULL) || (skey == NULL)) {
531                 printf("format error parameter %s\n", argv[i]);
532                 exit(0xc000);
533             }
534             option = (*ssub == '-');
535             stag = strtok(NULL, "\0");
536             if (stag)
537                 while (*stag == ' ')
538                     stag++;
539             ssub = strtok(skey, "\\");
540             ssub = strtok(NULL, "\0");
541             sval = strtok(stag, "=");
542             sval = strtok(NULL, "\0");
543             switch (option) {
544             case 0:
545                 Addkey(skey, ssub, stag, sval);
546                 break;
547             default:
548                 if (stag)
549                     Addkey(skey, ssub, stag, "");
550                 else
551                     Subkey(skey, ssub);
552                 break;
553             }
554
555             argc -= 1;
556         }
557         return 0;
558     }
559     if (strcmp(argv[1], "@") == 0) {
560         char msg[256], msgt[256];
561         char *ptr;
562         if (argc < 4)
563             usuage();
564         for (i = 3; argc >= 4; i++) {
565
566             char *ssect = strstr(argv[i], "[");
567             char *skey = strstr(ssect, "]");
568             char *sval;
569             if ((ssect == NULL) || (skey == NULL)) {
570                 printf("format error parameter %s\n", argv[i]);
571                 exit(0xc000);
572             }
573             ssect++;
574             *skey = 0;
575             if ((strlen(skey + 1) == 0) || (strlen(ssect) == 0)) {
576                 printf("format error parameter %s\n", argv[i]);
577                 exit(0xc000);
578             }
579             while (*++skey == ' ');
580             sval = strstr(skey, "=");
581             if (sval == NULL) {
582                 printf("format error parameter %s\n", argv[i]);
583                 exit(0xc000);
584             }
585             ptr = sval;
586             while (*--ptr == ' ');
587             *(ptr + 1) = 0;
588             while (*++sval == ' ');
589             if (ptr = strstr(sval, "*DatE*")) { // ok so lets substitute date in this string;
590                 char tmpbuf[32];
591                 *(ptr) = 0;
592                 strcpy(msg, sval);
593                 _tzset();
594                 _strdate(tmpbuf);
595                 strcat(msg, tmpbuf);
596                 strcat(msg, ptr + 6);
597                 sval = msg;
598             }
599             if (ptr = strstr(sval, "*TimE*")) {
600                 char tmpbuf[32];
601                 *(ptr) = 0;
602                 strcpy(msgt, sval);
603                 _strtime(tmpbuf);
604                 strncat(msgt, tmpbuf, 5);
605                 strcat(msgt, ptr + 6);
606                 sval = msgt;
607             }
608             if (WritePrivateProfileString(ssect, skey, sval, argv[2]) == 0) {
609                 LPVOID lpMsgBuf;
610                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
611                               FORMAT_MESSAGE_FROM_SYSTEM |
612                               FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
613                               GetLastError(), MAKELANGID(LANG_NEUTRAL,
614                                                          SUBLANG_DEFAULT),
615                               (LPTSTR) & lpMsgBuf, 0, NULL);
616                 printf("Error writing profile string - %s", lpMsgBuf);
617                 LocalFree(lpMsgBuf);
618                 exit(0xc000);
619             }
620             argc -= 1;
621         }
622         return 0;
623     }
624     strcpy(fname, argv[2]);
625     if (strcmp(argv[1], "+") == 0) {
626         file = fopen(fname, "rb");
627         if (file == NULL)
628             exit(0xc000);
629         len = filelength(_fileno(file));
630         save = (char *)malloc(len + 2);
631         ch = save;
632         *ch++ = 0;              /* a small hack to allow matching /r/n if /n is first character */
633         len = fread(ch, sizeof(char), len, file);
634         file = freopen(fname, "wb", file);
635         while (len-- > 0) {
636             if ((*ch == '\n') && (*(ch - 1) != '\r')) { /*line feed alone */
637                 fputc('\r', file);
638             }
639             fputc(*ch, file);
640             ch++;
641         }
642         fclose(file);
643         free(save);
644         return 0;
645     }
646     if (strcmp(argv[1], "-") == 0) {
647         strcpy(fname, argv[2]);
648         file = fopen(fname, "rb");
649         if (file == NULL)
650             exit(0xc000);
651         len = filelength(_fileno(file));
652         save = (char *)malloc(len + 1);
653         ch = save;
654         len = fread(ch, sizeof(char), len, file);
655         file = freopen(fname, "wb", file);
656         while (len-- > 0) {
657             if (*ch != '\r')
658                 fputc(*ch, file);
659             ch++;
660         }
661         fclose(file);
662         free(save);
663         return 0;
664     }
665     if (strstr(fname, ".et") == NULL)
666         strcat(fname, ".et");
667     file = fopen(fname, "rb");
668     if (file == NULL)
669         exit(0xc000);
670     len = filelength(_fileno(file));
671     save = (char *)malloc(len + 1);
672     ch = save;
673     len = fread(ch, sizeof(char), len, file);
674     file = freopen(fname, "wb", file);
675     while (len-- > 0) {
676         if (*ch != '\r')
677             fputc(*ch, file);
678         ch++;
679     }
680     fclose(file);
681     pvar = (char **)malloc(argc * sizeof(char *));
682     for (i = 1; i < argc - 1; i++)
683         pvar[i] = argv[i + 1];
684     pvar[argc - 1] = NULL;
685     pvar[0] = argv[1];
686     (void)_spawnvp(_P_WAIT, argv[1], pvar);
687     if (save)
688         free(save);
689     if (pvar)
690         free(pvar);
691     return 0;
692 }