made "test" an ash built-in.
[oweals/busybox.git] / coreutils / dos2unix.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * dos2unix for BusyBox
4  *
5  * dos2unix '\n' convertor 0.5.0
6  * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997)
7  * Copyright 1997,.. by Peter Hanecak <hanecak@megaloman.sk>.
8  * All rights reserved.
9  *
10  * dos2unix filters reading input from stdin and writing output to stdout.
11  *
12  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
13 */
14
15 #include <string.h>
16 #include <unistd.h>
17 #include <stdint.h>
18 #include <fcntl.h>
19 #include "busybox.h"
20
21 enum ConvType {
22         CT_UNIX2DOS = 1,
23         CT_DOS2UNIX
24 } ConvType;
25
26 /* if fn is NULL then input is stdin and output is stdout */
27 static int convert(char *fn)
28 {
29         FILE *in, *out;
30         int i;
31
32         if (fn != NULL) {
33                 in = bb_xfopen(fn, "rw");
34                 /*
35                    The file is then created with mode read/write and
36                    permissions 0666 for glibc 2.0.6 and earlier or
37                    0600  for glibc  2.0.7 and  later.
38                  */
39                 snprintf(bb_common_bufsiz1, sizeof(bb_common_bufsiz1), "%sXXXXXX", fn);
40                 /*
41                    sizeof bb_common_bufsiz1 is 4096, so it should be big enough to
42                    hold the full path.  However if the output is truncated the
43                    subsequent call to mkstemp would fail.
44                  */
45                 if ((i = mkstemp(&bb_common_bufsiz1[0])) == -1
46                         || chmod(bb_common_bufsiz1, 0600) == -1) {
47                         bb_perror_nomsg_and_die();
48                 }
49                 out = fdopen(i, "w+");
50                 if (!out) {
51                         close(i);
52                         remove(bb_common_bufsiz1);
53                 }
54         } else {
55                 in = stdin;
56                 out = stdout;
57         }
58
59         while ((i = fgetc(in)) != EOF) {
60                 if (i == '\r')
61                         continue;
62                 if (i == '\n') {
63                         if (ConvType == CT_UNIX2DOS)
64                                 fputc('\r', out);
65                         fputc('\n', out);
66                         continue;
67                 }
68                 fputc(i, out);
69         }
70
71         if (fn != NULL) {
72                 if (fclose(in) < 0 || fclose(out) < 0) {
73                         bb_perror_nomsg();
74                         remove(bb_common_bufsiz1);
75                         return -2;
76                 }
77                 /* Assume they are both on the same filesystem (which
78                  * should be true since we put them into the same directory
79                  * so we _should_ be ok, but you never know... */
80                 if (rename(bb_common_bufsiz1, fn) < 0) {
81                         bb_perror_msg("cannot rename '%s' as '%s'", bb_common_bufsiz1, fn);
82                         return -1;
83                 }
84         }
85
86         return 0;
87 }
88
89 int dos2unix_main(int argc, char *argv[])
90 {
91         int o;
92
93         /* See if we are supposed to be doing dos2unix or unix2dos */
94         if (bb_applet_name[0] == 'd') {
95                 ConvType = CT_DOS2UNIX; /*2 */
96         } else {
97                 ConvType = CT_UNIX2DOS; /*1 */
98         }
99         /* -u and -d are mutally exclusive */
100         bb_opt_complementally = "?:u--d:d--u";
101         /* process parameters */
102         /* -u convert to unix */
103         /* -d convert to dos  */
104         o = bb_getopt_ulflags(argc, argv, "du");
105
106         /* Do the conversion requested by an argument else do the default
107          * conversion depending on our name.  */
108         if (o)
109                 ConvType = o;
110
111         if (optind < argc) {
112                 while (optind < argc)
113                         if ((o = convert(argv[optind++])) < 0)
114                                 break;
115         } else
116                 o = convert(NULL);
117
118         return o;
119 }