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