ash: an unset dynamic variable should not be dynamic
[oweals/busybox.git] / coreutils / dos2unix.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * dos2unix for BusyBox
4  *
5  * dos2unix '\n' converter 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 GPLv2 or later, see file LICENSE in this source tree.
13  */
14 //config:config DOS2UNIX
15 //config:       bool "dos2unix (5.2 kb)"
16 //config:       default y
17 //config:       help
18 //config:       dos2unix is used to convert a text file from DOS format to
19 //config:       UNIX format, and vice versa.
20 //config:
21 //config:config UNIX2DOS
22 //config:       bool "unix2dos (5.2 kb)"
23 //config:       default y
24 //config:       help
25 //config:       unix2dos is used to convert a text file from UNIX format to
26 //config:       DOS format, and vice versa.
27
28 //applet:IF_DOS2UNIX(APPLET_NOEXEC(dos2unix, dos2unix, BB_DIR_USR_BIN, BB_SUID_DROP, dos2unix))
29 //applet:IF_UNIX2DOS(APPLET_NOEXEC(unix2dos, dos2unix, BB_DIR_USR_BIN, BB_SUID_DROP, unix2dos))
30
31 //kbuild:lib-$(CONFIG_DOS2UNIX) += dos2unix.o
32 //kbuild:lib-$(CONFIG_UNIX2DOS) += dos2unix.o
33
34 //usage:#define dos2unix_trivial_usage
35 //usage:       "[-ud] [FILE]"
36 //usage:#define dos2unix_full_usage "\n\n"
37 //usage:       "Convert FILE in-place from DOS to Unix format.\n"
38 //usage:       "When no file is given, use stdin/stdout.\n"
39 //usage:     "\n        -u      dos2unix"
40 //usage:     "\n        -d      unix2dos"
41 //usage:
42 //usage:#define unix2dos_trivial_usage
43 //usage:       "[-ud] [FILE]"
44 //usage:#define unix2dos_full_usage "\n\n"
45 //usage:       "Convert FILE in-place from Unix to DOS format.\n"
46 //usage:       "When no file is given, use stdin/stdout.\n"
47 //usage:     "\n        -u      dos2unix"
48 //usage:     "\n        -d      unix2dos"
49
50 #include "libbb.h"
51
52 /* This is a NOEXEC applet. Be very careful! */
53
54 enum {
55         CT_UNIX2DOS = 1,
56         CT_DOS2UNIX
57 };
58
59 /* if fn is NULL then input is stdin and output is stdout */
60 static void convert(char *fn, int conv_type)
61 {
62         FILE *in, *out;
63         int ch;
64         char *temp_fn = temp_fn; /* for compiler */
65         char *resolved_fn = resolved_fn;
66
67         in = stdin;
68         out = stdout;
69         if (fn != NULL) {
70                 struct stat st;
71                 int fd;
72
73                 resolved_fn = xmalloc_follow_symlinks(fn);
74                 if (resolved_fn == NULL)
75                         bb_simple_perror_msg_and_die(fn);
76                 in = xfopen_for_read(resolved_fn);
77                 xfstat(fileno(in), &st, resolved_fn);
78
79                 temp_fn = xasprintf("%sXXXXXX", resolved_fn);
80                 fd = xmkstemp(temp_fn);
81                 if (fchmod(fd, st.st_mode) == -1)
82                         bb_simple_perror_msg_and_die(temp_fn);
83                 fchown(fd, st.st_uid, st.st_gid);
84
85                 out = xfdopen_for_write(fd);
86         }
87
88         while ((ch = fgetc(in)) != EOF) {
89                 if (ch == '\r')
90                         continue;
91                 if (ch == '\n')
92                         if (conv_type == CT_UNIX2DOS)
93                                 fputc('\r', out);
94                 fputc(ch, out);
95         }
96
97         if (fn != NULL) {
98                 if (fclose(in) < 0 || fclose(out) < 0) {
99                         unlink(temp_fn);
100                         bb_perror_nomsg_and_die();
101                 }
102                 xrename(temp_fn, resolved_fn);
103                 free(temp_fn);
104                 free(resolved_fn);
105         }
106 }
107
108 int dos2unix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
109 int dos2unix_main(int argc UNUSED_PARAM, char **argv)
110 {
111         int o, conv_type;
112
113         /* See if we are supposed to be doing dos2unix or unix2dos */
114         if (ENABLE_DOS2UNIX
115          && (!ENABLE_UNIX2DOS || applet_name[0] == 'd')
116         ) {
117                 conv_type = CT_DOS2UNIX;
118         } else {
119                 conv_type = CT_UNIX2DOS;
120         }
121
122         /* -u convert to unix, -d convert to dos */
123         o = getopt32(argv, "^" "du" "\0" "u--d:d--u"); /* mutually exclusive */
124
125         /* Do the conversion requested by an argument else do the default
126          * conversion depending on our name.  */
127         if (o)
128                 conv_type = o;
129
130         argv += optind;
131         do {
132                 /* might be convert(NULL) if there is no filename given */
133                 convert(*argv, conv_type);
134         } while (*argv && *++argv);
135
136         return 0;
137 }