static char rcsid[] = "@(#)$Id: elmstringconvert.c,v 1.12 2006/04/09 07:37:30 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.12 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "elmutil.h"
#include "s_me.h"
#include "s_elm.h"
#include "cs_imp.h"
DEBUG_VAR(Debug,__FILE__,"util");
extern char *optarg;
extern int optind;
static charset_t source_charset = NULL;
static charset_t target_charset = NULL;
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
static int copy_between_fds P_((FILE *infd,FILE *fd,const char *name));
static int copy_between_fds(infd,fd,name)
FILE *infd;
FILE *fd;
const char *name;
{
char buffer[1024 * 1024 +1]; /* 1 MB */
int line_len;
int count = 0;
int errcount = 0;
while (0 < (line_len =
mail_gets(buffer, sizeof buffer -1, infd))) {
int l;
struct string * in_str = new_string(source_charset);
struct string * out_str = NULL;
char * res;
int reslen;
int written;
int errors = 0;
if ('\n' == buffer[line_len-1])
count++;
else {
DPRINT(Debug,7,(&Debug,
"Too long line (read %d bytes)\n",
line_len));
lib_error(CATGETS(elm_msg_cat, MeSet, MeLineTooLongOnFile,
"Warning: Line %d too long on file %s: %.50s..."),
count+1,name,buffer);
}
l = add_streambytes_to_string(in_str,line_len,s2us(buffer),&errors);
if (l < line_len) {
DPRINT(Debug,7,(&Debug,
"Feeding of line failed (handled %d bytes from %d)\n",
l,line_len));
lib_error(CATGETS(elm_msg_cat, MeSet, MeLineBadDataOnFile,
"Warning: Bad data on line %d on file %s: %.50s..."),
count,name,buffer);
errcount++;
}
if (errors) {
DPRINT(Debug,7,(&Debug,
"Feeding of line failed: %d errors\n",
errors));
errcount += errors;
}
out_str = convert_string(target_charset,in_str,0);
bytestream_from_string(out_str,&res,&reslen);
written = 0;
while (written < reslen) {
int X = fwrite(res + written, 1, reslen - written,fd);
if (X < 1) {
errcount++;
break;
}
written += X;
}
free_string(&in_str);
free_string(&out_str);
}
if (errcount)
return 0;
return 1;
}
static int copy_to_fd P_((FILE *fd,int argc,char *argv[]));
static int copy_to_fd(fd,argc,argv)
FILE *fd;
int argc;
char *argv[];
{
if (optind < argc) {
int errcount = 0;
for (;optind < argc; optind++) {
FILE * X;
if (0 != access(argv[optind],READ_ACCESS)) {
int errcode = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotReadable,
"File %.50s is not readable: %s"),
argv[optind], error_description(errcode));
errcount++;
continue;
}
X = fopen(argv[optind],"r");
if (!X) {
int errcode = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotReadable,
"File %.50s is not readable: %s"),
argv[optind], error_description(errcode));
errcount++;
continue;
}
if (!copy_between_fds(X,fd,argv[optind]))
errcount++;
if (ferror(X)) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorReading,
"Error reading from %.50s"),
argv[optind]);
errcount++;
}
fclose(X);
}
if (errcount) {
return 0;
}
} else {
return copy_between_fds(stdin,fd,"(stdin)");
}
return 1;
}
int main P_((int argc, char *argv[]));
int main(argc, argv)
int argc;
char *argv[];
{
int err = 0;
int c;
int global = 0;
char *targetfile = NULL;
#if DEBUG
init_debugfile("ELMSTRINGCONVERT");
#endif
locale_init();
user_init();
init_defaults();
while ((c = getopt(argc, argv, "Gd:w:S:T:")) != EOF) {
charset_t wanted_charset;
switch(c) {
case 'S':
wanted_charset = MIME_name_to_charset(optarg,0);
if (!wanted_charset) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeArgsCharsetSUnknown,
"Charset %s given with -S flag is unknown."),
optarg);
err = 1;
goto fail;
}
if (! wanted_charset->map_info) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeArgsCharsetSNeedsMap,
"Warning: Charset %s given on -S flag needs map defination (on %s file)"),
optarg,
global ? system_mime_charsets : USER_MIME_CHARSETS);
}
source_charset = wanted_charset;
break;
case 'T':
wanted_charset = MIME_name_to_charset(optarg,0);
if (!wanted_charset) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeArgsCharsetTUnknown,
"Charset %s given with -T flag is unknown."),
optarg);
err = 1;
goto fail;
}
if (! wanted_charset->map_info) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeArgsCharsetTNeedsMap,
"Warning: Charset %s given on -T flag needs map defination (on %s file)"),
optarg,
global ? system_mime_charsets : USER_MIME_CHARSETS);
}
target_charset = wanted_charset;
break;
case 'G':
global++;
break;
case 'd':
#if DEBUG
set_debugging(optarg);
#else
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmArgsIngoringDebug,
"Warning: system created without debugging enabled - request ignored\n"));
#endif
break;
case 'w' :
targetfile = optarg;
if (0 != access(targetfile,WRITE_ACCESS)) {
int errcode = errno;
if (errcode != ENOENT) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
targetfile, error_description(errcode));
err++;
goto fail;
}
}
break;
case '?':
err = 1;
goto fail;
}
}
elm_sfprintf(version_buff, sizeof version_buff,
FRM("%s PL%s"), VERSION, PATCHLEVEL);
#ifdef DEBUG
{
int d = panic_dprint("\n\
======================================================\n\
Debug output of the ELMSTRINGCONVERT program (version %s).\n",
version_buff);
if (d >= 50) {
#if 0
panic_dprint("WARNING: Edit manually out sensitive information from that file!\n");
lower_prompt("WARNING: Debug file may include passwords -- edit it!");
sleep(5+sleepmsg);
#endif
}
}
#endif
if (!global)
read_rc_file(0);
else
post_init_check(0);
if (!source_charset)
source_charset = system_charset;
if (!target_charset)
target_charset = system_charset;
if (source_charset != target_charset &&
(!(CS_mapping & charset_properties(source_charset)) ||
!(CS_mapping & charset_properties(target_charset)))) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCantConvertCharset,
"Can't convert text from charset %s to charset %s"),
source_charset -> MIME_name ?
source_charset -> MIME_name : "<no MIME name>",
target_charset -> MIME_name ?
target_charset -> MIME_name : "<no MIME name>");
err = 1;
goto fail;
}
if (targetfile) {
char * tmp = elm_message(FRM("%s.N"),targetfile);
int errcode = can_open(tmp,"w");
FILE *f;
if (errcode) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(errcode));
err++;
free(tmp);
goto fail;
}
f = fopen(tmp,"w");
if (!f) {
int errcode = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(errcode));
err++;
free(tmp);
goto fail;
}
if (!copy_to_fd(f,argc,argv)) {
fclose(f);
unlink(tmp);
err++;
free(tmp);
goto fail;
}
if (EOF == fclose(f)) {
int errcode = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(errcode));
unlink(tmp);
err++;
free(tmp);
goto fail;
}
if (0 != rename(tmp,targetfile)) {
int errcode = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %.30s"),
targetfile, error_description(errcode));
err++;
free(tmp);
goto fail;
}
free(tmp);
}
else {
if (!copy_to_fd(stdout,argc,argv))
err = 1;
}
fail:
if (err)
lib_error(CATGETS(elm_msg_cat, MeSet, MeProgFailed,
"%s failed; exit code=%d"),
argv[0],err);
return err;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1