/*********************************************************** * AOP mail agent library functions * ************************************************************ * Description: This library is linked into the interpreter * * code. It passes messages between the mail agent and the * * mail capability program. The interpreter calls the * * initilization function. * * * * Created by: avrami tzur * * At: Wed Sep 2 16:10:51 1992 * ***********************************************************/ /* INCLUDES */ # include # include /* for stat() ** needs types.h ***/ # include # include # include # include # include # include # include "structures.h" # include "AOPmail.h" # include "AOPcomm.h" extern int errno; /* DECLARATIONS */ void aopMailEntryFunction(int request_num); void readMailPipe(int pipe_id); static void mailInit(); static void mailExit(); static void mailProcessMsg(int msg_type, char *data); static void endMailProcess(); static void displayMailToUser(int arity, module_ptr agent, struct term ** args,void *data); static void sendMailToUser(int arity, module_ptr agent, struct term ** args,void *data); static void sendMailToAgent(int arity, module_ptr agent, struct term ** args,void *data); static void mailControl(int arity, module_ptr agent, struct term ** args,void *data); static void mailFileHandling(int arity, module_ptr agent, struct term ** args,void *data); static void writeToMailPipe(int msg_type, int data_length, void *data); static void displayMailMsg(mail_message *msg); static void notifyAgent(mail_message *msg); static mail_message *termMail2MsgMail(int arity, module_ptr agent, struct term ** args); static void sendMail(mail_message *msg); static int agentToAgent(mail_message *msg); static void writeMailToFile(FILE *fp, mail_message *msg); #define READ_PIPE 0 #define WRITE_PIPE 1 #define MAIL_FILE_APPEND 0 #define MAIL_FILE_OVERWRITE 1 #define MAIL_FILE_DELETE 2 static int read_pipe; static int write_pipe; static int ref_num = 0; /* ============================================================ | aopMailEntryFunction() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 2 16:15:00 1992 | |==========================================================| */ void aopMailEntryFunction(int request_num) { switch (request_num) { case MODULE_INIT: { mailInit(); break; } case MODULE_EXIT: { printf("\n\n\n EXit mail lib\n\n\n"); mailExit(); break; } } } /* ============================================================ | readMailPipe() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 2 16:21:44 1992 | |==========================================================| */ void readMailPipe(int pipe_id) { int n; mail_msg_header header; char *buffer; if((n = read(pipe_id, (char *)&header,sizeof(mail_msg_header) )) > 0){ if (n!= sizeof(mail_msg_header)) ErrSys(" Mail pipe - header read"); buffer = (char *)malloc(header.data_length); n = read(pipe_id, buffer, header.data_length); if(n != header.data_length ) ErrSys(" Mail pipe - data read"); mailProcessMsg(header.msg_type, buffer); free(buffer); } else { /* Error */ printf("Err nombur: %d\n", errno); if(errno == 0) { printf("Unregistening\n"); unregisterPipe(pipe_id); } else printf("What error\n"); } } /* ============================================================ | mailInit() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Thu Sep 3 13:45:32 1992 | |==========================================================| */ static void mailInit() { int pipe1[2]; int pipe2[2]; char c_read_pipe[10], c_write_pipe[10]; int pid; int *data; /* Register the module. */ ref_num = register_module("mail"); if(ref_num == -1) { ErrSys("Module registration error"); return; } /* Open the pipes. */ if(pipe(pipe1) < 0) return; if(pipe(pipe2) < 0) { close(pipe1[READ_PIPE]); close(pipe2[WRITE_PIPE]); return; } /* Convert pipes number to strings. */ sprintf(c_read_pipe, "%d", pipe1[READ_PIPE]); sprintf(c_write_pipe, "%d", pipe2[WRITE_PIPE]); /* Start the mail process. */ if((pid = fork()) < 0) { /* Fork failed. */ close(pipe1[READ_PIPE]); close(pipe1[WRITE_PIPE]); close(pipe2[READ_PIPE]); close(pipe2[WRITE_PIPE]); return; } if(pid == 0) { /* Child process. */ close(pipe2[READ_PIPE]); close(pipe1[WRITE_PIPE]); /*execlp("AOPmail", "AOPmail", c_read_pipe, c_write_pipe, (char *) 0); */ execlp("xterm","xterm","-g", "20x10-0+0", "-e", "AOPmail", c_read_pipe, c_write_pipe, (char *) 0); } else { /* Parent process. */ close(pipe2[WRITE_PIPE]); close(pipe1[READ_PIPE]); read_pipe = pipe2[READ_PIPE]; write_pipe = pipe1[WRITE_PIPE]; fcntl(read_pipe, F_SETFL, O_NDELAY); /* Register the pipe. */ if(registerPipe(read_pipe, &readMailPipe) == -1) printf("Did not register pipe\n"); /* Register the actions. */ /* 1. Send mail. */ register_function(ref_num, "send_mail_to_user", &sendMailToUser, (void *)NULL); /* 2. Send mail to agent. */ register_function(ref_num, "send_mail_to_agent", &sendMailToAgent, (void *)NULL); /* 3. Display mail to user. */ register_function(ref_num, "display_mail", &displayMailToUser, (void *)NULL); /* Control function. */ register_function(ref_num, "deliver_mail", &mailControl, (void *)NULL); register_function(ref_num, "hold_mail", &mailControl, (void *)&mailControl); /* File handeling functions. */ data = (int *)malloc(sizeof(int)); *data = MAIL_FILE_APPEND; register_function(ref_num, "mail_append_to_folder", &mailFileHandling, (void *)data); data = (int *)malloc(sizeof(int)); *data = MAIL_FILE_OVERWRITE; register_function(ref_num, "mail_overwrite_folder", &mailFileHandling, (void *)data); data = (int *)malloc(sizeof(int)); *data = MAIL_FILE_DELETE; register_function(ref_num, "mail_delete_folder", &mailFileHandling, (void *)data); } return; } /* ============================================================ | mailExit() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Thu Sep 3 13:46:56 1992 | |==========================================================| */ static void mailExit() { endMailProcess(); } /* ============================================================ | mailProcessMsg() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 2 16:33:50 1992 | |==========================================================| */ static void mailProcessMsg(int msg_type, char *data) { switch(msg_type){ case MAIL_INCOMING_MAIL:{ /* New mail arrived */ mail_message *msg = (mail_message *)data; notifyAgent(msg); free(data); break; } case MAIL_AGENT_MESSAGE:{ /* Transfer the message to an agent. */ break; } case MAIL_QUIT_REQUEST:{ /* The mail process like to quit */ endMailProcess(); exit(0); break; } } } /* ============================================================ | writeToMailPipe() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 2 16:40:23 1992 | |==========================================================| */ static void writeToMailPipe(int msg_type, int data_length, void *data) { char *buffer = (char *)malloc(sizeof(mail_msg_header) + data_length); mail_msg_header *header = (mail_msg_header *)buffer; char *ptr1 = (char *)(buffer + sizeof(mail_msg_header)); header->msg_type = msg_type; header->data_length = data_length; memcpy((void *)ptr1, data,data_length); write(write_pipe, buffer, sizeof(mail_msg_header) + data_length); free(buffer); } /* ============================================================ | endMailProcess() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 2 16:38:59 1992 | |==========================================================| */ static void endMailProcess() { writeToMailPipe(MAIL_QUIT_REQUEST, 0, NULL); /* Unregister the pipe. */ unregisterPipe(read_pipe); /* Close the pipe. */ close(read_pipe); close(write_pipe); } /* ============================================================ | sendMailToUser() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Thu Sep 3 11:03:45 1992 | |==========================================================| */ static void sendMailToUser(int arity, module_ptr agent, struct term ** args,void *data) { /*send_mail_to_user("To", "Cc", "Subject", ["line1", "line2"..])*/ struct term *t; char *temp; int counter; mail_message *msg = (mail_message *)malloc(sizeof(mail_message)); /* Create the mail format. */ temp = GetTermString(args[0]); strcpy(msg->header.to, temp); free(temp); temp = GetTermString(args[1]); strcpy(msg->header.cc, temp); free(temp); temp = GetTermString(args[2]); strcpy(msg->header.subject, temp); free(temp); t = args[3]; counter = 0; while(t->functor == CONS_LIST) { temp = GetTermString(t->argument_array[0]); strcpy(msg->body[counter++], temp); free(temp); t = t->argument_array[1]; } msg->line_counter = counter; /* Send the mail */ sendMail(msg); free(msg); } /* ============================================================ | sendMailToAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Thu Sep 3 11:04:59 1992 | |==========================================================| */ static void sendMailToAgent(int arity, module_ptr agent, struct term ** args,void *data) { /*send_mail_to_agent("Sender", "Reciver", "Term")*/ mail_message msg; full_address *addr; /* Need to find the reciver mail address. */ addr = resolveAgentAddress(sym_table[args[1]->functor]->name); if(addr == NULL) { /* Can not resolve the agent address. */ } else { char *term_string; term_ptr t; int fta = lookup_term("forward_to_agent"); t = maketerm(NONVAR, fta, 3, NULL,maketermarray(3)); t->argument_array[0] = args[0]; t->argument_array[1] = args[1]; t->argument_array[2] = args[2]; /* Create a string of the term. */ term_string = TermToString(t); /* Create the mail message. */ strcpy(msg.header.to, addr->user); strcat(msg.header.to, "@"); strcat(msg.header.to, addr->machine); strcpy(msg.header.subject, AGENT_TO_AGENT); strcpy(msg.body[0],term_string); msg.line_counter =1; /* Send the mail */ sendMail(&msg); /* Garbage colection. */ free(addr->agent); free(addr); free_term(t); free(term_string); } } /* ============================================================ | displayMailToUser() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Thu Sep 3 11:08:26 1992 | |==========================================================| */ static void displayMailToUser(int arity, module_ptr agent, struct term ** args,void *data) { /* display_mail(Start, From, To, Cc, Message-Id, Date, Return-Path, Subject, [line1, line2 ...linen]) */ mail_message *msg = termMail2MsgMail(arity, agent, args); writeToMailPipe(MAIL_DISPLAY_MAIL , sizeof(mail_message),(void *)msg); free(msg); } /* ============================================================ | mailControl() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Fri Sep 4 11:26:02 1992 | |==========================================================| */ static void mailControl(int arity, module_ptr agent, struct term ** args,void *data) { if(data == NULL) { /* Start delivering mail. */ writeToMailPipe(MAIL_DELIVER_MAIL, 0, NULL); } else { /* Hold mail */ writeToMailPipe(MAIL_HOLD_MAIL, 0, NULL); } } /* ============================================================ | termMail2MsgMail() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Fri Sep 4 10:02:13 1992 | |==========================================================| */ static mail_message *termMail2MsgMail(int arity, module_ptr agent, struct term ** args) { /* (Start, From, To, Cc, Message-Id, Date, Return-Path, Subject, [line1, line2 ...linen]) */ struct term *t; char *temp; int counter; mail_message *msg = (mail_message *)malloc(sizeof(mail_message)); temp = GetTermString(args[0]); strcpy(msg->header.start, temp); free(temp); temp = GetTermString(args[1]); strcpy(msg->header.from, temp); free(temp); temp = GetTermString(args[2]); strcpy(msg->header.to, temp); free(temp); temp = GetTermString(args[3]); strcpy(msg->header.cc, temp); free(temp); temp = GetTermString(args[4]); strcpy(msg->header.msg_id, temp); free(temp); temp = GetTermString(args[5]); strcpy(msg->header.date, temp); free(temp); temp = GetTermString(args[6]); strcpy(msg->header.return_path, temp); free(temp); temp = GetTermString(args[7]); strcpy(msg->header.subject, temp); free(temp); t = args[8]; counter = 0; while(t->functor == CONS_LIST) { temp = GetTermString(t->argument_array[0]); strcpy(msg->body[counter++], temp); free(temp); t = t->argument_array[1]; } msg->line_counter = counter; return(msg); } /* ============================================================ | notifyAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Thu Sep 3 16:08:19 1992 | |==========================================================| */ static void notifyAgent(mail_message *msg) { /*incoming_mail(User, Machine, Start, From, To, Cc, Message-Id, Date, Return-Path, Subject, [line1, line2 ...linen])*/ term_pointer t, body,temp; int func_num = functor_string("incoming_mail"); int agent_functor = functor_string("mail_agent"); int i; char *user; char *machine; if((func_num == -1) || (agent_functor == -1)){ ErrSys("Can not find functor number for 'incoming_mail'"); return; } if(!agentToAgent(msg)) { /* Saperate the sender name from the machine name. */ user = msg->header.return_path; machine = strchr(user, (int)'@'); if(machine != NULL) *machine = '\0'; t = maketerm(NONVAR, func_num, 11, NULL, maketermarray(11)); t->argument_array[0] = maketerm(STRING, 0, 0, user, NULL); if(machine != NULL) { t->argument_array[1] = maketerm(STRING, 0, 0, machine+1, NULL); /* Restore the @ signe. */ *machine = '@'; } else t->argument_array[1] = maketerm(STRING, 0, 0, "", NULL); /* Store the mail info */ t->argument_array[2] = maketerm(STRING, 0, 0, msg->header.start, NULL); t->argument_array[3] = maketerm(STRING, 0, 0, msg->header.from, NULL); t->argument_array[4] = maketerm(STRING, 0, 0, msg->header.to, NULL); t->argument_array[5] = maketerm(STRING, 0, 0, msg->header.cc, NULL); t->argument_array[6] = maketerm(STRING, 0, 0, msg->header.msg_id, NULL); t->argument_array[7] = maketerm(STRING, 0, 0, msg->header.date, NULL); t->argument_array[8] = maketerm(STRING, 0, 0, msg->header.return_path, NULL); t->argument_array[9] = maketerm(STRING, 0, 0, msg->header.subject, NULL); /* Create the message body. */ body = maketerm(NONVAR, EMPTY_LIST,0, NULL, NULL); for(i=msg->line_counter-1; i>=0; i--) { temp = maketerm(NONVAR,CONS_LIST,2,NULL,maketermarray(2)); temp->argument_array[1] = body; temp->argument_array[0] = maketerm(STRING,0,0,msg->body[i],NULL); body = temp; } t->argument_array[10] = body; send_message(INFORM, agent_functor, agent_functor, t); } else { /* Agent communicate through mail. */ struct clause *cl; if((cl=parse_interactive_input(msg->body[0])) != NULL){ send_message(INFORM, agent_functor, agent_functor, cl->head); free(cl); } } } /* ============================================================ | agentToAgent() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Fri Sep 4 14:59:28 1992 | |==========================================================| */ static int agentToAgent(mail_message *msg) { return(!strcmp(msg->header.subject, AGENT_TO_AGENT)); } /* ============================================================ | sendMail() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Fri Sep 4 10:11:39 1992 | |==========================================================| */ static void sendMail(mail_message *msg) { int pid; /* Fork a process to handle the mail. */ if((pid = fork()) < 0) { /* Fork failed. */ printf("Can not fork mail sender process.\n"); return; } if(pid == 0) { /* Child process. */ FILE *fp; int fd, i; char *getlogin(); char *username; char mail_file[50]; /* Get the user login name. */ username = getlogin(); if (!username) { struct passwd *pw = getpwuid (getuid ()); if (!pw) { printf ("%s: unable to find a username for you.\n", "Mail agent"); exit(1); } username = pw->pw_name; } /* Open the temporary mail file. */ sprintf(mail_file, "/tmp/AOPmail.%s", username); if((fp = fopen(mail_file, "w+")) == NULL) { printf("Can not open mail file\n" ); return; } /* Write the message to the file. */ fprintf(fp, "To: %s\n", msg->header.to); fprintf(fp,"Cc: %s\n", msg->header.cc); fprintf(fp,"Subject: %s\n", msg->header.subject); fprintf(fp,"\n"); for(i=0;i < msg->line_counter; i++) fprintf(fp,"%s\n",msg->body[i]); /* Rewinde the file */ rewind(fp); /* Make it the standard input. */ fd = fileno(fp); if(dup2(fd, 0) == -1) { printf("Can not duplicate fds\n"); return; } /* Close the fd */ close(fd); /* Free the message */ free(msg); /* Execute the send program */ execlp("/usr/lib/sendmail","sendmail", "-oi", "-t","-f",username, "-oep", "-odb",(char *) 0); exit(1); } } /* ============================================================ | mailFileHandling() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 9 09:19:02 1992 | |==========================================================| */ static void mailFileHandling(int arity, module_ptr agent, struct term ** args,void *data) { /* (File_name, Start, From, To, Cc, Message-Id, Date, Return-Path, Subject, [line1, line2 ...linen]) */ mail_message *msg; FILE *fp; struct stat dir_status; char *file_name = GetTermString(args[0]); switch(*(int *)data) { case MAIL_FILE_APPEND: { /* Convert to mail message form. */ msg = termMail2MsgMail(arity-1, agent, args+1); if((fp = fopen(file_name, "a")) == NULL){ /* Unable to create the file. */ ErrSys("Unable to open/create file\n"); return; } /* Append the mail to the file. */ writeMailToFile(fp,msg); if(fclose(fp) != 0){ ErrSys("Unable to close file\n"); } free(msg); break; } case MAIL_FILE_OVERWRITE: { /* Convert to mail message form. */ msg = termMail2MsgMail(arity-1, agent, args+1); if((fp = fopen(file_name, "w")) == NULL){ /* Unable to create the file. */ ErrSys("Unable to open/create file\n"); return; } /* Write the mail to the file. */ writeMailToFile(fp,msg); if(fclose(fp) != 0){ ErrSys("Unable to close file\n"); } free(msg); break; } case MAIL_FILE_DELETE: { if(stat(file_name,&dir_status) == 0){ /* File exists. */ if(unlink(file_name) == -1) { ErrSys("Unable to delete file\n"); } } break; } default: { ErrSys("Unknown request"); } } free(file_name); } /* ============================================================ | writeMailToFile() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | | Created by: avrami tzur | | At: Wed Sep 9 09:51:35 1992 | |==========================================================| */ static void writeMailToFile(FILE *fp, mail_message *msg) { int i; fprintf(fp, "\n\nFrom %s\nFrom: %s\nTo: %s\nCc: %s\nMessage-Id: %s\nDate: %s\nReturn-Path:<%s>\nSubject: %s\n\n", msg->header.start, msg->header.from, msg->header.to, msg->header.cc,msg->header.msg_id,msg->header.date, msg->header.return_path, msg->header.subject); for(i=0;iline_counter; i++) fprintf(fp, "%s\n", msg->body[i]); } /* ============================================================ | displayMailMsg() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : | | | | Returns: | |==========================================================| */ static void displayMailMsg(mail_message *msg) { int i; printf("\n\t (LIB) Mail Message (status %s)\n", (msg->line_counter >= MAIL_BODY_SIZE)?"To long":"ok"); printf("From %s\n", msg->header.start); printf("From: %s\n", msg->header.from); printf("To: %s\n", msg->header.to); printf("Cc: %s\n", msg->header.cc); printf("Message-Id:: %s\n", msg->header.msg_id); printf("Date: %s\n", msg->header.date); printf("Return-Path: <%s>\n", msg->header.return_path); printf("Subject: %s\n", msg->header.subject); printf("\n"); for(i=0;i < msg->line_counter; i++) printf("%s\n",msg->body[i]); printf("\n\t End of Mail Message\n"); }