midrange.com code scratchpad
Name:
Send MIME e-mail service program
Scriptlanguage:
Plain Text
Tabwidth:
4
Date:
02/25/2010 05:44:44 pm
IP:
Logged
Description:
Sends MIME formatted e-mail. This is based on an e-mail program published in an article by Scott Klement. The recipient address table is optional and the e-mail message table is optional. It was included to give the option to have pre-formatted messages and recipients.
Code:
  1.      h NoMain
  2.      h BndDir('RCHEVA1POC' :'QC2LE')
  3.      h Option(*SrcStmt :*NoDebugIO)
  4.       //--------------------------------------------------------------------------------------------
  5.       //   Program  . . :  UT1010R                     Author . . :  Rick Chevalier
  6.       //   Date . . . . :   8/06/2009
  7.       //   Project  . . :
  8.       //   Purpose  . . :  E-mail interface program
  9.       //--------------------------------------------------------------------------------------------
  10.       //   Modifications:
  11.       //
  12.       //  Project        Date         Developer                  Description
  13.       //--------------------------------------------------------------------------------------------
  14.       // xxxxxxxxx    xx/xx/xxxx   xxxxxxxxxxxxxxx   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  15.       //--------------------------------------------------------------------------------------------
  16.       //
  17.       //--------------------------------------------------------------------------------------------
  18.       // File definitions
  19.       //--------------------------------------------------------------------------------------------
  20.      fSNDEMADR  if   e           k Disk    UsrOpn
  21.       // Senders name and e-mail address
  22.  
  23.      fRCPEMADR  if   e           k Disk    UsrOpn
  24.       // Recipients name and e-mail address
  25.  
  26.      fEMAILMSG  if   e           k Disk    UsrOpn
  27.       // Pre-defined e-mail messages
  28.  
  29.      fRCPTYPES  it   f  142        Disk
  30.       // Recipient types used as pre-runtime array
  31.  
  32.       //--------------------------------------------------------------------------------------------
  33.       // External procedure prototypes
  34.       //--------------------------------------------------------------------------------------------
  35.  
  36.       // Definitions for call to QtmmSendMail
  37.       /copy qcpysrc,sendmail_h
  38.  
  39.       // Definitions for IFS procedures
  40.       /copy qcpysrc,ifsio_h
  41.  
  42.       // C function to create a temporary file
  43.      d CreateTempFile  pr              *   ExtProc('_C_IFS_tmpnam')
  44.      d   string                      39a   Options(*Omit)
  45.  
  46.       //--------------------------------------------------------------------------------------------
  47.       // Internal procedure prototypes
  48.       //--------------------------------------------------------------------------------------------
  49.  
  50.       // Prototypes for exported procedures
  51.       /include qcpysrc,ut1010cpy
  52.  
  53.       // Send CL e-mail message
  54.      d SendCLMail      pr
  55.      d  ErrorCode                     7a
  56.      d  SenderAddrKey                32a
  57.      d  Subject                     128a   Varying
  58.      d  MessageType                   7a
  59.      d  RecipType                     7a
  60.      d  RecipKey                     32a
  61.      d  RecipList                  7277a
  62.      d  MessageKey                   32a   Varying
  63.      d  MailMessage               32000a   Varying
  64.      d  Attachments                   1a
  65.      d  AttachList                 6402a
  66.  
  67.       // Write e-mail header to temp file
  68.      d WriteMailHeader...
  69.      d                 pr             5i 0
  70.      d  SenderKey                    32a   Const
  71.      d  RecipientsKey                32a   Const Options(*Omit)
  72.      d  RecipientsList...
  73.      d                                     LikeDS(AdHocRecipients_t)
  74.      d                                     Options(*Omit)
  75.      d  Subject                     128a   Varying Const
  76.  
  77.       // Write e-mail body to temp file
  78.      d WriteMailbody...
  79.      d                 pr
  80.      d  Message                   32000a   Varying Const
  81.  
  82.       // Add any attachments to the MIME file
  83.      d AddAttachments  pr
  84.      d  Attachments                        LikeDS(AttachmentList_t)
  85.  
  86.       // Write e-mail close to temp file
  87.      d WriteMailClose...
  88.      d                 pr
  89.  
  90.       // Build list of recipients using the recipients file
  91.      d AddPreDefinedRecipients...
  92.      d                 pr             5i 0
  93.      d  HdrRecipients              8192a   Varying
  94.      d  RecipientsKey                      Like(RcpLstKey) Const
  95.  
  96.       // Build list of recipients passed in as parameter
  97.      d AddAdHocRecipients...
  98.      d                 pr
  99.      d  HdrRecipients              8192a   Varying
  100.      d  AdHocRecipients...
  101.      d                                     LikeDS(AdHocRecipients_t)
  102.  
  103.       // Report any errors
  104.      d ReportError     pr
  105.  
  106.       // Generate todays date in SMTP required format
  107.      d MailDate        pr            31A
  108.  
  109.       //  Initialization routine to perform any necessary setup
  110.      d UT1010R_Constructor...
  111.      d                 pr
  112.  
  113.       //  Shutdown routine to perform any necessary closing processing
  114.      d UT1010R_Destructor...
  115.      d                 pr
  116.  
  117.       //--------------------------------------------------------------------------------------------
  118.       // Global variables
  119.       //--------------------------------------------------------------------------------------------
  120.  
  121.       // MIME message boundary.  Must be unique within the message.
  122.      d Boundary        c                   '--=_iSeries_MIME_Boundary'
  123.  
  124.       // List of recipients for API call
  125.      d RecipientList   ds                  LikeDS(ADDTO0100) Dim(25) Inz
  126.  
  127.       // Temporary file used to contain the mime message being sent.
  128.       // This file is used as input by the QtmmSendMail API.
  129.      d TempFile        s             50a   varying
  130.      d TempFileDesc    s             10i 0
  131.  
  132.       // Cross reference array of recipient types
  133.      d RecipientTypes  s              3a   Dim(3) PerRcd(1)
  134.      d                                     FromFile(RCPTYPES)
  135.      d APIType         s              1s 0 Dim(3) Alt(RecipientTypes)
  136.  
  137.       // Determine if constructor has been run or not
  138.      d ConstructorNotRun...
  139.      d                 s               n   Inz(*On)
  140.  
  141.       // Miscellaneous definitions
  142.      d CRLF            c                   x'0d25'
  143.  
  144.       //--------------------------------------------------------------------------------------------
  145.       // Send Ad-hoc mail message
  146.       //--------------------------------------------------------------------------------------------
  147.      p SendAdHocMail   b                   Export
  148.      d SendAdHocMail   pi
  149.      d  ErrorCode                     7a
  150.      d  SenderAddrKey                32a
  151.      d  Recipientskey                32a   Options(*Omit)
  152.      d  RecipientsList...
  153.      d                                     LikeDS(AdHocRecipients_t)
  154.      d                                     Options(*Omit)
  155.      d  Subject                     128a   Varying
  156.      d  MailMessage               32000a   Varying
  157.      d  AttachmentList...
  158.      d                                     LikeDS(AttachmentList_t)
  159.  
  160.       // API error parameter
  161.      d NullError       ds
  162.      d   BytesProv                   10I 0 inz(0)
  163.      d   BytesAvail                  10I 0 inz(0)
  164.  
  165.       // Miscellaneous definitions
  166.      d Index           s              5i 0
  167.      d NbrAddresses    s              5i 0
  168.  
  169.       /Free
  170.  
  171.         // Open files and perform any necessary setup
  172.         If ConstructorNotRun;
  173.           UT1010R_Constructor();
  174.         EndIf;
  175.  
  176.         // create a temporary file in the IFS. This is the e-mail message.
  177.         // mark that file as ccsid 819 (ISO 8859-1 ASCII)
  178.         // and ask IBM i to translate EBCDIC -> ASCII
  179.         TempFile = %str(CreateTempFile(*omit));
  180.         unlink(TempFile);
  181.  
  182.         TempFileDesc = open( TempFile
  183.                  : O_CREAT+O_EXCL+O_WRONLY+O_CCSID
  184.                    +O_TEXTDATA+O_TEXT_CREAT
  185.                  : M_RDWR
  186.                  : 819
  187.                  : 0 );
  188.  
  189.         // Error opening the temporary file
  190.         if (TempFileDesc = -1);
  191.            ReportError();
  192.         endif;
  193.  
  194.         // Place mail header into message temp file
  195.         NbrAddresses = WriteMailHeader(SenderAddrKey :RecipientsKey
  196.                                       :RecipientsList :Subject);
  197.  
  198.         // Place message body into message temp file
  199.         WriteMailBody(MailMessage);
  200.  
  201.         // If there are attachments add them to the mail file
  202.         If AttachmentList.NumberOfAttachments > 0;
  203.           AddAttachments(AttachmentList);
  204.         EndIf;
  205.  
  206.         // End the message and close the file
  207.         WriteMailClose();
  208.         CallP Close(TempFileDesc);
  209.  
  210.         // Send the message
  211.         QtmmSendMail( TempFile
  212.                    : %Len(TempFile)
  213.                    : SenderAddr
  214.                    : %len(SenderAddr)
  215.                    : RecipientList
  216.                    : NbrAddresses
  217.                    : NullError );
  218.  
  219.       /End-Free
  220.  
  221.      p SendAdHocMail   e
  222.  
  223.       //--------------------------------------------------------------------------------------------
  224.       // Send pre-defined mail message
  225.       //--------------------------------------------------------------------------------------------
  226.      p SendPreDefinedMail...
  227.      p                 b                   Export
  228.      d SendPreDefinedMail...
  229.      d                 pi
  230.      d  ErrorCode                     7a
  231.      d  SenderAddrKey                32a
  232.      d  Recipientskey                32a   Options(*Omit)
  233.      d  RecipientsList...
  234.      d                                     LikeDS(AdHocRecipients_t)
  235.      d                                     Options(*Omit)
  236.      d  Subject                     128a   Varying
  237.      d  MessageKey                   32a   Varying
  238.      d  AttachmentList...
  239.      d                                     LikeDS(AttachmentList_t)
  240.  
  241.       // API error parameter
  242.      d NullError       ds
  243.      d   BytesProv                   10I 0 inz(0)
  244.      d   BytesAvail                  10I 0 inz(0)
  245.  
  246.       // Miscellaneous definitions
  247.      d Index           s              5i 0
  248.      d NbrAddresses    s              5i 0
  249.      d EmailTextError  s           4000a   Varying
  250.      d                                     Inz('Message text not found for')
  251.  
  252.       /Free
  253.  
  254.         // Open files and perform any necessary setup
  255.         If ConstructorNotRun;
  256.           UT1010R_Constructor();
  257.         EndIf;
  258.  
  259.         // create a temporary file in the IFS. This is the e-mail message.
  260.         // mark that file as ccsid 819 (ISO 8859-1 ASCII)
  261.         // and ask IBM i to translate EBCDIC -> ASCII
  262.         TempFile = %str(CreateTempFile(*omit));
  263.         unlink(TempFile);
  264.  
  265.         TempFileDesc = open( TempFile
  266.                  : O_CREAT+O_EXCL+O_WRONLY+O_CCSID
  267.                    +O_TEXTDATA+O_TEXT_CREAT
  268.                  : M_RDWR
  269.                  : 819
  270.                  : 0 );
  271.  
  272.         // Error opening the temporary file
  273.         if (TempFileDesc = -1);
  274.            ReportError();
  275.         endif;
  276.  
  277.         // Place mail header into message temp file
  278.         NbrAddresses = WriteMailHeader(SenderAddrKey :RecipientsKey
  279.                                       :RecipientsList :Subject);
  280.  
  281.         // Place message body into message temp file
  282.         MessageID = MessageKey;
  283.         Chain(E) MessageID EMAILMSG;
  284.  
  285.         If Not %Error and %Found(EMAILMSG);
  286.           WriteMailBody(EmailText);
  287.         Else;
  288.           EmailText = EmailTextError + ' ' + MessageKey;
  289.           WriteMailBody(EmailText);
  290.         EndIf;
  291.  
  292.         // If there are attachments add them to the mail file
  293.         If AttachmentList.NumberOfAttachments > 0;
  294.           AddAttachments(AttachmentList);
  295.         EndIf;
  296.  
  297.         // End the message and close the file
  298.         WriteMailClose();
  299.         CallP Close(TempFileDesc);
  300.  
  301.         // Send the message
  302.         QtmmSendMail( TempFile
  303.                    : %Len(TempFile)
  304.                    : SenderAddr
  305.                    : %len(SenderAddr)
  306.                    : RecipientList
  307.                    : NbrAddresses
  308.                    : NullError );
  309.  
  310.       /End-Free
  311.  
  312.      p SendPreDefinedMail...
  313.      p                 e
  314.  
  315.       //--------------------------------------------------------------------------------------------
  316.       // Send CL e-mail message
  317.       //--------------------------------------------------------------------------------------------
  318.      p SendCLMail      b                   Export
  319.      d SendCLMail      pi
  320.      d  ErrorCode                     7a
  321.      d  SenderAddrKey                32a
  322.      d  Subject                     128a   Varying
  323.      d  MessageType                   7a
  324.      d  RecipType                     7a
  325.      d  RecipKey                     32a
  326.      d  pRecipList                 7277a
  327.      d  MessageKey                   32a   Varying
  328.      d  MailMessage               32000a   Varying
  329.      d  Attachments                   1a
  330.      d  AttachList                 6402a
  331.  
  332.       // Fields for calls to mail procedures
  333.      d RecipientsList...
  334.      d                 ds                  LikeDS(AdHocRecipients_t) Inz
  335.      d AttachmentList...
  336.      d                 ds                  LikeDS(AttachmentList_t) Inz
  337.  
  338.       // Convert 5i character field to numeric
  339.      d Cnv5iToNbr      ds
  340.      d  Char5i                        2a
  341.      d  Nbr5i                         5i 0 Overlay(Cnv5iToNbr :1)
  342.  
  343.       // Parameter list recipient
  344.      d ParmListRecip   ds                  Based(ParmListRecip@) Qualified
  345.      d  Name                         32a
  346.      d  Address                     256a
  347.      d  Type                          3a
  348.  
  349.      d ParmListRecipLen...
  350.      d                 s              5i 0 Inz(%Size(ParmListRecip))
  351.  
  352.       // Parameter list attachment
  353.      d ParmListAttach  ds                  LikeDS(AttachmentDetails_t)
  354.      d                                     Based(ParmListAttach@)
  355.  
  356.      d ParmListAttachLen...
  357.      d                 s              5i 0 Inz(%Size(ParmListAttach))
  358.  
  359.       // Miscellaneous definitions
  360.      d Index           s              5i 0
  361.      d Start           s              5i 0 Inz(1)
  362.      d RecipLen        s              5i 0
  363.  
  364.       /Free
  365.  
  366.         // Populate list of ad-hoc recipients
  367.         If RecipType = 'ADHOC';
  368.  
  369.           // Populate number of recipients and position to first one
  370.           Char5i = %SubSt(pRecipList :1 :2);
  371.           RecipientsList.NumberOfRecipients = Nbr5i;
  372.           ParmListRecip@ = %Addr(pRecipList) +
  373.             ((RecipientsList.NumberOfRecipients * 2) + 4);
  374.  
  375.           // Move each recipient to procedure parameter field
  376.           For Index = 1 to RecipientsList.NumberOfRecipients;
  377.             RecipientsList.Recipient(Index).Name =
  378.                                             %TrimR(ParmListRecip.Name);
  379.             RecipientsList.Recipient(Index).Address =
  380.                                             %TrimR(ParmListRecip.Address);
  381.             RecipientsList.Recipient(Index).Type =
  382.                                             %TrimR(ParmListRecip.Type);
  383.             ParmListRecip@ += ParmListRecipLen + 2;
  384.           EndFor;
  385.  
  386.         EndIf;
  387.  
  388.         // Populate list of attachments
  389.         If Attachments = 'Y';
  390.  
  391.           // Get number of attachments
  392.           Char5i = %SubSt(AttachList :1 :2);
  393.           AttachmentList.NumberOfAttachments = Nbr5i;
  394.  
  395.           // Format attachments for the e-mail procedures
  396.           ParmListAttach@ = %Addr(AttachList) +
  397.             ((AttachmentList.NumberOfAttachments * 2) + 4);
  398.  
  399.           // Move each recipient to procedure parameter field
  400.           For Index = 1 to AttachmentList.NumberOfAttachments;
  401.             AttachmentList.Attachment(Index).Name =
  402.                                             ParmListAttach.Name;
  403.             AttachmentList.Attachment(Index).Path =
  404.                                             ParmListAttach.Path;
  405.             ParmListAttach@ += ParmListAttachLen + 2;
  406.           EndFor;
  407.  
  408.         EndIf;
  409.  
  410.         // Determine which procedure to call
  411.         Select;
  412.  
  413.           When MessageType = 'ADHOC' and RecipType = 'ADHOC';
  414.             SendAdHocMail(ErrorCode :SenderAddrKey :*OMIT :RecipientsList
  415.                          :Subject :MailMessage :AttachmentList);
  416.  
  417.           When MessageType = 'ADHOC' and RecipType = 'DEFINED';
  418.             SendAdHocMail(ErrorCode :SenderAddrKey :RecipKey :*OMIT
  419.                          :Subject :MailMessage :AttachmentList);
  420.  
  421.           When MessageType = 'DEFINED' and RecipType = 'ADHOC';
  422.             SendPreDefinedMail(ErrorCode :SenderAddrKey :*OMIT :RecipientsList
  423.                          :Subject :MessageKey :AttachmentList);
  424.  
  425.           When MessageType = 'DEFINED' and RecipType = 'DEFINED';
  426.             SendPreDefinedMail(ErrorCode :SenderAddrKey :RecipKey :*OMIT
  427.                          :Subject :MessageKey :AttachmentList);
  428.         EndSl;
  429.  
  430.       /End-Free
  431.  
  432.      p SendCLMail      e
  433.  
  434.       //--------------------------------------------------------------------------------------------
  435.       // Write e-mail header to temp file
  436.       //--------------------------------------------------------------------------------------------
  437.      p WriteMailHeader...
  438.      p                 b
  439.      d WriteMailHeader...
  440.      d                 pi             5i 0
  441.      d  SenderKey                    32a   Const
  442.      d  RecipientsKey                32a   Const Options(*Omit)
  443.      d  RecipientsList...
  444.      d                                     LikeDS(AdHocRecipients_t)
  445.      d                                     Options(*Omit)
  446.      d  Subject                     128a   Varying Const
  447.  
  448.       // Header string
  449.      d Header          s          32767a   Varying
  450.  
  451.       // Recipient string
  452.      d HdrRecipients   s           8192a   Varying
  453.  
  454.       // Miscellaneous definitions
  455.      d NbrRecipients   s              5i 0
  456.  
  457.       // Key value for default sender address
  458.      d DefaultSender   s             32a   Inz('DEFAULT')
  459.  
  460.       // Constants to change field case
  461.      d Upper           c                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  462.      d Lower           c                   'abcdefghijklmnopqrstuvwxyz'
  463.       /Free
  464.  
  465.         // Get sender name and e-mail address
  466.         Chain SenderKey SNDEMADR;
  467.  
  468.         If Not %Found(SNDEMADR);
  469.           Chain DefaultSender SNDEMADR;
  470.         EndIf;
  471.  
  472.         // Build list of recipients
  473.         If %Addr(RecipientsKey) <> *NULL;
  474.           NbrRecipients = AddPreDefinedRecipients(HdrRecipients :RecipientsKey);
  475.         ElseIf %Addr(RecipientsList) <> *NULL;
  476.           AddAdHocRecipients(HdrRecipients :RecipientsList);
  477.           NbrRecipients = RecipientsList.NumberOfRecipients;
  478.         EndIf;
  479.  
  480.         // Build header string
  481.         Header =
  482.           'From: ' + SenderName + ' <' + %XLate(Upper :Lower :SenderAddr)
  483.         + '>' + CRLF
  484.         + HdrRecipients + CRLF
  485.         + 'Date: ' + MailDate() + CRLF
  486.         + 'Subject: ' + Subject + CRLF
  487.         + 'MIME-Version: 1.0' + CRLF
  488.         + 'Content-Type: multipart/mixed;'
  489.         + ' boundary="' + Boundary + '"' + CRLF
  490.         + CRLF
  491.         + 'Your mail reader doesn''t support MIME!' + CRLF
  492.         + CRLF;
  493.  
  494.         // Write e-mail header to temporary file
  495.         CallP Write(TempFileDesc: %addr(Header)+2: %len(Header));
  496.  
  497.         Return NbrRecipients;
  498.  
  499.       /End-Free
  500.  
  501.      p WriteMailHeader...
  502.      p                 e
  503.  
  504.       //--------------------------------------------------------------------------------------------
  505.       // Write e-mail body to temp file
  506.       //--------------------------------------------------------------------------------------------
  507.      p WriteMailBody...
  508.      p                 b
  509.      d WriteMailbody...
  510.      d                 pi
  511.      d  Message                   32000a   Varying Const
  512.  
  513.      d Body            s          32767a   Varying
  514.  
  515.       /Free
  516.  
  517.         // Build body boundary
  518.         Body = '--' + Boundary + CRLF
  519.           +'Content-type: text/plain' + CRLF
  520.           + CRLF;
  521.  
  522.         // Write body boundary to temporary file
  523.         CallP Write(TempFileDesc: %Addr(Body)+2: %Len(Body));
  524.  
  525.         // Write message body to temporary file
  526.         Body = Message + CRLF;
  527.         CallP Write(TempFileDesc: %Addr(Body)+2: %Len(Body));
  528.  
  529.       /End-Free
  530.  
  531.      p WriteMailBody...
  532.      p                 e
  533.  
  534.       //--------------------------------------------------------------------------------------------
  535.       // Add any attachments to the MIME file
  536.       //--------------------------------------------------------------------------------------------
  537.      p AddAttachments  b
  538.      d AddAttachments  pi
  539.      d  Attachments                        LikeDS(AttachmentList_t)
  540.  
  541.       // Miscellaneous variables
  542.      d Body            s          32767a   Varying
  543.      d Index           s              5i 0
  544.      d MaxAttachments  s              5i 0 Inz(25)
  545.      d MimeType        s             64a   Varying
  546.  
  547.       // Variables to control attachment file
  548.      d AttachmentDesc  s             10i 0
  549.      d AttachmentData  s             54a
  550.      d DataLength      s             10i 0
  551.  
  552.       // Endoded data variables
  553.      d EncodedData     s             74a
  554.      d EncodedLength   s             10i 0
  555.  
  556.       //Include base64 functions
  557.       /copy qcpysrc,apr_b64_h
  558.  
  559.       /Free
  560.  
  561.         If Attachments.NumberOfAttachments > MaxAttachments;
  562.           Attachments.NumberOfAttachments = MaxAttachments;
  563.         EndIf;
  564.  
  565.         For Index = 1 to Attachments.NumberOfAttachments;
  566.  
  567.           //  Insert the headers for the attachment file
  568.           mimeType = 'document/pdf';
  569.  
  570.           Body =
  571.            '--' + boundary + CRLF
  572.           +'Content-Type: ' + mimeType + '; '
  573.           +    'name="' + Attachments.Attachment(Index).Name + '"' + CRLF
  574.           +'Content-Transfer-Encoding: base64' + CRLF
  575.           +'Content-Disposition: attachment; '
  576.           +    'filename="' + Attachments.Attachment(Index).Name + '"' + CRLF
  577.           + CRLF;
  578.  
  579.           CallP Write(TempFileDesc: %Addr(Body)+2: %len(Body));
  580.  
  581.           //  Read the attachment file, and base64
  582.           //  encode it.  Write the results to the
  583.           //  e-mail message.
  584.           AttachmentDesc = open( Attachments.Attachment(Index).Path: O_RDONLY );
  585.  
  586.           If (AttachmentDesc = -1);
  587.             ReportError();
  588.           EndIf;
  589.  
  590.           // Read through input file
  591.           DataLength = read(AttachmentDesc: %Addr(AttachmentData)
  592.                            :%Size(AttachmentData));
  593.  
  594.           DoW DataLength > 0;
  595.  
  596.             // Encode data from the read
  597.             EncodedLength = apr_base64_encode_binary( EncodedData
  598.                                              : AttachmentData
  599.                                              : DataLength ) - 1;
  600.             %SubSt(EncodedData :EncodedLength + 1) = CRLF;
  601.  
  602.             // Add to e-mail message file
  603.             CallP write(TempFileDesc: %Addr(EncodedData): EncodedLength + 2);
  604.  
  605.             // Get next segment of attachment
  606.             DataLength = read(AttachmentDesc: %Addr(AttachmentData)
  607.                              :%Size(AttachmentData));
  608.           EndDo;
  609.  
  610.           CallP close(AttachmentDesc);
  611.  
  612.         EndFor;
  613.  
  614.       /End-Free
  615.  
  616.      p AddAttachments  e
  617.  
  618.       //--------------------------------------------------------------------------------------------
  619.       // Write e-mail close to temp file
  620.       //--------------------------------------------------------------------------------------------
  621.      p WriteMailClose...
  622.      p                 b
  623.      d WriteMailClose...
  624.      d                 pi
  625.  
  626.      d CloseText       s            128a   Varying
  627.  
  628.       /Free
  629.  
  630.         // Build close value
  631.         CloseText = CRLF + '--' + boundary + '--' + CRLF;
  632.  
  633.         // Write message close to temporary file
  634.         CallP Write(TempFileDesc: %Addr(CloseText)+2: %Len(CloseText));
  635.  
  636.       /End-Free
  637.  
  638.      p WriteMailClose...
  639.      p                 e
  640.  
  641.       //--------------------------------------------------------------------------------------------
  642.       // Build list of recipients using the recipients file
  643.       //--------------------------------------------------------------------------------------------
  644.      p AddPreDefinedRecipients...
  645.      p                 b
  646.      d AddPreDefinedRecipients...
  647.      d                 pi             5i 0
  648.      d  HdrRecipients              8192a   Varying
  649.      d  RecipientsKey                      Like(RcpLstKey) Const
  650.  
  651.       // Miscellaneous variables
  652.      d Index           s              5i 0
  653.      d Index2          s              3i 0
  654.  
  655.       // Recipient status
  656.      d ACTIVE          c                   'A'
  657.  
  658.       // Constants to change field case
  659.      d Upper           c                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  660.      d Lower           c                   'abcdefghijklmnopqrstuvwxyz'
  661.  
  662.       // Parts of the header recipients
  663.      d TORecipients    s           8195a   Varying
  664.      d CCRecipients    s           8195a   Varying
  665.      d BCCRecipients   s           8195a   Varying
  666.      d TOCount         s              5i 0 Inz(0)
  667.      d CCCount         s              5i 0 Inz(0)
  668.      d BCCCount        s              5i 0 Inz(0)
  669.  
  670.       /Free
  671.  
  672.         // Build list of recipients
  673.         Index = 0;
  674.         SetLL RecipientsKey RCPEMADR;
  675.         Read RCPEMADR;
  676.  
  677.         // DoW Not %EOF and RecipientsKey = RcpLstKey and Status = ACTIVE;
  678.         DoW Not %EOF and RecipientsKey = RcpLstKey;
  679.  
  680.           // Group recipients by type
  681.           Select;
  682.  
  683.             When %XLate(Lower :Upper :RcpType) = 'TO';
  684.               TOCount += 1;
  685.  
  686.               // First time through add keyword
  687.               If TOCount = 1;
  688.                 CCRecipients = CRLF + 'Cc: ';
  689.  
  690.               // For all except the first add separator
  691.               Else;
  692.                 TORecipients += ', ';
  693.               EndIf;
  694.  
  695.               TORecipients += RcpName + ' <' + %XLate(Upper :Lower :RcpAddr) +
  696.                 '>';
  697.  
  698.             When %XLate(Lower :Upper :RcpType) = 'CC';
  699.               CCCount += 1;
  700.  
  701.               // First time through add keyword
  702.               If CCCount = 1;
  703.                 TORecipients = 'To: ';
  704.  
  705.               // For all except the first add separator
  706.               Else;
  707.                 CCRecipients += ', ';
  708.               EndIf;
  709.  
  710.               CCRecipients += RcpName + ' <' + %XLate(Upper :Lower :RcpAddr) +
  711.                 '>';
  712.  
  713.             When %XLate(Lower :Upper :RcpType) = 'BCC';
  714.               BCCCount += 1;
  715.  
  716.               // First time through add keyword
  717.               If BCCCount = 1;
  718.                 BCCRecipients = CRLF + 'Bcc: ';
  719.  
  720.               // For all except the first add separator
  721.               Else;
  722.                 BCCRecipients += ', ';
  723.               EndIf;
  724.  
  725.               BCCRecipients += RcpName + ' <' + %XLate(Upper :Lower :RcpAddr) +
  726.                 '>';
  727.           EndSl;
  728.  
  729.           // Build list of recipients for API call.  RecipientList is a global DS.
  730.           Index += 1;
  731.           RecipientList(Index).NextOffset = %Size(ADDTO0100);
  732.           RecipientList(Index).AddrLen = %Len(RcpAddr);
  733.           RecipientList(Index).AddrFormat = 'ADDR0100';
  734.           Index2 = %Lookup(RcpType :RecipientTypes);
  735.  
  736.           If Index2 > 0;
  737.             RecipientList(Index).DistType = APIType(Index2);
  738.           Else;
  739.             RecipientList(Index).DistType = ADDR_NORMAL;
  740.           EndIf;
  741.  
  742.           RecipientList(Index).Reserved = 0;
  743.           RecipientList(Index).SmtpAddr = RcpAddr;
  744.  
  745.           Read RCPEMADR;
  746.         EndDo;
  747.  
  748.         // Create MIME recipient text
  749.         HdrRecipients = TORecipients + CCRecipients + BCCRecipients;
  750.  
  751.         // Return number of recipients
  752.         Return Index;
  753.  
  754.       /End-Free
  755.  
  756.      p AddPreDefinedRecipients...
  757.      p                 e
  758.  
  759.       //--------------------------------------------------------------------------------------------
  760.       // Build list of recipients passed in as parameter
  761.       //--------------------------------------------------------------------------------------------
  762.      p AddAdHocRecipients...
  763.      p                 b
  764.      d AddAdHocRecipients...
  765.      d                 pi
  766.      d  HdrRecipients              8192a   Varying
  767.      d  AdHocRecipients...
  768.      d                                     LikeDS(AdHocRecipients_t)
  769.  
  770.       // Miscellaneous variables
  771.      d Index           s              5i 0
  772.      d Index2          s              3i 0
  773.  
  774.       // Recipient status
  775.      d ACTIVE          c                   'A'
  776.  
  777.       // Constants to change field case
  778.      d Upper           c                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  779.      d Lower           c                   'abcdefghijklmnopqrstuvwxyz'
  780.  
  781.       // Parts of the header recipients
  782.      d TORecipients    s           8195a   Varying
  783.      d CCRecipients    s           8195a   Varying
  784.      d BCCRecipients   s           8195a   Varying
  785.      d TOCount         s              5i 0 Inz(0)
  786.      d CCCount         s              5i 0 Inz(0)
  787.      d BCCCount        s              5i 0 Inz(0)
  788.  
  789.       /Free
  790.  
  791.         // Walk through list of recipients
  792.         For Index = 1 to AdHocRecipients.NumberOfRecipients;
  793.  
  794.           // Group recipients by type
  795.           Select;
  796.  
  797.             When %XLate(Lower :Upper :AdHocRecipients.Recipient(Index).Type) =
  798.                  'TO';
  799.               TOCount += 1;
  800.  
  801.               // First time through add keyword
  802.               If TOCount = 1;
  803.                 TORecipients = 'To: ';
  804.  
  805.               // For all except the first add separator
  806.               Else;
  807.                 TORecipients += ', ';
  808.               EndIf;
  809.  
  810.               TORecipients += AdHocRecipients.Recipient(Index).Name + ' <' +
  811.                 %XLate(Upper :Lower :AdHocRecipients.Recipient(Index).Address) +
  812.                 '>';
  813.  
  814.             When %XLate(Lower :Upper :AdHocRecipients.Recipient(Index).Type) =
  815.                  'CC';
  816.               CCCount += 1;
  817.  
  818.               // For all except the first add separator
  819.               If CCCount = 1;
  820.                 CCRecipients = CRLF + 'Cc: ';
  821.  
  822.               // For all except the first add separator
  823.               Else;
  824.                 CCRecipients += ', ';
  825.               EndIf;
  826.  
  827.               CCRecipients += AdHocRecipients.Recipient(Index).Name + ' <' +
  828.                 %XLate(Upper :Lower :AdHocRecipients.Recipient(Index).Address) +
  829.                 '>';
  830.  
  831.             When %XLate(Lower :Upper :AdHocRecipients.Recipient(Index).Type) =
  832.                  'BCC';
  833.               BCCCount += 1;
  834.  
  835.               // First time through add keyword
  836.               If BCCCount = 1;
  837.                 BCCRecipients = CRLF + 'Bcc: ';
  838.  
  839.               // For all except the first add separator
  840.               Else;
  841.                 BCCRecipients += ', ';
  842.               EndIf;
  843.  
  844.               BCCRecipients += AdHocRecipients.Recipient(Index).Name + ' <' +
  845.                 %XLate(Upper :Lower :AdHocRecipients.Recipient(Index).Address) +
  846.                 '>';
  847.           EndSl;
  848.  
  849.           // Build list of recipients for API call.  RecipientList is a global DS.
  850.           RecipientList(Index).NextOffset = %Size(ADDTO0100);
  851.           RecipientList(Index).AddrLen =
  852.                                %Len(AdHocRecipients.Recipient(Index).Address);
  853.           RecipientList(Index).AddrFormat = 'ADDR0100';
  854.           Index2 =
  855.             %Lookup(AdHocRecipients.Recipient(Index).Type :RecipientTypes);
  856.  
  857.           If Index2 > 0;
  858.             RecipientList(Index).DistType = APIType(Index2);
  859.           Else;
  860.             RecipientList(Index).DistType = ADDR_NORMAL;
  861.           EndIf;
  862.  
  863.           RecipientList(Index).Reserved = 0;
  864.           RecipientList(Index).SmtpAddr =
  865.                                AdHocRecipients.Recipient(Index).Address;
  866.         EndFor;
  867.  
  868.         // Create MIME recipient text
  869.         HdrRecipients = TORecipients + CCRecipients + BCCRecipients;
  870.  
  871.       /End-Free
  872.  
  873.      p AddAdHocRecipients...
  874.      p                 e
  875.  
  876.       //--------------------------------------------------------------------------------------------
  877.       // maildate(): Get current date/time in format required for SMTP
  878.       //
  879.       //     For example:  'Mon, 15 Aug 2006 14:30:06 -0500'
  880.       //--------------------------------------------------------------------------------------------
  881.      p MailDate        B
  882.      d MailDate        PI            31A
  883.  
  884.      d CEEUTCO         PR                  opdesc
  885.      d   Hours                       10I 0
  886.      d   Minutes                     10I 0
  887.      d   Seconds                      8F
  888.      d   fc                          12A   options(*omit)
  889.  
  890.      d SUNDAY          C                   d'1899-12-31'
  891.  
  892.      d junk1           s              8F
  893.      d hours           s             10I 0
  894.      d mins            s             10I 0
  895.      d tz_hours        s              2P 0
  896.      d tz_mins         s              2P 0
  897.      d tz              s              5A   varying
  898.  
  899.      d CurTS           s               Z
  900.      d CurTime         s              8a   varying
  901.      d CurDay          s              2p 0
  902.      d CurYear         s              4p 0
  903.      d CurMM           s              2p 0
  904.      d CurMonth        s              3a   varying
  905.      d TempDOW         s             10i 0
  906.      d CurDOW          s              3a   varying
  907.  
  908.      d DateString      s             31a
  909.  
  910.       /free
  911.  
  912.          //
  913.          //  Calculate the Timezone in format '+0000', for example
  914.          //    CST should show up as '-0600'
  915.          //
  916.  
  917.          CEEUTCO(hours: mins: junk1: *omit);
  918.          tz_hours = %abs(hours);
  919.          tz_mins = mins;
  920.  
  921.          if (hours < 0);
  922.             tz = '-';
  923.          else;
  924.             tz = '+';
  925.          endif;
  926.  
  927.          tz += %editc(tz_hours:'X') + %editc(tz_mins:'X');
  928.  
  929.          //
  930.          //  Get the current time and convert it to the format
  931.          //    specified for e-mail in RFC 2822
  932.          //
  933.  
  934.          CurTS = %timestamp();
  935.  
  936.          CurTime = %char(%time(CurTS): *HMS:);
  937.  
  938.          CurDay  = %subdt(CurTS: *DAYS);
  939.          CurYear = %subdt(CurTS: *YEARS);
  940.          CurMM   = %subdt(CurTS: *MONTHS);
  941.  
  942.          select;
  943.          when CurMM = 1;
  944.            CurMonth = 'Jan';
  945.          when CurMM = 2;
  946.            CurMonth = 'Feb';
  947.          when CurMM = 3;
  948.            CurMonth = 'Mar';
  949.          when CurMM = 4;
  950.            CurMonth = 'Apr';
  951.          when CurMM = 5;
  952.            CurMonth = 'May';
  953.          when CurMM = 6;
  954.            CurMonth = 'Jun';
  955.          when CurMM = 7;
  956.            CurMonth = 'Jul';
  957.          when CurMM = 8;
  958.            CurMonth = 'Aug';
  959.          when CurMM = 9;
  960.            CurMonth = 'Sep';
  961.          when CurMM = 10;
  962.            CurMonth = 'Oct';
  963.          when CurMM = 11;
  964.            CurMonth = 'Nov';
  965.          when CurMM = 12;
  966.            CurMonth = 'Dec';
  967.          endsl;
  968.  
  969.          TempDOW = %diff( %date(CurTS) : SUNDAY : *DAYS );
  970.          TempDOW = %rem( TempDOW : 7 );
  971.  
  972.          Select;
  973.          when TempDOW = 0;
  974.            CurDOW = 'Sun';
  975.          when TempDOW = 1;
  976.            CurDOW = 'Mon';
  977.          when TempDOW = 2;
  978.            CurDOW = 'Tue';
  979.          when TempDOW = 3;
  980.            CurDOW = 'Wed';
  981.          when TempDOW = 4;
  982.            CurDOW = 'Thu';
  983.          when TempDOW = 5;
  984.            CurDOW = 'Fri';
  985.          when TempDOW = 6;
  986.            CurDOW = 'Sat';
  987.          endsl;
  988.  
  989.          DateString = CurDOW + ', '
  990.                     + %editc( CurDay: 'X' ) + ' '
  991.                     + CurMonth + ' '
  992.                     + %editc( CurYear: 'X' ) + ' '
  993.                     + CurTime + ' '
  994.                     + tz;
  995.  
  996.          return DateString;
  997.  
  998.       /end-free
  999.  
  1000.      p MailDate        e
  1001.  
  1002.       *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1003.       * ReportError():  Send an escape message explaining any errors
  1004.       *                 that occurred.
  1005.       *
  1006.       *  This function requires binding directory QC2LE in order
  1007.       *  to access the __errno() function.
  1008.       *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1009.      P ReportError     B
  1010.      D ReportError     PI
  1011.  
  1012.      D get_errno       PR              *   ExtProc('__errno')
  1013.      D ptrToErrno      s               *
  1014.      D errno           s             10I 0 based(ptrToErrno)
  1015.  
  1016.      D QMHSNDPM        PR                  ExtPgm('QMHSNDPM')
  1017.      D   MessageID                    7A   Const
  1018.      D   QualMsgF                    20A   Const
  1019.      D   MsgData                      1A   Const
  1020.      D   MsgDtaLen                   10I 0 Const
  1021.      D   MsgType                     10A   Const
  1022.      D   CallStkEnt                  10A   Const
  1023.      D   CallStkCnt                  10I 0 Const
  1024.      D   MessageKey                   4A
  1025.      D   ErrorCode                 8192A   options(*varsize)
  1026.  
  1027.      D ErrorCode       DS                  qualified
  1028.      D  BytesProv              1      4I 0 inz(0)
  1029.      D  BytesAvail             5      8I 0 inz(0)
  1030.  
  1031.      D MsgKey          S              4A
  1032.      D MsgID           s              7A
  1033.  
  1034.       /free
  1035.  
  1036.          ptrToErrno = get_errno();
  1037.          MsgID = 'CPE' + %char(errno);
  1038.  
  1039.          QMHSNDPM( MsgID
  1040.                  : 'QCPFMSG   *LIBL'
  1041.                  : ' '
  1042.                  : 0
  1043.                  : '*ESCAPE'
  1044.                  : '*PGMBDY'
  1045.                  : 1
  1046.                  : MsgKey
  1047.                  : ErrorCode         );
  1048.  
  1049.       /end-free
  1050.  
  1051.      P ReportError     E
  1052.  
  1053.       //--------------------------------------------------------------------------------------------
  1054.       //  Initialization routine to perform any necessary setup
  1055.       //--------------------------------------------------------------------------------------------
  1056.      p UT1010R_Constructor...
  1057.      p                 b
  1058.      d UT1010R_Constructor...
  1059.      d                 pi
  1060.  
  1061.       /Free
  1062.  
  1063.         If Not %Open(SNDEMADR);
  1064.           Open SNDEMADR;
  1065.         EndIf;
  1066.  
  1067.         If Not %Open(RCPEMADR);
  1068.           Open RCPEMADR;
  1069.         EndIf;
  1070.  
  1071.         If Not %Open(EMAILMSG);
  1072.           Open EMAILMSG;
  1073.         EndIf;
  1074.  
  1075.         ConstructorNotRun = *Off;
  1076.  
  1077.       /End-Free
  1078.  
  1079.      p UT1010R_Constructor...
  1080.      p                 e
  1081.  
  1082.       //--------------------------------------------------------------------------------------------
  1083.       //  Shutdown routine to perform any necessary closing processing
  1084.       //--------------------------------------------------------------------------------------------
  1085.      p UT1010R_Destructor...
  1086.      p                 b                   Export
  1087.      d UT1010R_Destructor...
  1088.      d                 pi
  1089.  
  1090.       /Free
  1091.  
  1092.         If %Open(SNDEMADR);
  1093.           Close SNDEMADR;
  1094.         EndIf;
  1095.  
  1096.         If %Open(RCPEMADR);
  1097.           Close RCPEMADR;
  1098.         EndIf;
  1099.  
  1100.         If %Open(EMAILMSG);
  1101.           Close EMAILMSG;
  1102.         EndIf;
  1103.  
  1104.         If %Open(RCPTYPES);
  1105.           Close RCPTYPES;
  1106.         EndIf;
  1107.  
  1108.       /End-Free
  1109.  
  1110.      p UT1010R_Destructor...
  1111.      p                 e
  1112.  
  1113. SMTP copybook
  1114.       /if defined(SENDMAIL_H)
  1115.       /eof
  1116.       /endif
  1117.       /define SENDMAIL_H
  1118.  
  1119.      D QtmmSendMail    PR                  ExtProc('QtmmSendMail')
  1120.      D   FileName                   255A   const options(*varsize)
  1121.      D   FileNameLen                 10I 0 const
  1122.      D   MsgFrom                    256A   const options(*varsize)
  1123.      D   MsgFromLen                  10I 0 const
  1124.      D   RecipBuf                          likeds(ADDTO0100)
  1125.      D                                     dim(32767)
  1126.      D                                     options(*varsize)
  1127.      D   NumRecips                   10I 0 const
  1128.      D   ErrorCode                 8000A   options(*varsize)
  1129.  
  1130.      D ADDTO0100       ds                  qualified
  1131.      D                                     based(Template)
  1132.      D   NextOffset                  10I 0
  1133.      D   AddrLen                     10I 0
  1134.      D   AddrFormat                   8A
  1135.      D   DistType                    10I 0
  1136.      D   Reserved                    10I 0
  1137.      D   SmtpAddr                   256A
  1138.  
  1139.      D ADDR_NORMAL     C                   CONST(0)
  1140.      D ADDR_CC         C                   CONST(1)
  1141.      D ADDR_BCC        C                   CONST(2)
  1142.  
  1143. IFS I/O copybook from Scott Klement
  1144.      /*-                                                                            +
  1145.       * Copyright (c) 2002-2006 Scott C. Klement                                    +
  1146.       * All rights reserved.                                                        +
  1147.       *                                                                             +
  1148.       * Redistribution and use in source and binary forms, with or without          +
  1149.       * modification, are permitted provided that the following conditions          +
  1150.       * are met:                                                                    +
  1151.       * 1. Redistributions of source code must retain the above copyright           +
  1152.       *    notice, this list of conditions and the following disclaimer.            +
  1153.       * 2. Redistributions in binary form must reproduce the above copyright        +
  1154.       *    notice, this list of conditions and the following disclaimer in the      +
  1155.       *    documentation and/or other materials provided with the distribution.     +
  1156.       *                                                                             +
  1157.       * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND      +
  1158.       * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE       +
  1159.       * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  +
  1160.       * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE     +
  1161.       * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  +
  1162.       * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS     +
  1163.       * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)       +
  1164.       * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  +
  1165.       * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   +
  1166.       * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF      +
  1167.       * SUCH DAMAGE.                                                                +
  1168.       *                                                                             +
  1169.       */                                                                            +
  1170.      D/if defined(IFSIO_H)
  1171.      D/eof
  1172.      D/endif
  1173.  
  1174.      D/define IFSIO_H
  1175.  
  1176.       **********************************************************************
  1177.       * Some CCSID definitions that I've found useful
  1178.       **********************************************************************
  1179.      D CP_MSDOS        C                   437
  1180.      D CP_ISO8859_1    C                   819
  1181.      D CP_WINDOWS      C                   1252
  1182.      D CP_UTF8         C                   1208
  1183.      D CP_UCS2         C                   1200
  1184.      D CP_CURJOB       C                   0
  1185.  
  1186.       **********************************************************************
  1187.       *  Flags for use in open()
  1188.       *
  1189.       * More than one can be used -- add them together.
  1190.       **********************************************************************
  1191.       *  00000000000000000000000000000001          Reading Only
  1192.      D O_RDONLY        C                   1
  1193.       *  00000000000000000000000000000010          Writing Only
  1194.      D O_WRONLY        C                   2
  1195.       *  00000000000000000000000000000100          Reading & Writing
  1196.      D O_RDWR          C                   4
  1197.       *  00000000000000000000000000001000          Create File if needed
  1198.      D O_CREAT         C                   8
  1199.       *  00000000000000000000000000010000          Exclusively create --
  1200.       *                                              open will fail if it
  1201.       *                                              already exists.
  1202.      D O_EXCL          C                   16
  1203.       *  00000000000000000000000000100000          Assign a CCSID to new
  1204.       *                                            file.
  1205.      D O_CCSID         C                   32
  1206.       *  00000000000000000000000001000000          Truncate file to 0 bytes
  1207.      D O_TRUNC         C                   64
  1208.       *  00000000000000000000000100000000          Append to file
  1209.       *                                            (write data at end only)
  1210.      D O_APPEND        C                   256
  1211.       *  00000000000000000000010000000000          Synchronous write
  1212.      D O_SYNC          C                   1024
  1213.       *  00000000000000000000100000000000          Sync write, data only
  1214.      D O_DSYNC         C                   2048
  1215.       *  00000000000000000001000000000000          Sync read
  1216.      D O_RSYNC         C                   4096
  1217.       *  00000000000000001000000000000000          No controlling terminal
  1218.      D O_NOCTTY        C                   32768
  1219.       *  00000000000000010000000000000000          Share with readers only
  1220.      D O_SHARE_RDONLY  C                   65536
  1221.       *  00000000000000100000000000000000          Share with writers only
  1222.      D O_SHARE_WRONLY  C                   131072
  1223.       *  00000000000001000000000000000000          Share with read & write
  1224.      D O_SHARE_RDWR    C                   262144
  1225.       *  00000000000010000000000000000000          Share with nobody.
  1226.      D O_SHARE_NONE    C                   524288
  1227.       *  00000000100000000000000000000000          Assign a code page
  1228.      D O_CODEPAGE      C                   8388608
  1229.       *  00000001000000000000000000000000          Open in text-mode
  1230.      D O_TEXTDATA      C                   16777216
  1231.       /if defined(*V5R2M0)
  1232.       *  00000010000000000000000000000000          Allow text translation
  1233.       *                                            on newly created file.
  1234.       * Note: O_TEXT_CREAT requires all of the following flags to work:
  1235.       *           O_CREAT+O_TEXTDATA+(O_CODEPAGE or O_CCSID)
  1236.      D O_TEXT_CREAT    C                   33554432
  1237.       /endif
  1238.       *  00001000000000000000000000000000          Inherit mode from dir
  1239.      D O_INHERITMODE   C                   134217728
  1240.       *  00100000000000000000000000000000          Large file access
  1241.       *                                            (for >2GB files)
  1242.      D O_LARGEFILE     C                   536870912
  1243.  
  1244.       **********************************************************************
  1245.       * Access mode flags for access() and accessx()
  1246.       *
  1247.       *   F_OK = File Exists
  1248.       *   R_OK = Read Access
  1249.       *   W_OK = Write Access
  1250.       *   X_OK = Execute or Search
  1251.       **********************************************************************
  1252.      D F_OK            C                   0
  1253.      D R_OK            C                   4
  1254.      D W_OK            C                   2
  1255.      D X_OK            C                   1
  1256.  
  1257.       **********************************************************************
  1258.       * class of users flags for accessx()
  1259.       *
  1260.       *   ACC_SELF = Check access based on effective uid/gid
  1261.       *   ACC_INVOKER = Check access based on real uid/gid
  1262.       *                 ( this is equvalent to calling access() )
  1263.       *   ACC_OTHERS = Check access of someone not the owner
  1264.       *   ACC_ALL = Check access of all users
  1265.       **********************************************************************
  1266.      D ACC_SELF        C                   0
  1267.      D ACC_INVOKER     C                   1
  1268.      D ACC_OTHERS      C                   8
  1269.      D ACC_ALL         C                   32
  1270.  
  1271.       **********************************************************************
  1272.       *      Mode Flags.
  1273.       *         basically, the mode parm of open(), creat(), chmod(),etc
  1274.       *         uses 9 least significant bits to determine the
  1275.       *         file's mode. (peoples access rights to the file)
  1276.       *
  1277.       *           user:       owner    group    other
  1278.       *           access:     R W X    R W X    R W X
  1279.       *           bit:        8 7 6    5 4 3    2 1 0
  1280.       *
  1281.       * (This is accomplished by adding the flags below to get the mode)
  1282.       **********************************************************************
  1283.       *                                         owner authority
  1284.      D S_IRUSR         C                   256
  1285.      D S_IWUSR         C                   128
  1286.      D S_IXUSR         C                   64
  1287.      D S_IRWXU         C                   448
  1288.       *                                         group authority
  1289.      D S_IRGRP         C                   32
  1290.      D S_IWGRP         C                   16
  1291.      D S_IXGRP         C                   8
  1292.      D S_IRWXG         C                   56
  1293.       *                                         other people
  1294.      D S_IROTH         C                   4
  1295.      D S_IWOTH         C                   2
  1296.      D S_IXOTH         C                   1
  1297.      D S_IRWXO         C                   7
  1298.       *                                         special modes:
  1299.       *                                         restrict rename/unlink
  1300.      D S_ISVTX         C                    512
  1301.       *                                         Set effective GID
  1302.      D S_ISGID         C                   1024
  1303.       *                                         Set effective UID
  1304.      D S_ISUID         C                   2048
  1305.  
  1306.       **********************************************************************
  1307.       * My own special MODE shortcuts for open() (instead of those above)
  1308.       **********************************************************************
  1309.      D M_RDONLY        C                   const(292)
  1310.      D M_RDWR          C                   const(438)
  1311.      D M_RWX           C                   const(511)
  1312.  
  1313.       **********************************************************************
  1314.       * "whence" constants for use with seek(), lseek() and others
  1315.       **********************************************************************
  1316.       /if not defined(SEEK_WHENCE_VALUES)
  1317.      D SEEK_SET        C                   CONST(0)
  1318.      D SEEK_CUR        C                   CONST(1)
  1319.      D SEEK_END        C                   CONST(2)
  1320.       /define SEEK_WHENCE_VALUES
  1321.       /endif
  1322.  
  1323.       **********************************************************************
  1324.       * flags specified in the f_flags element of the ds_statvfs
  1325.       *   data structure used by the statvfs() API
  1326.       **********************************************************************
  1327.      D ST_RDONLY...
  1328.      D                 C                   CONST(1)
  1329.      D ST_NOSUID...
  1330.      D                 C                   CONST(2)
  1331.      D ST_CASE_SENSITITIVE...
  1332.      D                 C                   CONST(4)
  1333.      D ST_CHOWN_RESTRICTED...
  1334.      D                 C                   CONST(8)
  1335.      D ST_THREAD_SAFE...
  1336.      D                 C                   CONST(16)
  1337.      D ST_DYNAMIC_MOUNT...
  1338.      D                 C                   CONST(32)
  1339.      D ST_NO_MOUNT_OVER...
  1340.      D                 C                   CONST(64)
  1341.      D ST_NO_EXPORTS...
  1342.      D                 C                   CONST(128)
  1343.      D ST_SYNCHRONOUS...
  1344.      D                 C                   CONST(256)
  1345.  
  1346.       **********************************************************************
  1347.       * Constants used by pathconf() API
  1348.       **********************************************************************
  1349.      D PC_CHOWN_RESTRICTED...
  1350.      D                 C                   0
  1351.      D PC_LINK_MAX...
  1352.      D                 C                   1
  1353.      D PC_MAX_CANON...
  1354.      D                 C                   2
  1355.      D PC_MAX_INPUT...
  1356.      D                 C                   3
  1357.      D PC_NAME_MAX...
  1358.      D                 C                   4
  1359.      D PC_NO_TRUNC...
  1360.      D                 C                   5
  1361.      D PC_PATH_MAX...
  1362.      D                 C                   6
  1363.      D PC_PIPE_BUF...
  1364.      D                 C                   7
  1365.      D PC_VDISABLE...
  1366.      D                 C                   8
  1367.      D PC_THREAD_SAFE...
  1368.      D                 C                   9
  1369.  
  1370.       **********************************************************************
  1371.       * Constants used by sysconf() API
  1372.       **********************************************************************
  1373.      D SC_CLK_TCK...
  1374.      D                 C                   2
  1375.      D SC_NGROUPS_MAX...
  1376.      D                 C                   3
  1377.      D SC_OPEN_MAX...
  1378.      D                 C                   4
  1379.      D SC_STREAM_MAX...
  1380.      D                 C                   5
  1381.      D SC_CCSID...
  1382.      D                 C                   10
  1383.      D SC_PAGE_SIZE...
  1384.      D                 C                   11
  1385.      D SC_PAGESIZE...
  1386.      D                 C                   12
  1387.  
  1388.       **********************************************************************
  1389.       * File Information Structure (stat)
  1390.       *   struct stat {
  1391.       *     mode_t         st_mode;       /* File mode                       */
  1392.       *     ino_t          st_ino;        /* File serial number              */
  1393.       *     nlink_t        st_nlink;      /* Number of links                 */
  1394.       *     unsigned short st_reserved2;  /* Reserved                    @B4A*/
  1395.       *     uid_t          st_uid;        /* User ID of the owner of file    */
  1396.       *     gid_t          st_gid;        /* Group ID of the group of file   */
  1397.       *     off_t          st_size;       /* For regular files, the file
  1398.       *                                      size in bytes                   */
  1399.       *     time_t         st_atime;      /* Time of last access             */
  1400.       *     time_t         st_mtime;      /* Time of last data modification  */
  1401.       *     time_t         st_ctime;      /* Time of last file status change */
  1402.       *     dev_t          st_dev;        /* ID of device containing file    */
  1403.       *     size_t         st_blksize;    /* Size of a block of the file     */
  1404.       *     unsigned long  st_allocsize;  /* Allocation size of the file     */
  1405.       *     qp0l_objtype_t st_objtype;    /* AS/400 object type              */
  1406.       *     char           st_reserved3;  /* Reserved                    @B4A*/
  1407.       *     unsigned short st_codepage;   /* Object data codepage            */
  1408.       *     unsigned short st_ccsid;      /* Object data ccsid           @AAA*/
  1409.       *     dev_t          st_rdev;       /* Device ID (if character special */
  1410.       *                                   /* or block special file)      @B4A*/
  1411.       *     nlink32_t      st_nlink32;    /* Number of links-32 bit      @B5C*/
  1412.       *     dev64_t        st_rdev64;     /* Device ID - 64 bit form     @B4A*/
  1413.       *     dev64_t        st_dev64;      /* ID of device containing file -  */
  1414.       *                                   /* 64 bit form.                @B4A*/
  1415.       *     char           st_reserved1[36]; /* Reserved                 @B4A*/
  1416.       *     unsigned int   st_ino_gen_id; /* File serial number generation id
  1417.       *  };
  1418.       *                                                                  @A2A*/
  1419.       **********************************************************************
  1420.      D statds          DS                  qualified
  1421.      D                                     BASED(Template)
  1422.      D  st_mode                      10U 0
  1423.      D  st_ino                       10U 0
  1424.      D  st_nlink                      5U 0
  1425.      D  st_reserved2                  5U 0
  1426.      D  st_uid                       10U 0
  1427.      D  st_gid                       10U 0
  1428.      D  st_size                      10I 0
  1429.      D  st_atime                     10I 0
  1430.      D  st_mtime                     10I 0
  1431.      D  st_ctime                     10I 0
  1432.      D  st_dev                       10U 0
  1433.      D  st_blksize                   10U 0
  1434.      D  st_allocsize                 10U 0
  1435.      D  st_objtype                   11A
  1436.      D  st_reserved3                  1A
  1437.      D  st_codepage                   5U 0
  1438.      D  st_ccsid                      5U 0
  1439.      D  st_rdev                      10U 0
  1440.      D  st_nlink32                   10U 0
  1441.      D  st_rdev64                    20U 0
  1442.      D  st_dev64                     20U 0
  1443.      D  st_reserved1                 36A
  1444.      D  st_ino_gen_id                10U 0
  1445.  
  1446.  
  1447.       **********************************************************************
  1448.       * File Information Structure, Large File Enabled (stat64)
  1449.       *   struct stat64 {                                                    */
  1450.       *     mode_t         st_mode;       /* File mode                       */
  1451.       *     ino_t          st_ino;        /* File serial number              */
  1452.       *     uid_t          st_uid;        /* User ID of the owner of file    */
  1453.       *     gid_t          st_gid;        /* Group ID of the group of fileA2A*/
  1454.       *     off64_t        st_size;       /* For regular files, the file     */
  1455.       *                                      size in bytes                   */
  1456.       *     time_t         st_atime;      /* Time of last access             */
  1457.       *     time_t         st_mtime;      /* Time of last data modification2A*/
  1458.       *     time_t         st_ctime;      /* Time of last file status changeA*/
  1459.       *     dev_t          st_dev;        /* ID of device containing file    */
  1460.       *     size_t         st_blksize;    /* Size of a block of the file     */
  1461.       *     nlink_t        st_nlink;      /* Number of links                 */
  1462.       *     unsigned short st_codepage;   /* Object data codepage            */
  1463.       *     unsigned long long st_allocsize; /* Allocation size of the file2A*/
  1464.       *     unsigned int   st_ino_gen_id; /* File serial number generationAid*/
  1465.       *                                                                      */
  1466.       *     qp0l_objtype_t st_objtype;    /* AS/400 object type              */
  1467.       *     char           st_reserved2[5]; /* Reserved                  @B4A*/
  1468.       *     dev_t          st_rdev;       /* Device ID (if character specialA*/
  1469.       *                                   /* or block special file)      @B4A*/
  1470.       *     dev64_t        st_rdev64;     /* Device ID - 64 bit form     @B4A*/
  1471.       *     dev64_t        st_dev64;      /* ID of device containing file@-2A*/
  1472.       *                                   /* 64 bit form.                @B4A*/
  1473.       *     nlink32_t      st_nlink32;    /* Number of links-32 bit      @B5A*/
  1474.       *     char           st_reserved1[26]; /* Reserved            @B4A @B5C*/
  1475.       *     unsigned short st_ccsid;      /* Object data ccsid           @AAA*/
  1476.       *  };                                                                  */
  1477.       *
  1478.       **********************************************************************
  1479.      D statds64        DS                  qualified
  1480.      D                                     BASED(Template)
  1481.      D  st_mode                      10U 0
  1482.      D  st_ino                       10U 0
  1483.      D  st_uid                       10U 0
  1484.      D  st_gid                       10U 0
  1485.      D  st_size                      20I 0
  1486.      D  st_atime                     10I 0
  1487.      D  st_mtime                     10I 0
  1488.      D  st_ctime                     10I 0
  1489.      D  st_dev                       10U 0
  1490.      D  st_blksize                   10U 0
  1491.      D  st_nlink                      5U 0
  1492.      D  st_codepage                   5U 0
  1493.      D  st_allocsize                 20U 0
  1494.      D  st_ino_gen_id                10U 0
  1495.      D  st_objtype                   11A
  1496.      D  st_reserved2                  5A
  1497.      D  st_rdev                      10U 0
  1498.      D  st_rdev64                    20U 0
  1499.      D  st_dev64                     20U 0
  1500.      D  st_nlink32                   10U 0
  1501.      D  st_reserved1                 26A
  1502.      D  st_ccsid                      5U 0
  1503.  
  1504.       **********************************************************************
  1505.       * ds_statvfs - data structure to receive file system info
  1506.       *
  1507.       *   f_bsize   = file system block size (in bytes)
  1508.       *   f_frsize  = fundamental block size in bytes.
  1509.       *                if this is zero, f_blocks, f_bfree and f_bavail
  1510.       *                are undefined.
  1511.       *   f_blocks  = total number of blocks (in f_frsize)
  1512.       *   f_bfree   = total free blocks in filesystem (in f_frsize)
  1513.       *   f_bavail  = total blocks available to users (in f_frsize)
  1514.       *   f_files   = total number of file serial numbers
  1515.       *   f_ffree   = total number of unused file serial numbers
  1516.       *   f_favail  = number of available file serial numbers to users
  1517.       *   f_fsid    = filesystem ID.  This will be 4294967295 if it's
  1518.       *                too large for a 10U 0 field. (see f_fsid64)
  1519.       *   f_flag    = file system flags (see below)
  1520.       *   f_namemax = max filename length.  May be 4294967295 to
  1521.       *                indicate that there is no maximum.
  1522.       *   f_pathmax = max pathname legnth.  May be 4294967295 to
  1523.       *                indicate that there is no maximum.
  1524.       *   f_objlinkmax = maximum number of hard-links for objects
  1525.       *                other than directories
  1526.       *   f_dirlinkmax = maximum number of hard-links for directories
  1527.       *   f_fsid64  = filesystem id (in a 64-bit integer)
  1528.       *   f_basetype = null-terminated string containing the file
  1529.       *                  system type name.  For example, this might
  1530.       *                  be "root" or "Network File System (NFS)"
  1531.       *
  1532.       *  Since f_basetype is null-terminated, you should read it
  1533.       *  in ILE RPG with:
  1534.       *       myString = %str(%addr(ds_statvfs.f_basetype))
  1535.       **********************************************************************
  1536.      D ds_statvfs      DS                  qualified
  1537.      D                                     BASED(Template)
  1538.      D  f_bsize                      10U 0
  1539.      D  f_frsize                     10U 0
  1540.      D  f_blocks                     20U 0
  1541.      D  f_bfree                      20U 0
  1542.      D  f_bavail                     20U 0
  1543.      D  f_files                      10U 0
  1544.      D  f_ffree                      10U 0
  1545.      D  f_favail                     10U 0
  1546.      D  f_fsid                       10U 0
  1547.      D  f_flag                       10U 0
  1548.      D  f_namemax                    10U 0
  1549.      D  f_pathmax                    10U 0
  1550.      D  f_objlinkmax                 10I 0
  1551.      D  f_dirlinkmax                 10I 0
  1552.      D  f_reserved1                   4A
  1553.      D  f_fsid64                     20U 0
  1554.      D  f_basetype                   80A
  1555.  
  1556.  
  1557.       **********************************************************************
  1558.       * Group Information Structure (group)
  1559.       *
  1560.       *  struct group {
  1561.       *        char    *gr_name;        /* Group name.                      */
  1562.       *        gid_t   gr_gid;          /* Group id.                        */
  1563.       *        char    **gr_mem;        /* A null-terminated list of pointers
  1564.       *                                    to the individual member names.  */
  1565.       *  };
  1566.       *
  1567.       **********************************************************************
  1568.      D group           DS                  qualified
  1569.      D                                     BASED(Template)
  1570.      D   gr_name                       *
  1571.      D   gr_gid                      10U 0
  1572.      D   gr_mem                        *   DIM(256)
  1573.  
  1574.  
  1575.       **********************************************************************
  1576.       * User Information Structure (passwd)
  1577.       *
  1578.       * (Don't let the name fool you, this structure does not contain
  1579.       *  any password information.  Its named after the UNIX file that
  1580.       *  contains all of the user info.  That file is "passwd")
  1581.       *
  1582.       *   struct passwd {
  1583.       *        char    *pw_name;            /* User name.                   */
  1584.       *        uid_t   pw_uid;              /* User ID number.              */
  1585.       *        gid_t   pw_gid;              /* Group ID number.             */
  1586.       *        char    *pw_dir;             /* Initial working directory.   */
  1587.       *        char    *pw_shell;           /* Initial user program.        */
  1588.       *   };
  1589.       *
  1590.       **********************************************************************
  1591.      D passwd          DS                  qualified
  1592.      D                                     BASED(Template)
  1593.      D  pw_name                        *
  1594.      D  pw_uid                       10U 0
  1595.      D  pw_gid                       10U 0
  1596.      D  pw_dir                         *
  1597.      D  pw_shell                       *
  1598.  
  1599.  
  1600.       **********************************************************************
  1601.       * File Time Structure (utimbuf)
  1602.       *
  1603.       * struct utimbuf {
  1604.       *    time_t     actime;           /*  access time       */
  1605.       *    time_t     modtime;          /*  modification time */
  1606.       * };
  1607.       *
  1608.       **********************************************************************
  1609.      D utimbuf         DS                  qualified
  1610.      D                              
© 2004-2019 by midrange.com generated in 0.015s valid xhtml & css