/*	MailCarrier.m

	See the .h file for additional notes.
	Written in January 1991 by Eric Celeste.
														 */

#import "MailCarrier.h"
#import <stdio.h>
#import <stdlib.h>
#import <strings.h>
#import <mach.h>
#import <mach_interface.h>
#import <appkit/Application.h>
#import <appkit/Control.h>
#import <appkit/Listener.h>
#import <appkit/Pasteboard.h>

@implementation MailCarrier

/*	Note that init gets called too early in the process of the
	application's launch to let us set up the listener right here.
	Thus, we make ourself a delegate of the application here, and
	then take care of the listener later, once the application
	is done launching.
																	*/
- init
{
	[super init];
	
	[NXApp setDelegate:self];
	
	return self;
}

/*	Now it is late enough for the listener to be ready to deal with
	our demands. Here we make sure the listener knows to send us
	all the messages meant for services. While we are here, we also
	make sure that the recipient field is set up to point back to 
	the user (since I assume this service will often be used to
	archive stuff into the users own mail).
																	*/
- appDidInit:sender
{
	[[NXApp appListener] setServicesDelegate:self];
	[recipient setStringValue:NXUserName()];
	
	return self;
}

/*	This is the heart of my service. It gets quite messy, but it
	seems that most of this mess is really needed. In particular,
	it is vital that "types" gets called before "readType:data:length:"
	or else the pasteboard will never do the right thing.
																	*/
- carryMail:myPasteboard userData:(const char *)userData error:(char **)message
{
	const NXAtom *myTypes;		/* absorbs the result of types message */
	char *data;					/* data returned by the pasteboard */
	int   length;				/* length of data returned by the pasteboard */
	char *text;					/* holds copy of data from the pasteboard */
	const char *name;			/* holds a pointer to the user's name */
	FILE *stream;				/* our connection to the outside world */
	char *command;				/* the command string we send outside */
	
	myTypes = [myPasteboard types];
	
	if ([myPasteboard readType:NXAsciiPboardType data:&data length:&length]) {
	
		/* this bit of work ensures there is a null at the text's end */
		text = malloc(length+1);
		strncpy(text, data, length);
		text[length]='\0';
		
		/* let the user know what has been sent */
		[content setStringValue:(const char *)text];
		
		/* make room for and create command using the name at the outlet */
		command = malloc(20 + strlen(name = [recipient stringValue]));
		strcpy(command,"/usr/lib/sendmail ");
		strcat(command,name);
		
		/* here is where we send the command out to unix */
		stream = popen((const char *)command,"w");
		if (stream) {
			/* and we put the message into the command's standard input */
			fputs((const char *)text, stream);
			pclose(stream);
			/* this is a small signal to the user that all went well */
			[notes setIntValue:++numberOfMessages];
		} else {
			/* and this signals that all went not-so-well */
			[notes setStringValue:"Failed to allocate the stream!"];
		}
				
		/* don't forget to let go of memory */
		free(text);
		/* use vm_deallocate since readType above used Mach to allocate  */
		vm_deallocate(task_self(), (vm_address_t)data, (vm_size_t)length);
		
	} else {
	
		/* making sure the user is not misled about our failure */
		[content setStringValue:""];
		[notes setStringValue:"Failed to read the pasteboard!"];
		
	}
	
	return self;
}

@end
