Example-DEC C   How to read MIME mail attachments using VAXMail. 

EXAMPLE TEMPLATE:
PRODUCT: COMPAQ C Version 6.2-005
OP/SYS: OpenVMS ALPHA Version 7.2-1H1
COMPONENT: Mail Utility (VAXMail) SOURCE: Philippe Vouters Fontainebleau/France
LOW-COST HIGH-TECH: http://techno-star.fr
OVERVIEW: The command procedure below enable to read VMS Mail messages sent using protocol SMTP and to extract encoded attachment files, if any.
*** CAUTION *** This sample procedure has been tested using COMPAQ C V6.2-005 on OpenVMS Alpha V7.2-1H1. However, we cannot guarantee its effectiveness because of the possibility of error in transmitting or implementing it. It is meant to be used as a template for writing your own procedure, and may require modification for use on your system.
PROCEDURE NOTES: Extract the command file below and execute it. This produces 2 files (MAIL_ATTACHMENTS.EXE and SYS$HELP:MAIL_ATTACHMENT.HLB). After being invited by tghe procedure, type $ RUN MAIL_ATTACHMENTS. At the program's prompt "MAIL> ", enter HELP. This will give the correct syntax and examples on how to use this program. You may have to adjust the MAIN_PROC_DEPTH value according to your Compaq C compiler and optimization level.
PROCEDURE: $! Procedure Parameters: $! P1 = "DEBUG" or "" $! P2 = "DECC" or "VAXC" or "" $! $! COPYRIGHT (C) 2002 BY $! COMPAQ COMPUTER CORPORATION, HOUSTON $! TEXAS. ALL RIGHTS RESERVED. $! $! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED $! ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION $! OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES $! THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER $! PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY $! TRANSFERRED. $! $! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND $! SHOULD NOT BE CONSTRUED AS A COMMITMENT BY COMPAQ COMPUTER CORPORATION. $! $! COMPAQ ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS $! SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY COMPAQ. $! $! NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE $! ON EQUIPMENT THAT IS NOT SUPPLIED BY COMPAQ COMPUTER CORPORATION. $! $! SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY COMPAQ SOFTWARE $! PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE $! CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED. $! $ if P1 .eqs. "DEBUG" $ then $ ccflags="/debug/nooptimize" $ lnkflags="/debug" $ else $ lnkflags="/notraceback" $ endif $ $ compiler_switch = "/"+ P2 $ c_include = f$trnlnm("VAXC$INCLUDE") $ decc = f$search ("sys$system:decc$compiler.exe") $ vaxc_compiler = f$search ("sys$system:vaxc.exe") $ if vaxc_compiler .eqs. "" .and. decc .eqs. "" then goto end $ if vaxc_compiler .eqs. "" .and. decc .nes. "" $ then $ compiler_switch = "" $ compiler = "DECC" $ endif $ if vaxc_compiler .nes. "" .and. decc .eqs. "" $ then $ compiler_switch = "" $ compiler = "VAXC" $ endif $ if vaxc_compiler .nes. "" .and. decc .nes. "" .and. P2 .eqs. "" $ then $ compiler_switch = "/VAXC" $ compiler = "VAXC" $ else $ if P2 .nes. "" $ then $ compiler_switch = "/"+ P2 $ compiler = P2 $ endif $ endif $ if f$search ("mail_attachments.exe") .nes. "" then delete mail_attachments.exe; $ if f$search ("mail_attachments.c") .nes. "" then delete mail_attachments.c; $ if (compiler .eqs. "DECC") .and. (P1 .eqs. "") $ then $ ccflags="''ccflags'/define=(MAIN_PROC_DEPTH=7)" $ endif $ if (compiler .eqs. "VAXC") $ then $ create mailmsgdef.h #define MAIL$_FACILITY 126 #define MAIL$_CODERR 8290316 #define MAIL$_UPGRADE 8290324 #define MAIL$_UAFGETERR 8290330 #define MAIL$_UAFOPNERR 8290338 #define MAIL$_NOSUCHUSR 8290346 #define MAIL$_NOTREADIN 8290354 #define MAIL$_LOGLINK 8290362 #define MAIL$_CREPRIJOB 8290370 #define MAIL$_SENDERR 8290378 #define MAIL$_NOMOREMSG 8290386 #define MAIL$_NOMSGS 8290394 #define MAIL$_USERSPEC 8290402 #define MAIL$_SENDABORT 8290410 #define MAIL$_EDITPROC 8290418 #define MAIL$_INVCMD 8290426 #define MAIL$_NOTFOUND 8290434 #define MAIL$_NETIOERR 8290442 #define MAIL$_USERDSABL 8290450 #define MAIL$_FORWLOOP 8290458 #define MAIL$_NAMTOOBIG 8290466 #define MAIL$_ILLCHAR 8290474 #define MAIL$_DATIMUSED 8290482 #define MAIL$_NOTISAM 8290490 #define MAIL$_DELMSG 8290498 #define MAIL$_DELWASTE 8290506 #define MAIL$_NOFOLDER 8290514 #define MAIL$_NOTEXIST 8290522 #define MAIL$_NOTSUBDIR 8290530 #define MAIL$_ILLSUBDIR 8290538 #define MAIL$_ILLFOLNAM 8290546 #define MAIL$_NOMSGPRI 8290554 #define MAIL$_ALTPRIJOB 8290562 #define MAIL$_ILLPERNAM 8290570 #define MAIL$_NOSUCHUSRAT 8290578 #define MAIL$_SENDERRAT 8290586 #define MAIL$_CONABORT 8290594 #define MAIL$_NOTCALEDT 8290602 #define MAIL$_FILECONFUSED 8290610 #define MAIL$_CAPTIVE 8290618 #define MAIL$_IVPROTVAL 8290626 #define MAIL$_RECTOBIG 8290634 #define MAIL$_ILLCTXADR 8290642 #define MAIL$_WRONGCTX 8290650 #define MAIL$_FAILGETVM 8290658 #define MAIL$_INVITMCOD 8290666 #define MAIL$_MISREQITM 8290674 #define MAIL$_INVITMLEN 8290682 #define MAIL$_FILEOPEN 8290690 #define MAIL$_NOFILEOPEN 8290698 #define MAIL$_CONITMCOD 8290706 #define MAIL$_NOMORECTX 8290714 #define MAIL$_WRONGFILE 8290722 #define MAIL$_ILLTPRT 8290730 #define MAIL$_INVITMVAL 8290738 #define MAIL$_ERACTED 8290746 #define MAIL$_FORMSG 8290754 #define MAIL$_NOTFORMSG 8290762 #define MAIL$_ERRACTRNS 8290770 #define MAIL$_BADVALUE 8290778 #define MAIL$_CLOSEDEL 8290786 #define MAIL$_FILNOTDEL 8290794 #define MAIL$_OPENIN 8290802 #define MAIL$_OPENOUT 8290810 #define MAIL$_PARSEFAIL 8290818 #define MAIL$_READERR 8290826 #define MAIL$_SEARCHFAIL 8290834 #define MAIL$_SYSERROR 8290842 #define MAIL$_NOSYSNAM 8290850 #define MAIL$_NOSYSPRV 8290858 #define MAIL$_PROTOCOL 8290866 #define MAIL$_NOACCPTMSG 8290874 #define MAIL$_DOTSPACK 8290882 #define MAIL$_DOTSUNPACK 8290890 #define MAIL$_NOUSERSPEC 8290898 #define MAIL$_INVRANGE 8290906 #define MAIL$_LISTTOOLONG 8290914 #define MAIL$_SELECTED 8306307 #define MAIL$_DELMSGS 8306315 #define MAIL$_CVTFILE 8306323 #define MAIL$_DELSPACE 8306331 #define MAIL$_NEWFOLDER 8306339 #define MAIL$_RECLPLSWAIT 8306347 #define MAIL$_REENTER 8306355 #define MAIL$_DELETED 8306363 #define MAIL$_FFMTMSG 8306371 #define MAIL$_MOREMSG 8314304 #define MAIL$_DIRHD0 8314312 #define MAIL$_DIRHD10 8314320 #define MAIL$_DIRHD20 8314328 #define MAIL$_DIRDEL10 8314336 #define MAIL$_ISUB10 8314344 #define MAIL$_ISUB20 8314352 #define MAIL$_ISUB30 8314360 #define MAIL$_PRESRET 8314368 #define MAIL$_YOUHAVENEW 8314376 #define MAIL$_MAIL10 8314384 #define MAIL$_MAIL20 8314392 #define MAIL$_WANTOSEND 8314400 #define MAIL$_NOTIFY10 8314408 #define MAIL$_NOTIFY20 8314416 #define MAIL$_JOBENTERED 8314424 #define MAIL$_SHOW10 8314432 #define MAIL$_SHOW20 8314440 #define MAIL$_SHOW30 8314448 #define MAIL$_SHOW40 8314456 #define MAIL$_SHOW50 8314464 #define MAIL$_SHOW60 8314472 #define MAIL$_SHOW70 8314480 #define MAIL$_SHOW80 8314488 #define MAIL$_SHOW90 8314496 #define MAIL$_SHOW100 8314504 #define MAIL$_SHOW110 8314512 #define MAIL$_EDIT10 8314520 #define MAIL$_INFO10 8314528 #define MAIL$_INFO20 8314536 #define MAIL$_INFO30 8314544 #define MAIL$_SEND 8314552 #define MAIL$_REPLY 8314560 #define MAIL$_SHOW120 8314568 #define MAIL$_SHOW130 8314576 #define MAIL$_INFO50 8314584 #define MAIL$_SHOW140 8314592 #define MAIL$_SHOW150 8314600 #define MAIL$_SHOW160 8314608 #define MAIL$_ISUB50 8314616 #define MAIL$_MAIL30 8314624 #define MAIL$_RETCONT 8314632 #define MAIL$_NEWSEQ 8314640 #define MAIL$_MAILDIR 8314648 #define MAIL$_MAILFILE 8314656 #define MAIL$_MAILFOLDER 8314664 #define MAIL$_MAIL40 8314672 #define MAIL$_CRENEWFOLD 8314680 #define MAIL$_NONEWMAIL 8314688 #define MAIL$_SHOWKEY10 8314696 #define MAIL$_SHOWKEY20 8314704 #define MAIL$_SHOWKEY30 8314712 #define MAIL$_SHOWKEY40 8314720 #define MAIL$_SHOWKEY50 8314728 #define MAIL$_SHOWKEY60 8314736 #define MAIL$_SHOWKEY70 8314744 #define MAIL$_NOTIFY30 8314752 #define MAIL$_NOTIFY40 8314760 #define MAIL$_NOPARENT 8314768 #define MAIL$_FILEMPTY 8314776 #define MAIL$_NONEFOUND 8314784 #define MAIL$_NOMOREREC 8314792 #define MAIL$_USERFWD 8314800 #define MAIL$_PROMPT 8314808 #define MAIL$_INFO12 8314816 #define MAIL$_INFO14 8314824 #define MAIL$_INFO16 8314832 #define MAIL$_INFO18 8314840 #define MAIL$_CRENEWFILE 8314848 #define MAIL$_SHOW15 8314856 #define MAIL$_SHOW25 8314864 #define MAIL$_SHOW35 8314872 #define MAIL$_FORWARD 8314880 #define MAIL$_SHOW200 8314888 #define MAIL$_SHOW205 8314896 #define MAIL$_SHOW210 8314904 #define MAIL$_SHOW215 8314912 #define MAIL$_CLOSEIN 8314920 #define MAIL$_CLOSEOUT 8314928 #define MAIL$_INVQUAVAL 8314936 #define MAIL$_WRITEERR 8314944 #define MAIL$_SHOW220 8314952 #define MAIL$_SHOW225 8314960 #define MAIL$_HPROMPT 8314968 #define MAIL$_SHOWNOSIG 8314976 #define MAIL$_SHOWSIG 8314984 #define MAIL$_BADLOGVAL 8314992 #define MAIL$_MSGTEXT 8322305 #define MAIL$_MSGINFO 8322313 #define MAIL$_MSGSENT 8322321 #define MAIL$_MSGSENTAT 8322329 #define MAIL$_YES 8322337 #define MAIL$_COPIEDR 8322345 #define MAIL$_CREATED 8322353 #define MAIL$_RENAMED 8322361 #define MAIL$_TEXT 8322369 #define MAIL$_MAILFOLD 8322377 #define MAIL$_WASTEFOLD 8322385 #define MAIL$_ILLEDTNAM 8322394 #define MAIL$_KEYNOTDEF 8322402 #define MAIL$_INVKEYNAM 8322410 $ endif $ create mail_attachments.c #ifdef __DECC #pragma module mail_attachments "V1.0-00" #else #module mail_attachments "V1.0-00" #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <setjmp.h> #include <stat.h> #include <ctype.h> #include <starlet.h> #include <chfdef.h> #include <descrip.h> #include <ctype.h> #include <ssdef.h> #include <rmsdef.h> #include <mail$routines.h> #include <maildef.h> #include <smg$routines.h> #include <lbr$routines.h> #include <lib$routines.h> #include <cli$routines.h> #ifdef __DECC #include <mailmsgdef.h> #else #include "mailmsgdef.h" #endif /* single character decode */ #define DEC(c) (((c) - ' ') & 077) #define S_IPERM 01777 /* File permission bits (shb in stat.h) */ #define BLOCKSIZE 512 #define SCREENWIDTH 80 #ifdef __DECC #pragma member_alignment save #pragma nomember_alignment byte #endif typedef struct item { short buffer_length; short item_code; void *buffer; unsigned int *return_length; } item_t; typedef struct termchar { unsigned char class; unsigned char type; unsigned short bufsiz; unsigned int basictermchar:24; unsigned char pagelength; } termchar_t; #ifdef __DECC #pragma member_alignment restore #endif enum encoding_t {UNKNOWN,TEXT,QUOTED_PRINTABLE,SEVEN_BIT, UUENCODE,BASE64,OCTETSTREAM}; typedef struct attachment_type { struct attachment_type *next; char *name; char *file; char *charset; enum encoding_t encode_format; /* Type of encoding */ char *rfm_format; char *filebuff; /* Pointer to file buffer */ char *endfile; } attachment_t; typedef struct message_type { struct message_type *next; /* next message */ int message_id; /* id returned by directory_routine */ attachment_t *attachment; /* flag indicating attachments present */ char *ThisMail; char *EndThisMail; char *separator; } message_t; #ifdef __DECC #pragma extern_model globalvalue extern const int CLI$_NORMAL,CLI$_NOCOMD,CLI$_PRESENT,CLI$_ABSENT; /* * Declare as external link time value the table which holds the valid * commands. The name of the table is thez cld module name. Refer * to cld file content. */ #pragma extern_model strict_refdef extern unsigned long long Test; #else globalvalue int CLI$_NORMAL,CLI$_NOCOMD,CLI$_PRESENT,CLI$_ABSENT; globalref unsigned long long Test; #endif #ifdef __DECC #pragma extern_model strict_refdef #endif int file_context, message_context, messages_selected; static message_t *message_list; static item_t message_in_itmlst[] = { {sizeof(file_context),MAIL$_MESSAGE_FILE_CTX,&file_context,0}, {0,0,0,0}}; static item_t message_select_out_itmlst[] = { {sizeof(messages_selected),MAIL$_MESSAGE_SELECTED,&messages_selected,0}, {0,0,0,0}}; typedef struct filext_to_rfm_type{ char *application; char *knowfileextension; char *record_format; }filext_to_rfm_t; #define RFM_MAX sizeof(file_to_rfm)/sizeof(filext_to_rfm_t) static const char *rfm_fix = "rfm=fix"; static const char *standard_output="sys$output:TEXT.TXT"; static const char *default_charset="us-ascii"; static filext_to_rfm_t file_to_rfm[] = { {"application/activemessage",NULL,"rfm=fix"}, {"application/andrew-inset",NULL,"rfm=fix"}, {"application/applefile",NULL,"rfm=fix"}, {"application/atomicmail",NULL,"rfm=fix"}, {"application/dca-rft",NULL,"rfm=fix"}, {"application/dec-dx",NULL,"rfm=fix"}, {"application/mac-binhex40",NULL,"rfm=fix"}, {"application/macwriteii",NULL,"rfm=fix"}, {"application/msword","doc","rfm=var"}, {"application/news-message-id",NULL,"rfm=fix"}, {"application/news-transmission",NULL,"rfm=fix"}, {"application/octet-stream","bin dat","rfm=stmlf"}, {"application/xmsdownload","exe","rfm=fix"}, {"application/oda","oda","rfm=fix"}, {"application/pdf","pdf","rfm=fix"}, {"application/postscript","ai eps ps","rfm=var"}, {"application/remote-printing",NULL,"rfm=fix"}, {"application/rtf","rtf","rfm=var"}, {"application/slate",NULL,"rfm=fix"}, {"application/x-mif","mif","rfm=fix"}, {"application/wita",NULL,"rfm=fix"}, {"application/wordperfect5.1","doc","rfm=var"}, {"application/x-csh","csh","rfm=fix"}, {"application/x-dvi","dvi","rfm=fix"}, {"application/x-hdf","hdf","rfm=fix"}, {"application/x-latex","latex","rfm=fix"}, {"application/x-netcdf","nc cdf","rfm=fix"}, {"application/x-sh","sh","rfm=fix"}, {"application/x-tcl","tcl","rfm=fix"}, {"application/x-tex","tex","rfm=fix"}, {"application/x-texinfo","texinfo texi","rfm=fix"}, {"application/x-troff","t tr roff","rfm=fix"}, {"application/x-troff-man","man","rfm=fix"}, {"application/x-troff-me","me","rfm=fix"}, {"application/x-troff-ms","ms","rfm=fix"}, {"application/x-wais-source","src","rfm=var"}, {"application/zip","zip","rfm=fix"}, {"application/x-bcpio","bcpio","rfm=fix"}, {"application/x-cpio","cpio","rfm=fix"}, {"application/x-gtar","gtar","rfm=fix"}, {"application/x-shar","shar","rfm=fix"}, {"application/x-sv4cpio","sv4cpio","rfm=fix"}, {"application/x-sv4crc","sv4crc","rfm=fix"}, {"application/x-tar","tar","rfm=fix"}, {"application/x-ustar","ustar","rfm=fix"}, {"audio/basic","au snd","rfm=fix"}, {"audio/x-aiff","aif aiff aifc","rfm=fix"}, {"audio/x-wav","wav","rfm=fix"}, {"image/gif","gif","rfm=fix"}, {"image/ief","ief","rfm=fix"}, {"image/jpeg","jpeg jpg jpe","rfm=fix"}, {"image/tiff","tiff tif","rfm=fix"}, {"image/x-cmu-raster","ras","rfm=fix"}, {"image/x-portable-anymap","pnm","rfm=fix"}, {"image/x-portable-bitmap","pbm","rfm=fix"}, {"image/x-portable-graymap","pgm","rfm=fix"}, {"image/x-portable-pixmap","ppm","rfm=fix"}, {"image/x-rgb","rgb","rfm=fix"}, {"image/x-xbitmap","xbm","rfm=fix"}, {"image/x-xpixmap","xpm","rfm=fix"}, {"image/x-xwindowdump","xwd","rfm=fix"}, {"message/external-body",NULL,"rfm=fix"}, {"message/news",NULL,"rfm=fix"}, {"message/partial",NULL,"rfm=fix"}, {"message/rfc822",NULL,"rfm=var"}, {"multipart/alternative",NULL,"rfm=fix"}, {"multipart/appledouble",NULL,"rfm=fix"}, {"multipart/digest",NULL,"rfm=fix"}, {"multipart/mixed",NULL,"rfm=fix"}, {"multipart/parallel",NULL,"rfm=fix"}, {"text/html","html","rfm=var"}, {"text/plain","txt","rfm=var"}, {"text/richtext","rtx","rfm=var"}, {"text/tab-separated-values","tsv","rfm=var"}, {"text/x-setext","etx","rfm=var"}, {"video/mpeg","mpeg mpg mpe","rfm=fix"}, {"video/quicktime","qt mov","rfm=fix"}, {"video/x-msvideo","avi","rfm=fix"}, {"video/x-sgi-movie","movie","rfm=fix"}, {NULL,NULL,NULL}}; int DisplayInternetHeader(int, char *, message_t *); int DisplayDate(int,char *, message_t *); int DisplayData(int, char *, message_t *); int Push(int, char *, message_t *); typedef struct { char *InternetHeader; int (*action)(int index, char *text, message_t *message); }HeadersAction_t; static HeadersAction_t InternetHeaders[]={ "Received: ", DisplayInternetHeader, "Date: ", DisplayDate, "From: ", DisplayData, "Sender: ", DisplayData, "To: " ,DisplayData, "CC: ", DisplayData, "Bcc: ", DisplayInternetHeader, "Reply-to: ", DisplayInternetHeader, "Subject: ", DisplayData, "MIME-Version: ", DisplayInternetHeader, "Content-Type: ", Push, "Message-Id: ", DisplayInternetHeader, "Return-Path: ", DisplayInternetHeader, "X-OriginalArrivalTime: ", DisplayInternetHeader, "Content-Transfer-Encoding: ", Push, "Content-Disposition: ", Push }; #define NUMBER_HEADERS \ sizeof(InternetHeaders)/sizeof(HeadersAction_t) #ifndef MAIN_PROC_DEPTH #define MAIN_PROC_DEPTH 10 /* Unwind depth to return to main routine */ #endif #define FULL_ERROR_MESSAGE 15 #define CONTENT_TYPE_INDEX 10 #define CONTENT_TRANSFER_ENCODING 14 #define CONTENT_DISPOSITION 15 #define LF 10 jmp_buf environment_buffer; unsigned int directory_handler (void *sigarr, void *mecharr) { struct chf$signal_array *signal_args; struct chf$mech_array *mech_args; unsigned long *additional; unsigned int depth; signal_args = (struct chf$signal_array *)sigarr; mech_args = (struct chf$mech_array *)mecharr; if (signal_args->chf$l_sig_name != SS$_UNWIND){ if (signal_args->chf$l_sig_name == MAIL$_NOMOREMSG){ /* * To return to exception establisher,only use a up-level * GOTO. (longjmp in C) * equivalent to sys$unwind (mech_args->chf$l_mch_frame,NULL) */ longjmp (environment_buffer,1) ; return(SS$_CONTINUE); } if (signal_args->chf$l_sig_name == MAIL$_NOTEXIST){ unsigned int msgvec[4]; /* * Get error text and output it. */ additional = (unsigned long *)&signal_args->chf$l_sig_arg1; /* Points to the exception PC. */ additional = (unsigned long *)&additional[signal_args->chf$l_sig_args-3], additional--; msgvec[0]=3; msgvec[1]=signal_args->chf$l_sig_name; msgvec[2]=(FULL_ERROR_MESSAGE << 16) + 1; msgvec[3]=*additional; (void)sys$putmsg (msgvec,NULL,NULL,NULL); /* Unwind to read_ast */ depth = MAIN_PROC_DEPTH; (void)sys$unwind (&depth,NULL); } /* if (signal_args->chf$l_sig_name == MAIL$_NOTEXIST) */ return(SS$_RESIGNAL); } return(SS$_CONTINUE); } int DisplayInternetHeader(int index,char *text,message_t *message){ return 1; } int DisplayDate(int index,char *text, message_t *message){ return 1; } int DisplayData(int index,char *text, message_t *message){ return 1; } int Push(int index, char *text, message_t *message){ char *cp=text+strlen(InternetHeaders[index].InternetHeader); char *cp1; attachment_t *tmp,*attachment; int i; if (index == CONTENT_TYPE_INDEX){ if ((!strncasecmp(cp,"multipart/mixed",strlen("multipart/mixed"))) || (!strncasecmp(cp,"multipart/report",strlen("multipart/report")))){ /* * locate the boundary string * */ while ((cp1 = strstr(cp,"boundary=")) == NULL) cp += strlen(cp)+1; cp1 += strlen("boundary="); message->separator=cp1; if (*message->separator= '"') message->separator++; if (message->separator == cp1 +1){ cp1 = strchr(message->separator,'"'); *cp1=0; } } else{ /* * Search last attachment for the input VAXMail message */ tmp = (attachment_t *)&message->attachment; attachment = message->attachment; while (attachment != NULL){ tmp = attachment; attachment = attachment->next; } attachment = tmp; if (!message->attachment){ attachment = calloc(1,sizeof(attachment_t)); tmp->next=attachment; cp1=cp; while (*cp1) cp1 += strlen(cp1)+1; attachment->filebuff=cp1+1; attachment->encode_format=TEXT; } for (i=0;((i<RFM_MAX) && (file_to_rfm[i].application) && (strncasecmp(cp,file_to_rfm[i].application, strlen(file_to_rfm[i].application))));i++); if (i < RFM_MAX) attachment->rfm_format=file_to_rfm[i].record_format; else attachment->rfm_format=(char *)rfm_fix; if (!strncasecmp(cp,"text/plain;",strlen("text/plain;"))){ /* * locate the charset string if present * */ cp1=NULL; while ((*cp) && ((cp1 = strstr(cp,"charset=")) == NULL)) cp += strlen(cp)+1; if (cp1) cp1 += strlen("charset="); else cp1=(char *)default_charset; attachment->charset=cp1; } else{ if ((cp = strchr(cp,';')) != NULL){ /* * Locate the name information */ while ((cp < message->EndThisMail) && ((cp1 = strstr(cp,"name=")) == NULL)) cp += strlen(cp)+1; if (cp < message->EndThisMail){ cp1 += strlen("name="); attachment->name=cp1; } } } } } if (index == CONTENT_TRANSFER_ENCODING){ attachment = (attachment_t *)&message->attachment; tmp = message->attachment; while (tmp != NULL){ attachment=tmp; tmp = tmp->next; } if (!strncasecmp(cp,"quoted-printable",strlen("quoted-printable"))) attachment->encode_format=QUOTED_PRINTABLE; else if (!strncasecmp(cp,"base64",strlen("base64"))) attachment->encode_format=BASE64; else if (!strncasecmp(cp,"7bit",strlen("7bit"))) attachment->encode_format=SEVEN_BIT; else if (!strncasecmp(cp,"uuencode",strlen("uuencode"))) attachment->encode_format=UUENCODE; else attachment->encode_format=UNKNOWN; } if (index == CONTENT_DISPOSITION){ attachment = (attachment_t *)&message->attachment; tmp = message->attachment; while (tmp != NULL){ attachment=tmp; tmp = tmp->next; } /* * locate the filename string * */ while ((cp1 = strstr(cp,"filename=")) == NULL) cp += strlen(cp)+1; cp1 += strlen("filename="); attachment->file=cp1; if (*attachment->file= '"') attachment->file++; if (attachment->file == cp1 +1){ cp1 = strchr(attachment->file,'"'); *cp1=0; } } return 1; } void cleanup() { message_t *curmsg,*nextmsg; attachment_t *curatt,*nextatt; if (!message_list) return; curmsg=message_list; while (curmsg){ nextmsg=curmsg->next; curatt=curmsg->attachment; while(curatt){ nextatt=curatt->next; free(curatt); curatt=nextatt; } free(curmsg->ThisMail); free(curmsg); curmsg=nextmsg; message_list=NULL; } } int directory_routine() { $DESCRIPTOR (fromdsc,"FROM"); $DESCRIPTOR (attachmentdsc,"ATTACHMENT"); $DESCRIPTOR (folderdsc,"FOLDER"); char frombuf[256]; struct dsc$descriptor_s from = {sizeof(frombuf), DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; char folderbuf[256]; struct dsc$descriptor_s folder = {sizeof ("MAIL") - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, "MAIL"}; int select_size = 3; char attachment = 0; char subject[256]; char sender[256]; unsigned int sender_length; unsigned int subject_length; int index; int status,info_stat, msgid; item_t *message_select_in_itmlst; item_t info_in_itmlst[2]; item_t info_out_itmlst[4]; item_t get_in_itmlst[2]; item_t get_out_itmlst[2]; item_t nulllist ={0,0,NULL,NULL}; message_t *tmp_lst,*last_id; attachment_t *attachments,*tmp; char *cp,*cp1,*cp2; int i; int size; char coding[50]; char *record; #define MAX_RECORD_SIZE 255 unsigned int record_length; unsigned int number_records_in_mail; char first = 1; char InternetHeadersAtEnd,InternetMail; index=0; memset(&info_in_itmlst,0,sizeof(info_in_itmlst)); info_in_itmlst[0].item_code = MAIL$_MESSAGE_NEXT; memset(&info_out_itmlst,0,sizeof(info_out_itmlst)); info_out_itmlst[0].item_code = MAIL$_MESSAGE_SENDER; info_out_itmlst[1].item_code = MAIL$_MESSAGE_SUBJECT; info_out_itmlst[2].item_code = MAIL$_MESSAGE_CURRENT_ID; memset(&get_in_itmlst,0,sizeof(get_in_itmlst)); get_in_itmlst[0].item_code = MAIL$_MESSAGE_ID; memset(&get_out_itmlst,0,sizeof(get_out_itmlst)); cleanup(); /* * Get input user name if present. */ if (cli$present (&fromdsc) == CLI$_PRESENT) { from.dsc$a_pointer = frombuf; status = cli$get_value (&fromdsc,&from, &from.dsc$w_length) ; if (!(status&1)) lib$signal (status); from.dsc$a_pointer[from.dsc$w_length] = 0; select_size += sizeof(item_t); } /* * Check presence of attachment qualifier. */ if (cli$present (&attachmentdsc) == CLI$_PRESENT) attachment = 1; /* * Get input folder name if present. */ if (cli$present (&folderdsc) == CLI$_PRESENT){ folder.dsc$a_pointer = folderbuf; folder.dsc$w_length = sizeof (folderbuf); status = cli$get_value (&folderdsc,&folder, &folder.dsc$w_length) ; if (!(status&1)) lib$signal (status); folder.dsc$a_pointer[folder.dsc$w_length] = 0; } if (message_context != 0) mail$message_end(&message_context, &nulllist, &nulllist); message_context = 0; status = mail$message_begin (&message_context,message_in_itmlst, &nulllist); if (!(status&1)) lib$stop(status); /* * Allocate and fill message_select item list. */ message_select_in_itmlst = calloc(select_size,sizeof(item_t)); message_select_in_itmlst[index].buffer =folder.dsc$a_pointer; message_select_in_itmlst[index].buffer_length = folder.dsc$w_length; message_select_in_itmlst[index].item_code = MAIL$_MESSAGE_FOLDER; message_select_in_itmlst[index].return_length = 0; if (cli$present (&fromdsc) == CLI$_PRESENT) { index++; message_select_in_itmlst[index].buffer =from.dsc$a_pointer; message_select_in_itmlst[index].buffer_length = from.dsc$w_length; message_select_in_itmlst[index].item_code = MAIL$_MESSAGE_FROM_SUBSTRING; message_select_in_itmlst[index].return_length = 0; } /* * Select messages according to folder and from criteria. */ VAXC$ESTABLISH (directory_handler) ; status = mail$message_select(&message_context, message_select_in_itmlst, message_select_out_itmlst); free(message_select_in_itmlst); if (!(status & 1)) lib$stop(status); VAXC$ESTABLISH (NULL) ; /* * Get a directory of all message. Ask MAIL to return sender's name, * subject and message id for later processing by the read routine. */ info_out_itmlst[0].buffer = &sender; info_out_itmlst[0].buffer_length = sizeof(sender); info_out_itmlst[0].return_length = &sender_length; info_out_itmlst[1].buffer = &subject; info_out_itmlst[1].buffer_length = sizeof(subject); info_out_itmlst[1].return_length = &subject_length; info_out_itmlst[2].buffer = &msgid; info_out_itmlst[2].buffer_length = sizeof(msgid); info_out_itmlst[2].return_length = 0; message_list = last_id = NULL; index = 0; do { getnext:; memset(sender,0,sizeof(sender)); memset(subject,0,sizeof(subject)); index++; VAXC$ESTABLISH (directory_handler) ; if (setjmp (environment_buffer) == 0){ info_stat = mail$message_info(&message_context, info_in_itmlst, info_out_itmlst); if (info_stat == MAIL$_NOMOREMSG) break; if (!(info_stat & 1)) lib$stop (info_stat); } else break; VAXC$ESTABLISH (NULL) ; tmp_lst = calloc(1,sizeof(message_t)); tmp_lst->next = NULL; tmp_lst->message_id = msgid; /* * If the user selected attachment files display, read the messages * and locates the string attachment or * X-Ms-Attachment"). */ first = 1; InternetMail=0; InternetHeadersAtEnd=0; do{ if (first==1){ get_in_itmlst[0].buffer = &msgid; get_in_itmlst[0].buffer_length = sizeof(msgid); get_in_itmlst[0].return_length = 0; get_in_itmlst[0].item_code = MAIL$_MESSAGE_ID; memset(&get_out_itmlst[0],0,sizeof (item_t)); get_out_itmlst[0].buffer = &number_records_in_mail; get_out_itmlst[0].buffer_length=sizeof(number_records_in_mail); get_out_itmlst[0].item_code = MAIL$_MESSAGE_SIZE; get_out_itmlst[0].return_length = 0; first--; } else { memset(&get_in_itmlst[0],0,sizeof (item_t)); get_in_itmlst[0].item_code = MAIL$_MESSAGE_CONTINUE; record_length = 0; if (!first){ tmp_lst->ThisMail=calloc(number_records_in_mail,MAX_RECORD_SIZE); if (!tmp_lst->ThisMail) lib$stop(SS$_VASFULL); cp = tmp_lst->ThisMail; first--; } get_out_itmlst[0].buffer = cp; get_out_itmlst[0].buffer_length = MAX_RECORD_SIZE; get_out_itmlst[0].return_length = &record_length; get_out_itmlst[0].item_code = MAIL$_MESSAGE_RECORD; } status = mail$message_get(&message_context, get_in_itmlst, get_out_itmlst); if (status == MAIL$_NOMOREREC) break; if (!(status & 1)) lib$stop(status); if (!number_records_in_mail){ free(tmp_lst); goto getnext; } if (status == MAIL$_MSGTEXT){ if ((InternetHeadersAtEnd) && (!strncmp(cp,"% ",2))){ for (i=0;((i< NUMBER_HEADERS) && (strncasecmp(cp+2,InternetHeaders[i].InternetHeader, strlen(InternetHeaders[i].InternetHeader))));i++); if (i< NUMBER_HEADERS){ InternetMail=1; InternetHeaders[i].action(i,cp+2,tmp_lst); } } if (!strcmp(cp,"% ====== Internet headers and postmarks ======")) InternetHeadersAtEnd=1; cp += record_length+1; } } while (status != MAIL$_NOMOREREC); tmp_lst->EndThisMail=cp; if (attachment){ char BoundarySeen; char BoundaryFlag; /* * Search for each Internet header type and call the action routine */ cp1=tmp_lst->ThisMail; BoundarySeen=0; BoundaryFlag=0; while ( cp1 < tmp_lst->EndThisMail){ for (i=0;((i< NUMBER_HEADERS) && (strncasecmp(cp1,InternetHeaders[i].InternetHeader, strlen(InternetHeaders[i].InternetHeader))));i++); if (i< NUMBER_HEADERS){ InternetMail=1; InternetHeaders[i].action(i,cp1,tmp_lst); } else if (tmp_lst->separator){ if ((!strncmp(cp1,"--",2)) && (!strncmp(cp1+2,tmp_lst->separator, strlen(tmp_lst->separator)))){ /* * Add an attachment for the input VAXMail message */ tmp = (attachment_t *)&tmp_lst->attachment; attachments = tmp_lst->attachment; while (attachments != NULL){ tmp = attachments; attachments = attachments->next; } if (tmp_lst->attachment) tmp->endfile=cp1-2; if (!strcmp(cp1+2+strlen(tmp_lst->separator),"--")) break; attachments = calloc(1,sizeof(attachment_t)); attachments->encode_format=TEXT; if (!tmp_lst->attachment) tmp_lst->attachment=attachments; else tmp->next=attachments; BoundarySeen++; BoundaryFlag++; } if ((!*cp1) && (BoundaryFlag)){ for (i=0,attachments=(attachment_t *)&tmp_lst->attachment; i<BoundarySeen; i++,attachments=attachments->next); if (!attachments->filebuff) attachments->filebuff=cp1+2; BoundaryFlag--; } } /* * Handle the case when the SMTP mail starts with "..". * We must replace it with "." */ if ((InternetMail) && (!strncmp(cp1,"..",2))){ /* * copy the buffer until end one character up. */ bcopy(cp1+1,cp1,(long)(tmp_lst->EndThisMail - cp1-1)); /* * Adjust End Pointer */ tmp_lst->EndThisMail--; } cp1 += strlen(cp1)+1; } }/* if attachment */ printf ("#%d %.*s\t \"%.*s\"\n",index,sender_length,sender,subject_length,subject); if (message_list == NULL){ message_list = tmp_lst; last_id = tmp_lst; } else{ last_id->next = tmp_lst; last_id = tmp_lst; } if (attachment){ i=1; for (attachments = tmp_lst->attachment; attachments; attachments=attachments->next){ if(!attachments->endfile) attachments->endfile=tmp_lst->EndThisMail; printf ("\tAttachment #%1d, name=%s,file=%s\n", i++,attachments->name,attachments->file); }/*end for */ }/* if attachment */ } while (info_stat == SS$_NORMAL); printf ("%%MAIL-I-SEL, %d messages selected\n",messages_selected); return (SS$_NORMAL); } /* warn - print a warning message * * DESCRIPTION * * Print an error message listing the program name, the actual error * which occurred and an informational message as to why the error * occurred on the standard error device. The standard error is * flushed after the error is printed to assure that the user gets * the message in a timely fasion. * * * PARAMETERS * * char *who - Pointer to string describing who it is. * char *why - Pointer to string describing why did it failed. */ void warn(char *who, char *why) { fprintf(stderr, "%s: %s\r\n", who, why); fflush(stderr); } /* * output a group of 3 bytes (4 input characters). * the input chars are pointed to by p, they are to * be output to file f. n is used to tell us not to * output all of them at the end of the file. */ outdec(p, f, n,outbuf,m,dontinterpretcrlf) char *p; FILE *f; int n; unsigned char *outbuf; int *m; char dontinterpretcrlf; { int c1, c2, c3; c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; c3 = DEC(p[2]) << 6 | DEC(p[3]); if (n >= 1) { outbuf[*m] = (unsigned char) c1; *m = *m +1; if (((outbuf[*m-1] == '\012') && (!dontinterpretcrlf)) || (*m == 512)){ if (*m == 512) fwrite(outbuf,*m,1, f); else fwrite(outbuf,*m-2,1, f); *m = 0; } } if (n >= 2) { outbuf[*m] = (unsigned char) c2; *m = *m +1; if (((outbuf[*m-1] == '\012') && (!dontinterpretcrlf)) || (*m == 512)){ if (*m == 512) fwrite(outbuf,*m,1, f); else fwrite(outbuf,*m-2,1, f); *m = 0; } } if (n >= 3) { outbuf[*m] = (unsigned char) c3; *m = *m +1; if (((outbuf[*m-1] == '\012') && (!dontinterpretcrlf)) || (*m == 512)){ if (*m == 512) fwrite(outbuf,*m,1, f); else fwrite(outbuf,*m-2,1, f); *m = 0; } } } /* * copy from in to out, decoding as you go along. */ char *decodeit(file, out,dontinterpretcrlf) char *file; FILE *out; char dontinterpretcrlf; { char buf[80]; unsigned char outbuf[512]; char *bp; int m = 0, n; for (;;) { n = DEC(file[0]); if (n <= 0) break; bp = &file[1]; while (n > 0) { outdec(bp, out, n,outbuf, &m,dontinterpretcrlf); bp += 4; n -= 3; } file += strlen(file)+1; } fwrite(outbuf,m,1,out); file += strlen(file)+1; return(file); } /* * getrecordformat determines the type of record format (rfm) for * a given file extension. */ char *getrecordformat(char *filename){ int index = 0; char *extension; char filelowercase[128]; /* * copy and convert to lowercase the filename. */ for (index= 0;index < strlen(filename) + 1;index++) filelowercase[index] = tolower(filename[index]); /* * Locate the extension separator. */ extension = strchr(filelowercase,'.'); /* * If separator located, point to the file extension. */ if (extension != NULL) extension++; /* * Reset used variable. */ index= 0; /* * Loop until found or end of array. */ do { /* * At end of array ? If so, exit loop. */ if (file_to_rfm[index].application == NULL) break; /* * treat the case extension = NULL. */ if (extension == file_to_rfm[index].knowfileextension) return(file_to_rfm[index].record_format); /* * extension points to a valid extension. * Search for a matching extension in array. */ if ((extension != NULL) && (file_to_rfm[index].knowfileextension != NULL) && (strstr(file_to_rfm[index].knowfileextension,extension) != NULL)) return(file_to_rfm[index].record_format); index++; } while(1); return ("rfm=var"); } void uudecode (char *fileptr, char *defaultfilename){ FILE *out; stat_t statbuff; int fd; int mode; char dest[128]; char cp[128]; int i; char *rfm; char dontinterpretcrlf = 1; if (defaultfilename) strcpy(dest,defaultfilename); else dest[0] = '\0'; (void)sscanf(fileptr, "begin %o %s", &mode, cp); if (strlen(dest) == 0) strcpy (dest,cp); /* * Get record format according to file extension name. */ rfm = getrecordformat(dest); /* * create output file */ out = fopen(dest, "w","mrs=512",rfm); if (out == NULL) { perror(dest); return; } /* * if file format equals varaible ("rfm=var"*), skip included crlf */ if (strcmp(rfm,"rfm=var") == 0) dontinterpretcrlf = 0; /* * skip the string "begin mode dest". */ fileptr += strlen(fileptr)+1; chmod(dest, mode); fileptr = decodeit(fileptr, out,dontinterpretcrlf); if (strcmp(fileptr, "end")!= 0) { fprintf(stderr, "%%MAIL-I-NOEND, No end line (UUENCODE format)\r\n"); fclose(out); return; } /* * Work done. Close oputput file. */ fclose(out); /* * Reopen file to get file size and display message. */ if((!stat(dest,&statbuff)) && (statbuff.st_mode & S_IFREG)) fprintf (stderr,"%%MAIL-I-CREATED, attachment file %s created, size \ %1d blocks\r\n", dest,(statbuff.st_size+511)/BLOCKSIZE); return; } /*------------------------------------------------------------------------ decode_64.c Author: Sohail Gani Dept: Mail Interchange Group Date: 30-10-91 ------------------------------------------------------------------------*/ /*------------------------------------------------------------------------ This is the look up table used for the base decoding ------------------------------------------------------------------------*/ /* * convert */ convert (fp,data) FILE *fp; int data[8]; { int i, j, total; i = total = 0; for (j = 128; j >= 1; j /= 2) total += data[i++] * j; fprintf (fp, "%c", total); } /* * process */ process (FILE *fp,char *seg) { char lut[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=', ',' }; int cnt_a, num; int j, k; int which = 0; int index = 0; int reg[3][8]; for (cnt_a = 0; cnt_a < 4; cnt_a++) { if (seg[cnt_a] == '=') break; for (num = 0; num < 64; num++) { if (lut[num] == seg[cnt_a]) { /*------------------------------------------------------------------------ Use base64 look up table to extract 8-bit binary and convert ------------------------------------------------------------------------*/ for (j = 32; j >= 1; j /= 2) { if (num >= j) { num = num % j; reg[which][index] = 1; } else { reg[which][index] = 0; } index++; if (index >= 8) { convert (fp, reg[which]); index = 0; which = (which + 1) % 3; for (k = 0; k < 8; k++) reg[which][k] = 0; } } break; } } } } void decode_64(char *fileptr, char *eof,char *defaultfilename){ int i; char literal; stat_t statbuff; char segment[4]; char *cp,*cp1,*rfm; FILE *fpo; char dest[80]; cp = NULL; if (defaultfilename) strcpy(dest,defaultfilename); else dest[0] = '\0'; if (strlen(dest) == 0) strcpy (dest,standard_output); /* * Get record format according to file extension name. */ /* rfm = getrecordformat(dest); */ rfm=(char *)rfm_fix; /* * Open the output file. */ fpo = fopen (dest, "w","mrs=512",rfm); if (fpo == NULL) { perror(dest); return; } i = 0; /* * Process the input until end of file, ignore "\n" and * deal with eol (i.e. ",") */ while (fileptr < eof){ while (sscanf (fileptr, "%c", &literal) != EOF) { fileptr++; if (literal == '\0') { continue; } if (literal == ',') { fprintf (fpo, "\r\n"); continue; } segment[i++] = literal; if (i >= 4) { process (fpo,segment); i = 0; } }/* while sscanf */ fileptr++; }/* while fileptr != eof */ /* * Let's tidy up */ fprintf (fpo, ""); fclose (fpo); /* * Get file size and display message. */ if((!stat(dest,&statbuff)) && (statbuff.st_mode & S_IFREG)) fprintf (stderr,"%%MAIL-I-CREATED, attachment file %s created, size \ %1d blocks\r\n", dest,(statbuff.st_size+511)/BLOCKSIZE); return; } void quoted_printable(char *fileptr,char *eof,char *defaultfilename, char *rfm){ char *cp,*cp1; FILE *fpo; int i; stat_t statbuff; char dest[80]; char buff[512]; char special_char[3]; cp = NULL; special_char[2]='\0'; if (defaultfilename) strcpy(dest,defaultfilename); else dest[0] = '\0'; if (strlen(dest) == 0) strcpy (dest,standard_output); /* * Open the output file. */ if (strcmp(rfm,"rfm=var")) fpo = fopen (dest, "w","mrs=512",rfm); else fpo = fopen (dest, "w","mrs=512",rfm,"rat=cr"); if (fpo == NULL) { perror(dest); return; } /* * Outputs the data to the file. */ while (fileptr < eof){ /* * Point to special '=' character. */ memset(buff,0,sizeof(buff)); while (((cp = strchr(fileptr,'=')) != NULL) && (*fileptr != '\0')){ *cp = '\0'; strcat(buff,fileptr); *cp='='; cp++; if (!strncmp(cp,"3D",2)){ strcat(buff,"="); fileptr=cp+2; } else if (*(cp+2) == 'X'){ sscanf(cp,"%02X",buff+strlen(buff)); fileptr=cp+3; } else if (!*cp) fileptr=cp+1; else{ strncpy(special_char,cp,2); buff[strlen(buff)]=((special_char[0] - '0') << 4) + (special_char[1] - '0'); fileptr=cp+2; } } strcat(buff,fileptr); fileptr += strlen(fileptr)+1; fprintf(fpo,"%s\n",buff); } fclose (fpo); /* * Get file size and display message. */ if((!stat(dest,&statbuff)) && (statbuff.st_mode & S_IFREG)) fprintf (stderr,"%%MAIL-I-CREATED, attachment file %s created, size \ %1d blocks\r\n", dest,(statbuff.st_size+511)/BLOCKSIZE); return; } void seven_bit(char *fileptr,char *eof,char *defaultfilename){ char *cp,*cp1,*rfm; FILE *fpo; int i; stat_t statbuff; char dest[80]; cp = NULL; if (defaultfilename) strcpy(dest,defaultfilename); else dest[0] = '\0'; if (strlen(dest) == 0) strcpy (dest,standard_output); /* * Get record format according to file extension name. */ if (cp != NULL) strcpy (dest,cp); rfm = getrecordformat(dest); /* * Open the output file. */ fpo = fopen (dest, "w","mrs=512",rfm); if (fpo == NULL) { perror(dest); return; } /* * Outputs the data to the file. */ while (fileptr < eof){ fprintf(fpo,"%s\r\n",fileptr); fileptr += strlen(fileptr)+1; } fclose (fpo); /* * Get file size and display message. */ if((!stat(dest,&statbuff)) && (statbuff.st_mode & S_IFREG)) fprintf (stderr,"%%MAIL-I-CREATED, attachment file %s created, size \ %1d blocks\r\n", dest,(statbuff.st_size+511)/BLOCKSIZE); return; } void output_text(char *fileptr,char *eof,char *defaultfilename){ char *cp,*rfm; FILE *fpo; stat_t statbuff; char dest[80]; cp = NULL; if (defaultfilename) strcpy(dest,defaultfilename); else dest[0] = '\0'; if (strlen(dest) == 0) strcpy (dest,standard_output); /* * Get record format according to file extension name. */ rfm = getrecordformat(dest); /* * Open the output file. */ fpo = fopen (dest, "w","mrs=512",rfm); if (fpo == NULL) { perror(dest); return; } /* * Outputs the data to the file. */ while (fileptr < eof){ fprintf(fpo,"%s\r\n",fileptr); fileptr += strlen(fileptr)+1; for (cp=fileptr;((*cp=='\0') && (cp<eof));cp++); if (cp == eof) break; } fclose (fpo); /* * Get file size and display message. */ if((!stat(dest,&statbuff)) && (statbuff.st_mode & S_IFREG)) fprintf (stderr,"%%MAIL-I-CREATED, attachment file %s created, size \ %1d blocks\r\n", dest,(statbuff.st_size+511)/BLOCKSIZE); return; } int read_routine() { char indexbuf[256],msgnumbuf[256],attachmentbuf[256]; $DESCRIPTOR (attachmentdsc,"ATTACHMENT"); $DESCRIPTOR (indexdsc,"INDEX"); $DESCRIPTOR (msgnumdsc,"P1"); struct dsc$descriptor_s attachment = {sizeof(attachmentbuf), DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; struct dsc$descriptor_s msgnum = {sizeof(msgnumbuf), DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; struct dsc$descriptor_s Index = {sizeof(indexbuf), DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; int indexnum = -1; int message_number,status,i; message_t *tmp_lst; item_t get_in_itmlst[] = { {0,MAIL$_MESSAGE_ID,0,0}, {0,0,0,0}}; item_t get_out_itmlst[] = { {0,MAIL$_MESSAGE_SIZE,0,0}, {0,0,0,0}}; item_t nulllist ={0,0,NULL,NULL}; attachment_t *tmp; char *file; attachmentbuf[0]='\0'; /* * Get message number (Parameter P1). */ msgnum.dsc$a_pointer = msgnumbuf; status = cli$get_value (&msgnumdsc,&msgnum, &msgnum.dsc$w_length) ; if (!(status&1)) lib$signal (status); msgnum.dsc$a_pointer[msgnum.dsc$w_length] = 0; /* * Convert ASCII to decimal. */ if (sscanf (msgnumbuf,"%d",&message_number) == EOF){ printf ("%%MAIL-W-ILLDIGIT, illegal non numeric character\r\n"); return (SS$_NORMAL); } /* * Get index number. */ if (cli$present (&indexdsc) == CLI$_PRESENT) { Index.dsc$a_pointer = indexbuf; status = cli$get_value (&indexdsc,&Index, &Index.dsc$w_length) ; if (!(status&1)) lib$signal (status); Index.dsc$a_pointer[Index.dsc$w_length] = 0; if (sscanf(indexbuf,"%u",&indexnum) != 1) { printf ("%%MAIL-W-INVDIGIT, invalid index digit\r\n"); return (SS$_NORMAL); } } /* * Get input attachment file name if present. */ if (cli$present (&attachmentdsc) == CLI$_PRESENT) { attachment.dsc$a_pointer = attachmentbuf; status = cli$get_value (&attachmentdsc,&attachment, &attachment.dsc$w_length) ; if (!(status&1)) lib$signal (status); attachment.dsc$a_pointer[attachment.dsc$w_length] = 0; } /* * Locate required message id. */ tmp_lst = message_list; if (tmp_lst == NULL) { printf ("%%MAIL-W-NOSELMSG, no selected message\r\n"); return (SS$_NORMAL); } while ((tmp_lst) && (tmp_lst->message_id != message_number)) tmp_lst = tmp_lst->next; if (tmp_lst == NULL) { printf ("%%MAIL-W-NOSUCHMSG, no such message\r\n"); return (SS$_NORMAL); } /* * Check if attachements to message if qualifier present. */ if ((cli$present (&indexdsc) == CLI$_PRESENT) && (!tmp_lst->attachment)){ printf ("%%MAIL-W-NOATTACH, no file attachment to message\r\n"); return (SS$_NORMAL); } /* * Check if attachement qualifier present and index absent and * attachments. */ /* if ((cli$present (&indexdsc) == CLI$_ABSENT) && (cli$present (&attachmentdsc) == CLI$_PRESENT) && (tmp_lst->attachment)){ printf ("%%MAIL-W-NOATTACH, qualifier INDEX absent\r\n"); return (SS$_NORMAL); } /* * Decode buffer. */ if ((tmp_lst->attachment) && (indexnum != -1)) tmp = (attachment_t *)&tmp_lst->attachment; else tmp = NULL; for (i=0;i<indexnum;i++) if (tmp) tmp=tmp->next; /* * did the user requested a specific file and the file was not found * and he diod not specify an index value ? If yes return an error. */ if (cli$present (&attachmentdsc) == CLI$_PRESENT) file = attachmentbuf; else if (tmp) file = tmp->file; else file=(char *)standard_output; if ((tmp == NULL) && (indexnum != -1)){ printf ("%%MAIL-I-NOATTACH, attachment number %1u not found\r\n",indexnum); return(SS$_NORMAL); } if ((tmp != NULL) && (tmp->filebuff != NULL)) switch (tmp->encode_format){ case UUENCODE : uudecode (tmp->filebuff,file); break; case QUOTED_PRINTABLE: quoted_printable(tmp->filebuff, tmp->endfile, file, tmp->rfm_format); break; case SEVEN_BIT: seven_bit (tmp->filebuff, tmp->endfile, file); break; case TEXT : output_text(tmp->filebuff, tmp->endfile, file); break; case BASE64 : decode_64 (tmp->filebuff, tmp->endfile, file); break; case UNKNOWN: default : printf ("%%MAIL-F-UNKNOCODING, Unknown encoding format\r\n"); } else output_text(tmp_lst->ThisMail,tmp_lst->EndThisMail,NULL); return (SS$_NORMAL); } int help_routine() { struct dsc$descriptor_s libspec = {sizeof("MAIL_ATTACHMENT.HLB")-1, DSC$K_DTYPE_T,DSC$K_CLASS_S, "MAIL_ATTACHMENT.HLB"}; struct dsc$descriptor_s linedsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0}; $DESCRIPTOR (topicdsc,"P1"); int status; char topic[80]; /* * Get input topic name if present. */ if (cli$present (&topicdsc) == CLI$_PRESENT) { linedsc.dsc$a_pointer = topic; linedsc.dsc$w_length = sizeof(topic); status = cli$get_value (&topicdsc,&linedsc, &linedsc.dsc$w_length) ; if (!(status&1)) lib$signal (status); } /* * Display help. */ status = lbr$output_help (lib$put_output,0,&linedsc,&libspec, 0,lib$get_input); if (!(status&1)) lib$stop(status); return (SS$_NORMAL); } int exit_routine() { item_t nulllist ={0,0,NULL,NULL}; mail$mailfile_close(&file_context, &nulllist, &nulllist); mail$mailfile_end(&file_context, &nulllist, &nulllist); exit(0); return (SS$_NORMAL); } unsigned long screen_setup() { /* * Returns a keyboard id for a pasteboard */ int kbdid,stat; stat = smg$create_virtual_keyboard(&kbdid,0,0,0); if (!(stat&1)) lib$stop(stat); return (kbdid); } int main () { unsigned int istat,status; $DESCRIPTOR (prompt_descr,"MAIL> "); struct dsc$descriptor_s command_desc; int keyboard_id; item_t nulllist ={0,0,NULL,NULL}; char string[SCREENWIDTH]; istat = CLI$_NORMAL; status = mail$mailfile_begin(&file_context, &nulllist, &nulllist); if (status != SS$_NORMAL) lib$stop(status); status = mail$mailfile_open(&file_context, &nulllist, &nulllist); /* Leave program execution if CTRL-Z has been typed in */ keyboard_id = screen_setup(); do { /* ** Setup the CLASS S descriptor. */ command_desc.dsc$w_length = SCREENWIDTH; command_desc.dsc$b_dtype = DSC$K_DTYPE_T; command_desc.dsc$b_class = DSC$K_CLASS_S; command_desc.dsc$a_pointer = string; status = smg$read_composed_line(&keyboard_id,NULL,&command_desc, &prompt_descr, &command_desc.dsc$w_length, NULL,NULL,NULL, NULL,NULL,NULL,NULL); if (!(status & 1)) break; if (command_desc.dsc$w_length == 0) continue; /* * dispatch only the lines that contain characters (i.e.: do not * dispatch if a return or a CRTL-Z has been entered). If the * command does not exist in the Tables, cli$dispatch will output * a warning error message. If the program has not been linked with * NOTRACEBACK option, the traceback information will follow. */ istat = cli$dcl_parse (&command_desc,&Test,NULL,&NULL,NULL); if (istat == CLI$_NORMAL) { istat = cli$dispatch(); } } while (istat != RMS$_EOF); mail$mailfile_close(&file_context, &nulllist, &nulllist); mail$mailfile_end(&file_context, &nulllist, &nulllist); } $ create cldfile.cld MODULE TEST DEFINE VERB DIRECTORY ROUTINE directory_routine QUALIFIER FROM, NONNEGATABLE, VALUE (type=$file) QUALIFIER ATTACHMENT, NONNEGATABLE QUALIFIER FOLDER, NONNEGATABLE, VALUE (type=$file) DEFINE VERB READ ROUTINE read_routine QUALIFIER ATTACHMENT, NONNEGATABLE, VALUE (type=$file) QUALIFIER INDEX, NONNEGATABLE, VALUE (required,type=$number) PARAMETER P1, VALUE (type=$number) DEFINE VERB HELP ROUTINE help_routine PARAMETER P1, VALUE (type=$file) DEFINE VERB EXIT ROUTINE exit_routine $ create mail_attachment.hlp 1 HELP This program reads OpenVMS mail and optionnaly extracts file attachments that has been encoded with UUENCODE. This command displays help on available commands for this file OpenVMS mail program. 1 DIRECTORY This command lists the mails displaying the "From" and "Subject", and optionally the attachment files. 2 Qualifier 3 /FOLDER Specify the name of a OpenVMS Mail folder. If this qualifier is not specified, the folder defaults to MAIL folder. 3 /FROM Specify the sender's name to select mails from this sender. 3 /ATTACHMENT Requests this program to display the name of attachment files. 2 Example MAIL> DIRE /FOLDER = NEWMAIL Lists the new mails from any sender. MAIL> DIRE /FROM=joe /ATTACHMENT Lists the mails in folder MAIL, sent by user "joe". The ATTACHMENT qualifier will also list attachment file names, if present. 1 EXIT This command exits the program. 1 READ This command reads a specific mail selected by a previous DIRECTORY command. Format: READ <message-number>[/qualifier] 2 Parameter Specify the mail number which is displayed in the DIRECTORY list. 2 Qualifier 3 /ATTACHMENT=filename.ext Specify the filename.ext as read with /ATTACHMENT qualifier of the DIRECTORY command. This qualifier will extract the file filename.ext, thus enabling to use it with another tool, after this program exit. This qualifier is compulsary when filename appeears as "<no name>" 3 /INDEX=number Specify the index as read with /ATTACHMENT qualifier of the DIRECTORY command. 2 Example MAIL> READ 8/INDEX=2/ATTACHMENT=writerms.c Extracts the second attachment from the eigth mail message, number and give it the name of writerms.c MAIL> READ 8 Reads the eigth mail message text. $ $ if f$search ("sys$help:mail_attachment.hlb") .nes. "" then goto compile $ write sys$output "Creating help library sys$help:mail_attachment.hlp..." $ library/create/help sys$help:mail_attachment.hlb mail_attachment.hlp $ $ compile: $ write sys$output "Compiling source files ..." $ set command/object=cldfile.obj cldfile.cld $ if c_include .eqs. "" then goto skip $ deassign vaxc$include $skip: $ cc'compiler_switch'/prefix=all'ccflags' mail_attachments $ $ write sys$output "Linking object files ..." $ if compiler .eqs. "VAXC" then link'lnkflags' mail_attachments,cldfile.obj,- sys$library:vaxcrtl/lib $ if compiler .eqs. "DECC" then link'lnkflags' mail_attachments,cldfile.obj $ $ write sys$output "type $ run mail_attachments" $ $ if c_include .nes. "" then define vaxc$include 'c_include' $ delete mail_attachments.obj;* $ delete cldfile.obj;* $ if P1 .nes. "DEBUG" then delete mail_attachments.c;* $ delete mail_attachment.hlp;* $ delete cldfile.cld;* $ if f$search ("mailmsgdef.h") then delete mailmsgdef.h;* $ exit $end: $ WRITE SYS$OUTPUT "Fatal- No C compiler present in this system" $ exit
REFERENCE(S): OpenVMS Utility Routines Manual (chapter: Mail Utility (MAIL) Routines) Order Number: AA-PV6EC-TK
Did you find this helpful?