7fbc9a7317d7bfa4d6b7ff6b93c27dc521f98694
[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             default:
456                 usuage();
457             }
458         }
459         file = fopen(argv[3], "r");
460         if (file == NULL)
461             usuage();
462         len = filelength(_fileno(file));
463         buf = (char *)malloc(len + 1);
464         len = fread(buf, sizeof(char), len, file);
465         buf[len] = 0;           //set eof
466         fclose(file);
467         file = fopen(argv[4], "w");
468         if (file == NULL)
469             usuage();
470         sprintf(v1, "%i", maj);
471         sprintf(v2, "%i", min);
472         sprintf(v3, "%i", pat);
473         sprintf(v4, "%02i", pat2);
474         while (1) {
475             ptr = strstr(buf, "%");
476             fwrite(buf, 1, (ptr) ? ptr - buf : strlen(buf), file);      //write file if no % found or up to %
477             if (ptr == NULL)
478                 break;
479             switch (*(ptr + 1)) //skip first scan if buf="1...."
480             {
481             case '1':
482                 fwrite(v1, 1, strlen(v1), file);
483                 ptr++;
484                 break;
485             case '2':
486                 fwrite(v2, 1, strlen(v2), file);
487                 ptr++;
488                 break;
489             case '3':
490                 fwrite(v3, 1, strlen(v3), file);
491                 ptr++;
492                 break;
493             case '4':
494                 fwrite(v4, 1, strlen(v4), file);
495                 ptr++;
496                 break;
497             case '5':
498                 fwrite(v5, 1, strlen(v5), file);
499                 ptr++;
500                 break;
501             default:
502                 fwrite("%", 1, 1, file);        //either % at end of file or no %1...
503                 break;
504             }
505             buf = ptr + 1;
506         }
507         fclose(file);
508         return 0;
509     }
510     if (strcmp(argv[1], "~") == 0) {    //check for file presence
511         if (fopen(argv[2], "r"))
512             return (0);
513         if (argc < 4)
514             printf("ERROR --- File not present %s\n", argv[2]);
515         else
516             printf("Error---%s\n", argv[3]);
517         exit(0xc000);
518     }
519     if (strcmp(argv[1], "*") == 0) {    /* "[HKEY_CLASSES_ROOT\CLSID\{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}]  @=AFS Client Shell Extension" */
520         if (argc < 3)
521             usuage();
522         for (i = 2; argc >= 3; i++) {
523             char *ssub = strtok(argv[i], "[");
524             BOOL option;
525             char *skey = strtok(NULL, "]");
526             char *sval, *stag;
527             if ((ssub == NULL) || (skey == NULL)) {
528                 printf("format error parameter %s\n", argv[i]);
529                 exit(0xc000);
530             }
531             option = (*ssub == '-');
532             stag = strtok(NULL, "\0");
533             if (stag)
534                 while (*stag == ' ')
535                     stag++;
536             ssub = strtok(skey, "\\");
537             ssub = strtok(NULL, "\0");
538             sval = strtok(stag, "=");
539             sval = strtok(NULL, "\0");
540             switch (option) {
541             case 0:
542                 Addkey(skey, ssub, stag, sval);
543                 break;
544             default:
545                 if (stag)
546                     Addkey(skey, ssub, stag, "");
547                 else
548                     Subkey(skey, ssub);
549                 break;
550             }
551
552             argc -= 1;
553         }
554         return 0;
555     }
556     if (strcmp(argv[1], "@") == 0) {
557         char msg[256], msgt[256];
558         char *ptr;
559         if (argc < 4)
560             usuage();
561         for (i = 3; argc >= 4; i++) {
562
563             char *ssect = strstr(argv[i], "[");
564             char *skey = strstr(ssect, "]");
565             char *sval;
566             if ((ssect == NULL) || (skey == NULL)) {
567                 printf("format error parameter %s\n", argv[i]);
568                 exit(0xc000);
569             }
570             ssect++;
571             *skey = 0;
572             if ((strlen(skey + 1) == 0) || (strlen(ssect) == 0)) {
573                 printf("format error parameter %s\n", argv[i]);
574                 exit(0xc000);
575             }
576             while (*++skey == ' ');
577             sval = strstr(skey, "=");
578             if (sval == NULL) {
579                 printf("format error parameter %s\n", argv[i]);
580                 exit(0xc000);
581             }
582             ptr = sval;
583             while (*--ptr == ' ');
584             *(ptr + 1) = 0;
585             while (*++sval == ' ');
586             if (ptr = strstr(sval, "*DatE*")) { // ok so lets substitute date in this string;
587                 char tmpbuf[32];
588                 *(ptr) = 0;
589                 strcpy(msg, sval);
590                 _tzset();
591                 _strdate(tmpbuf);
592                 strcat(msg, tmpbuf);
593                 strcat(msg, ptr + 6);
594                 sval = msg;
595             }
596             if (ptr = strstr(sval, "*TimE*")) {
597                 char tmpbuf[32];
598                 *(ptr) = 0;
599                 strcpy(msgt, sval);
600                 _strtime(tmpbuf);
601                 strncat(msgt, tmpbuf, 5);
602                 strcat(msgt, ptr + 6);
603                 sval = msgt;
604             }
605             if (WritePrivateProfileString(ssect, skey, sval, argv[2]) == 0) {
606                 LPVOID lpMsgBuf;
607                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
608                               FORMAT_MESSAGE_FROM_SYSTEM |
609                               FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
610                               GetLastError(), MAKELANGID(LANG_NEUTRAL,
611                                                          SUBLANG_DEFAULT),
612                               (LPTSTR) & lpMsgBuf, 0, NULL);
613                 printf("Error writing profile string - %s", lpMsgBuf);
614                 LocalFree(lpMsgBuf);
615                 exit(0xc000);
616             }
617             argc -= 1;
618         }
619         return 0;
620     }
621     strcpy(fname, argv[2]);
622     if (strcmp(argv[1], "+") == 0) {
623         file = fopen(fname, "rb");
624         if (file == NULL)
625             exit(0xc000);
626         len = filelength(_fileno(file));
627         ch = (char *)malloc(len + 2);
628         *ch++ = 0;              /* a small hack to allow matching /r/n if /n is first character */
629         len = fread(ch, sizeof(char), len, file);
630         file = freopen(fname, "wb", file);
631         while (len-- > 0) {
632             if ((*ch == '\n') && (*(ch - 1) != '\r')) { /*line feed alone */
633                 fputc('\r', file);
634             }
635             fputc(*ch, file);
636             ch++;
637         }
638         fclose(file);
639         return 0;
640     }
641     if (strcmp(argv[1], "-") == 0) {
642         strcpy(fname, argv[2]);
643         file = fopen(fname, "rb");
644         if (file == NULL)
645             exit(0xc000);
646         len = filelength(_fileno(file));
647         ch = (char *)malloc(len + 1);
648         len = fread(ch, sizeof(char), len, file);
649         file = freopen(fname, "wb", file);
650         while (len-- > 0) {
651             if (*ch != '\r')
652                 fputc(*ch, file);
653             ch++;
654         }
655         fclose(file);
656         return 0;
657     }
658     if (strstr(fname, ".et") == NULL)
659         strcat(fname, ".et");
660     file = fopen(fname, "rb");
661     if (file == NULL)
662         exit(0xc000);
663     len = filelength(_fileno(file));
664     ch = (char *)malloc(len + 1);
665     len = fread(ch, sizeof(char), len, file);
666     file = freopen(fname, "wb", file);
667     while (len-- > 0) {
668         if (*ch != '\r')
669             fputc(*ch, file);
670         ch++;
671     }
672     fclose(file);
673     pvar = (char **)malloc(argc * sizeof(char *));
674     for (i = 1; i < argc - 1; i++)
675         pvar[i] = argv[i + 1];
676     pvar[argc - 1] = NULL;
677     pvar[0] = argv[1];
678     l = _spawnvp(_P_WAIT, argv[1], pvar);
679     if (ch)
680         free(ch);
681     if (pvar)
682         free(pvar);
683     return 0;
684 }