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