1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <sys/stat.h>
7
8 #define BUFSIZE (1024*8)
9 static void to_unix(char* buf);
10 static void unix_to_dos(char* buf2, const char* buf);
11
usage()12 int usage()
13 {
14 fprintf(stderr, "usage: line_endings unix|dos FILES\n"
15 "\n"
16 "Convert FILES to either unix or dos line endings.\n");
17 return 1;
18 }
19
20 typedef struct Node {
21 struct Node *next;
22 char buf[BUFSIZE*2+3];
23 } Node;
24
25 int
main(int argc,char ** argv)26 main(int argc, char** argv)
27 {
28 enum { UNIX, DOS } ending;
29 int i;
30
31 if (argc < 2) {
32 return usage();
33 }
34
35 if (0 == strcmp("unix", argv[1])) {
36 ending = UNIX;
37 }
38 else if (0 == strcmp("dos", argv[1])) {
39 ending = DOS;
40 }
41 else {
42 return usage();
43 }
44
45 for (i=2; i<argc; i++) {
46 int fd;
47 int len;
48
49 // force implied
50 chmod(argv[i], S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
51
52 fd = open(argv[i], O_RDWR);
53 if (fd < 0) {
54 fprintf(stderr, "unable to open file for read/write: %s\n", argv[i]);
55 return 1;
56 }
57
58 len = lseek(fd, 0, SEEK_END);
59 lseek(fd, 0, SEEK_SET);
60
61 if (len > 0) {
62 Node* root = malloc(sizeof(Node));
63 Node* node = root;
64 node->buf[0] = 0;
65
66 while (len > 0) {
67 node->next = malloc(sizeof(Node));
68 node = node->next;
69 node->next = NULL;
70
71 char buf[BUFSIZE+2];
72 ssize_t amt;
73 ssize_t amt2 = len < BUFSIZE ? len : BUFSIZE;
74 amt = read(fd, buf, amt2);
75 if (amt != amt2) {
76 fprintf(stderr, "unable to read file: %s\n", argv[i]);
77 return 1;
78 }
79 buf[amt2] = '\0';
80 to_unix(buf);
81 if (ending == UNIX) {
82 strcpy(node->buf, buf);
83 } else {
84 char buf2[(BUFSIZE*2)+3];
85 unix_to_dos(buf2, buf);
86 strcpy(node->buf, buf2);
87 }
88 len -= amt2;
89 }
90
91 (void)ftruncate(fd, 0);
92 lseek(fd, 0, SEEK_SET);
93 while (root) {
94 ssize_t amt2 = strlen(root->buf);
95 if (amt2 > 0) {
96 ssize_t amt = write(fd, root->buf, amt2);
97 if (amt != amt2) {
98 fprintf(stderr, "unable to write file: %s\n", argv[i]);
99 return 1;
100 }
101 }
102 node = root;
103 root = root->next;
104 free(node);
105 }
106 }
107 close(fd);
108 }
109 return 0;
110 }
111
112 void
to_unix(char * buf)113 to_unix(char* buf)
114 {
115 char* p = buf;
116 char* q = buf;
117 while (*p) {
118 if (p[0] == '\r' && p[1] == '\n') {
119 // dos
120 *q = '\n';
121 p += 2;
122 q += 1;
123 }
124 else if (p[0] == '\r') {
125 // old mac
126 *q = '\n';
127 p += 1;
128 q += 1;
129 }
130 else {
131 *q = *p;
132 p += 1;
133 q += 1;
134 }
135 }
136 *q = '\0';
137 }
138
139 void
unix_to_dos(char * buf2,const char * buf)140 unix_to_dos(char* buf2, const char* buf)
141 {
142 const char* p = buf;
143 char* q = buf2;
144 while (*p) {
145 if (*p == '\n') {
146 q[0] = '\r';
147 q[1] = '\n';
148 q += 2;
149 p += 1;
150 } else {
151 *q = *p;
152 p += 1;
153 q += 1;
154 }
155 }
156 *q = '\0';
157 }
158
159