/* (c) Copyright 1993 by Mike W. Meyer
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of Mike W.
 * Meyer not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission.  Mike W. Meyer makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * MIKE W. MEYER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL MIKE W. MEYER BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>

#include <proto/exec.h>
#include <proto/dos.h>

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <errno.h>

#include "common.h"
#include "xmalloc.h"

#define BADCHARS	"#?()|[]%<>:;$&*\\\ \t\`\""

int overwrite_files = 0 ;
static char *output_fname = NULL;
extern int errno, _OSERR ;
void os_perror(char *) ;

/* Generate a message-id */
char *
os_genid(void) {
	static struct Task *task = NULL ;
	static time_t now ;
	static char hostname[32] ;
	char *result ;

	if (task == NULL) {
		task = FindTask(NULL) ;
		time(&now) ;
		if (GetVar("hostname", hostname, sizeof(hostname), 0) < 0)
			strcpy(hostname, "random-pc") ;
		}
	result = malloc(25 + strlen(hostname)) ;
	sprintf(result, "%d.%d@%s", (long) task, now++, hostname) ;
	return result ;
	}
	
/* Create and return a directory for a message-id */
char *
os_idtodir(char *id) {
	static char buf[512] ;
	char *p ;
	BPTR *dir ;

	if (p = getenv("METAMAIL_P_DIR")) strcpy(buf, p) ;
	else strcpy(buf, "t:");

	if (!(p = getenv("USER")) && !(p = getenv("USERNAME"))) p = "anonymous" ;
	AddPart(buf, p, sizeof(buf)) ;
	
	if (mkdir(buf) == -1 && errno != EEXIST && _OSERR != ERROR_OBJECT_EXISTS) {
		os_perror(buf) ;
		return NULL ;
		}

	p = buf + strlen(buf) ;
	*p++ = '/' ;
	while (*id) {
		if (isprint(*id) && !strchr(BADCHARS, *id)) *p++ = *id ;
		id += 1 ;
		}
	*p  = '\0' ;

	if (mkdir(buf) == -1 && errno != EEXIST && _OSERR != ERROR_OBJECT_EXISTS) {
		os_perror(buf) ;
		return NULL ;
		}
	strcpy(p, "/") ;
	return buf ;
	}

/* Delete the directory created by os_idtodir() */
void
os_donewithdir(char *dir) {

	/* Chop off trailing slash */
	dir[strlen(dir) - 1] = '\0' ;
	rmdir(dir) ;
	}
	
/* Create a new file of name "fname". Clean up the name first */
FILE *
os_newtypedfile(char *fname, char *contentType, int binary) {
	char *p, *name, *description, buf[512] ;
	FILE *outfile = NULL ;
	static int filesuffix = 0 ;

	name = FilePart(fname) ;

	/* No BADCHARS */
	for (p = name; *p; p += 1)
		if (!isprint(*p) || strchr(BADCHARS, *p)) *p = 'X' ;

	/* Add a count if we don't have a name, or we aren't overwriting */
	if (!*fname || !overwrite_files) {
		if (*fname) strcpy(buf, fname) ;
		else {
			name = "part" ;
			sprintf(buf, "part.%d", ++filesuffix) ;
			}
		while (outfile = fopen(buf, "r")) {
			if (outfile) fclose(outfile) ;
			sprintf(buf, "%s.%d", name, ++filesuffix) ;
			}
		name = buf ;
		fclose(outfile) ;
		}

	if (!(outfile = fopen(name, "w"))) os_perror(name) ;

	if (output_fname) free(output_fname) ;
	output_fname = strsave(name) ;
	description = xmalloc(strlen(name) + 6) ;
	strcpy(description, name) ;
	strcat(description, ".desc") ;
	(void) rename(TEMPFILENAME, description) ;
	free(description) ;

	fprintf(stdout, "%s (%s)\n", output_fname, contentType) ;
	return outfile ;
	}

/* Warn user that MD5 digest didn't match */
void
os_warnMD5mismatch(void) {
	char *warning;

	warning = xmalloc(strlen(output_fname) + 100);
	sprintf(warning, "%s was corrupted in transit", output_fname);
	warn(warning);
	free(warning);
	}

/* Report an error (in errno) concerning a filename */
void
os_perror(char *file) {
	if (errno != EOSERR) perror(file);
	else poserr(file) ;
	}
