#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#define BUFSIZE (1024*8)
static void to_unix(char* buf);
static void unix_to_dos(char* buf2, const char* buf);
int usage()
{
fprintf(stderr, "usage: line_endings unix|dos FILES\n"
"\n"
"Convert FILES to either unix or dos line endings.\n");
return 1;
}
typedef struct Node {
struct Node *next;
char buf[BUFSIZE*2+3];
} Node;
int
main(int argc, char** argv)
{
enum { UNIX, DOS } ending;
int i;
if (argc < 2) {
return usage();
}
if (0 == strcmp("unix", argv[1])) {
ending = UNIX;
}
else if (0 == strcmp("dos", argv[1])) {
ending = DOS;
}
else {
return usage();
}
for (i=2; i<argc; i++) {
int fd;
int len;
// force implied
chmod(argv[i], S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
fd = open(argv[i], O_RDWR);
if (fd < 0) {
fprintf(stderr, "unable to open file for read/write: %s\n", argv[i]);
return 1;
}
len = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if (len > 0) {
Node* root = malloc(sizeof(Node));
Node* node = root;
node->buf[0] = 0;
while (len > 0) {
node->next = malloc(sizeof(Node));
node = node->next;
node->next = NULL;
char buf[BUFSIZE+2];
ssize_t amt;
ssize_t amt2 = len < BUFSIZE ? len : BUFSIZE;
amt = read(fd, buf, amt2);
if (amt != amt2) {
fprintf(stderr, "unable to read file: %s\n", argv[i]);
return 1;
}
buf[amt2] = '\0';
to_unix(buf);
if (ending == UNIX) {
strcpy(node->buf, buf);
} else {
char buf2[(BUFSIZE*2)+3];
unix_to_dos(buf2, buf);
strcpy(node->buf, buf2);
}
len -= amt2;
}
(void)ftruncate(fd, 0);
lseek(fd, 0, SEEK_SET);
while (root) {
ssize_t amt2 = strlen(root->buf);
if (amt2 > 0) {
ssize_t amt = write(fd, root->buf, amt2);
if (amt != amt2) {
fprintf(stderr, "unable to write file: %s\n", argv[i]);
return 1;
}
}
node = root;
root = root->next;
free(node);
}
}
close(fd);
}
return 0;
}
void
to_unix(char* buf)
{
char* p = buf;
char* q = buf;
while (*p) {
if (p[0] == '\r' && p[1] == '\n') {
// dos
*q = '\n';
p += 2;
q += 1;
}
else if (p[0] == '\r') {
// old mac
*q = '\n';
p += 1;
q += 1;
}
else {
*q = *p;
p += 1;
q += 1;
}
}
*q = '\0';
}
void
unix_to_dos(char* buf2, const char* buf)
{
const char* p = buf;
char* q = buf2;
while (*p) {
if (*p == '\n') {
q[0] = '\r';
q[1] = '\n';
q += 2;
p += 1;
} else {
*q = *p;
p += 1;
q += 1;
}
}
*q = '\0';
}