AQ :: Enqueue Process

Hi,
We have 2 databases A,B where A needs to be read frequently (like polling) and B should be read as batch. We are implementing AQ, where queues are created for tables in A and B resp.
Now, please tell me which will be the best way to achieve Enqueue operation?
1. Use a trigger and call enqueue package?
2. Use some external agent to call the enqueue package?
Kindly let me know if there is any other best practice by which we can shedule/operate enqueue process.
Regards,
AP

Hi,
Oracle provides you option to perform enqueue/dequeue operation either one message at time or Array of message in one shot and also you have option to apply plsql notification which can further be used to dequeue message automatically. It depends on your app requirement which way to go either shedule job in oracle or write windows service to perform Enqueue/Dequeue operation. If requirement is DB instensive go for Oracle Job. More about packages you can find here.. http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28419/d_aq.htm#i1000850
If you are planning about moving mesage from A-Q to B-Q you can set message propagation by denfining subscriber and propagation schedule..
Thanks

Similar Messages

  • Enqueue process deleted automatically

    Hi Experts,
             Now i am facing a critical issue, In our SAP systems (DEV,QAS,PRD) suddenly the Enqueue process is deleted. It is not displayed in the SM50 t-code and i checked in rz11, All the parameters are showing 0 value.So that users automatically logged out from the sessions.then they tried to login ,they able to login but transaction codes are not performing. The error message it is showing is "table is locked by the same user" .for this entire day was loss.
    then we added Enqueue process ,we have 60 logins in the company ,from this onwards if 60 users login to the system the users getting different kinds of errors.and also i found that almost all dialog work process and update work process is running for long time, if around 30 users login to the system it is performing well. almost two days gone. we are not able to find root cause and solution.
    pls help me, if any doubts pls ask me.
    pls reply me and help me.
    thanks and regards,
    Patan Thavaheer.

    Hi Thavaheer,
    we have 60 logins in the company ,from this onwards if 60 users login to the system the users getting different kinds of errors.and also i found that almost all dialog work process and update work process is running for long time, if around 30 users login to the system it is performing well. almost two days gone
    1) How much RAM do you have configured on the server ?
    2) What is the OS and DB version ?
    Regards,
    Deepak Kori

  • What is Enqueue Work process in SAP ? Enqueue Process in Oracle ?

    Hello Nation,
    I am new to SAP BASIS ,When i was learning the sap basis architecture i came across a doubt that
    What is the work of SAP ENQUEUE ?
    What is ORACLE ENQUEUE?
    Why there is TWO ENQUEUE ?
    What is the difference between SAP ENQUEUE and ORACLE ENQUEUE ?
    Since i am fresher i couldn't differentiate use of both the enqueue process,awaiting
    Thanks in advance ,
    -Mohamed Naveen  

    please read this and in case you still have question.. ask.
    Relationship Between SAP Locks and Database Locks - The SAP Lock Concept (BC-CST-EQ) - SAP Library
    Enqueue Workprocess and database locking
    best regards
    ashish

  • Locking without Enqueue Process

    Hi All,
    Here is a strange scenario ;
    - Standalone EP SP12 installation.
    - Start J2EE
    - Logon to Portal, open an iview(iviewA) to edit it
    - Open "Monitor Locked Objects" within Portal to see the locked iview object
    - Terminate enqueue server process manually on O.S Level.
    - Open another iview object (iviewB) to edit in Portal
    Now,if I try to edit iviewB with another user, I expect to edit it without any restriction although it is in edit mode by another user, because there is no enqueue process to handle the locks. But that does not happen! I'm still getting "Object is Read-Only" message if I try to edit iviewB and I can see the provided lock for iviewB in "Locked Objects List".
    Another thing is, I can also still see the lock for iviewA in lock table even though there is no enqueue process.
    Now, how can this be explained ? There is no lock server, but someone is still providing locks ???
    Regards
    Ahmet Tekin

    It's entirely possible that the PCD which persists iviews uses internal persistent locks on an object level; and if it uses enqueue locks at all then most likely for cluster-wide  synchronized access to critical PCD superstructures only.

  • Increase enqueue process

    Hi,
    i have one enqueue process in my ECC  server. i  want to increase  the process from one to two.
    plz suggest.
    regards,
    krushna ch Nayak

    Dear Milind
    SAP has not recomended to increase more then One enque for one SAP  R/3.
    Enque work process maintain the locking machanizam for entire R/3.
    regards
    Bandla

  • Adding one more enqueue process to ECC 5.0

    hi,
    we are running with ECC 5.0 talking to CRM 4.0 & BW ,many times it has been observed that lakhs of queues(inbound) remain stuck due to non availability of the enqueue process at ECC ,after checking the same at ECC it was for a long in "running" state ideally a enq process should be in running state only for few milli secs
    so its only after its restart we can proceed i know its possible to incraese the enqueue Work process as finally we have only one lock table , but i need to kow the process on how to add this work process & what cautionary thin gs to be taken care while adding an enqueue work process.
    Regards
    SM

    Daer Jaun
    thanks for your prompt reply
    I would like if you could help me on the documents if any for getting an additional enqueue work process & associated configurations,however i do analyse the system on regular basis & since this concern is being faced at a customer's place it was their observance on the enq process being occupied for a longer period.
    Regards
    SM

  • Enqueue process not getting start after failover

    Hi Experts,
    We are facing problem suddenly after doing failover test. This problem arrived today only. Before it was happening successfully.
    Before failover everything is running fine on primary node. After doing failover the enqueue sever process on ASCS instance is not starting in secondary node.
    It's also showing license will expire on 16.11.2010, but system has
    already license installed.
    The ASCS start logs are showing as below -
    Execute Pre-Startup Commands
    (12517410) Local: /usr/sap/PRD/SYS/exe/run/sapcpe pf=/usr/sap/PRD/SYS/profile/PRD_ASCS00_sapprd1 list:/usr/sap/PRD/SYS/exe/run/scs.lst
    (11534542) system(/usr/sap/PRD/SYS/exe/run/sapcpe pf=/usr/sap/PRD/SYS/profile/PRD_ASCS00_sapprd1 list:/usr/sap/PRD/SYS/exe/run/scs.lst) returns 4
    (12517412) Local: /usr/sap/PRD/SYS/exe/run/sapcpe pf=/usr/sap/PRD/SYS/profile/PRD_ASCS00_sapprd1 list:/usr/sap/PRD/SYS/exe/run/sapcrypto.lst
    (11534542) system(/usr/sap/PRD/SYS/exe/run/sapcpe pf=/usr/sap/PRD/SYS/profile/PRD_ASCS00_sapprd1 list:/usr/sap/PRD/SYS/exe/run/sapcrypto.lst) returns 255
    (12517414) Local: rm -f ms.sapPRD_ASCS00
    (12517416) Local: ln -s -f /usr/sap/PRD/ASCS00/exe/msg_server ms.sapPRD_ASCS00
    (12517418) Local: rm -f en.sapPRD_ASCS00
    (12517420) Local: ln -s -f /usr/sap/PRD/ASCS00/exe/enserver en.sapPRD_ASCS00
    Starting Programs
    24.10.2010 18:39:42
    ShmDetach
    OK
    (12517424) Starting: local ms.sapPRD_ASCS00 pf=/usr/sap/PRD/SYS/profile/PRD_ASCS00_sapprd1
    (8585426) Starting: local en.sapPRD_ASCS00 pf=/usr/sap/PRD/SYS/profile/PRD_ASCS00_sapprd1
    (11534542) Waiting for Child Processes to terminate.
    (11534542) **** 2010/10/24 18:39:42 Child 8585426 terminated with Status 1 . ****
    (8585426) **** 2010/10/24 18:39:42 No RestartProgram command for program 1  ****
    It's unable to start enqueue server process.
    Please suggest your solutions.
    Regards,
    Ramesh.

    Hi Gagan,
    The enqueue problem is resolved. Atually 2 days before we increased RAM of primary node by 1GB, and that was creating issue. we revert it back and again did a switchover and everything is running fine. It was strange that my secondary node is getting affected due to increasing the RAM in primary node.
    Regarding license key, can you please provide me detail steps to resolve it. I have gone through installation doc but couldnt find it. Now Tcode slicense is showing another hardware key in my DI system. Do I need to get seperate permenant license key for DI by registering DI host and new hardware key??
    Just confirm and also add some of your expert suggetsions.
    Regards,
    Ramesh.
    Edited by: ramesh_basis on Oct 25, 2010 7:26 AM

  • Strategy and Process on how to best enqueue from the file system

    I have a single database that must accept BFILES from one location via a directory folder, http text documents via proxy server, and unstructured XMLTYPE CLOB from another database.
    I have created an ANYDATA queue, and will try to transform the dequeued output to XMLTYPE payloads for a pl/sql callback.
    My problem is how to monitor both the file system BFILE folder, and the XMLTYPE CLOBS, to automatically begin then enqueue process. The queue would have to accept from (1) to anynumber of files, and given that requirement the use of an array batch is what I would like to use, but need to populate the array.
    Any help would be most appreciated.
    David

    Thank you for the quick reply.
    The database version is 10.2.0.3.
    There are three sources of documents coming into the system.
    Source 1: Outside entity (in-front of a secure firewall) who must place their XML (XSD compliant) files on a shared file system server (the BFILES).
    Source 2: Internal entity (behind firewall) who publishes their XML files to a defined database directory on the database server.
    Source 3: Enterprise Intranet contributors submitting their individual files via url.
    On entry for each file they must be validated for XSD compliance then if passed submitted to the main enqueue for propagation to 5 additional process queues with separate callback procedures.
    If reasonably possible, separate agents of some sort would "listen" at each folder location, then begin the enqueue process when either a batch of files or a single file is placed in the directory folder.
    AQ itself has no such mechanism to monitor locations, and a scheduled job makes sense - however the job would have to continuously run given the very short processing requirement. However, using DBMS_SCHEDULER may be the best solution given ALL rhe requirements.
    Thank you for your professionalism - I appreciate the assistance.

  • Usage of IN UPDATE TASK in Update process

    Hi
    I want to synchronize the Lock and Rollback process with respect to
    addon table and FI document posting.Need to consider that many  addon programs are accessing the table at same time and may be bulk records need to be udpated sometimes.So may be more time to execute. I am trying to execute below in 1LUW process. pls correct me if i am doing wrong here. below is my issue.
    Pls correct me whether can i go with below process.
    1)Check and prepare record for Update
    2)If (No) record exists
      Display Error.
      Else
    3)call Function Enqueue_XXXXX " (Lock the Updating doc record for table.)
    4)Call Function 'UPDATE_ZMMT44' IN UPDATE TASK(Inside FM Update stmt is written)
    FI document standard Commit Work (hope this will release both table lock and BKPF lock)
    FI standard Rollback Work
    Issue
    1)Lock Release timing of Enqueue process?
      Lock Release happens only at the end of FI document Posting. if batch update happens it will lead to long time freeze and no error can be displayed unfortunately. how to handle this?
    2)How to handle SQL error(Update <table> stmt error)
    I am not able to catch this error inside program. seems it goes to ST22 ...how to catch this inside program?
    My earlier query is not clear and i did not get answer so i am post it again
    regards
    prince
    Edited by: princeck on Nov 18, 2011 2:28 AM

    Hello Prince,
    Regarding issue2, this is not solved, How to handle the SQL error when update record?
    Now its going to SAP office and gives error. not showing error at same place.
    This is the standard behavior when an "update"(processed via an Update WP) fails.
    If you don't want this to happen you can opt for local updates(SET UPDATE TASK LOCAL). You would like to read the [behavior of messages in local updates|http://help.sap.com/abapdocu_702/en/abenabap_message_update.htm].
    BR,
    Suhas

  • Server down: disp+work process terminated

    By mistake, SAP server(SMS) was deleted. We used the week old backup to restore
    SMS. Now when we are trying to start the server, disp+work process get
    terminated within 1-2 minute.Tried different option but it is not working
    for us.
    SMS is dual stack server. I have attached some log files of work directory.
    Pls help us to fix this problem.
    Thanks
    trc file: "dev_ms", trc level: 1, release: "701"
    [Thr 5760] Fri Feb 10 13:51:14 2012
    [Thr 5760] MsSSetTrcLog: trc logging active, max size = 31457280 bytes
    systemid   560 (PC with Windows NT)
    relno      7010
    patchlevel 0
    patchno    143
    intno      20020600
    make:      multithreaded, Unicode, optimized
    pid        5756
    [Thr 5760] ***LOG Q01=> MsSInit, MSStart (Msg Server 1 5756) [msxxserv.c   1853]
    [Thr 5760] load acl file = D:\usr\sap\SMS\SYS\global\ms_acl_info.DAT
    [Thr 5760] MsGetOwnIpAddr: my host addresses are :
    [Thr 5760]   1 : [140.18.102.209] xxx.xxx (HOSTNAME)
    [Thr 5760]   2 : [127.0.0.1] xxx.xxx (LOCALHOST)
    [Thr 5760] MsHttpInit: full qualified hostname = xxx.xxx
    [Thr 5760] HTTP logging is switch off
    [Thr 5760] set HTTP state to LISTEN
    [Thr 5760] MsHttpOwnDomain: own domain[1] = xxx.xxx
    [Thr 5760] ms/icf_info_server : deleted
    [Thr 5760] *** I listen to port sapmsSMS (3601) ***
    [Thr 5760] *** I listen to internal port 3901 (3901) ***
    [Thr 5760] *** HTTP port 8101 state LISTEN ***
    [Thr 5760] CUSTOMER KEY: >U1041778160<
    [Thr 5760] build version=701.2009.12.02
    [Thr 5760] Fri Feb 10 13:52:52 2012
    [Thr 5760] *** ERROR => MsSClientHandle: no server provides service ENQ  (4), requested from xxx.xxx
    [msxxserv.c   4731]
    [Thr 5760] Fri Feb 10 14:03:13 2012
    [Thr 5760] *** ERROR => MsSCheckConnections: no response from client C0 (140.18.102.209) after 300 secs received [msxxserv.c   3217]
    [Thr 5760] *** ERROR => MsSCheckConnections: disconnect now [140.18.102.209] [msxxserv.c   3221]
    ****I checked profile and Enqueue process is available in Profile **********
    trc file: "dev_rd", trc level: 1, release: "701"
    Fri Feb 10 13:51:21 2012
    ***LOG S00=> GwInitReader, gateway started ( 6076) [gwxxrd.c     1759]
    systemid   560 (PC with Windows NT)
    relno      7010
    patchlevel 0
    patchno    140
    intno      20020600
    make:      multithreaded, Unicode, optimized
    pid        6076
    gateway runs with dp version 246000(ext=110000) (@(#) DPLIB-INT-VERSION-246000-UC)
    gateway (version=701.2011.04.20)
    gw/reg_no_conn_info = 0
    gw/local_addr : 0.0.0.0
    SWITCH TRC-RESOLUTION from 1 TO 1
    Fri Feb 10 13:51:22 2012
    CCMS: AlInitGlobals : alert/use_sema_lock = TRUE.
    Bind service sapgw01 (socket) to port 3301
    GwIRegInitRegInfo: reg_info file D:\usr\sap\SMS\DVEBMGS01\data\reginfo.DAT not found
    GwPrintMyHostAddr: my host addresses are :
      1 : [140.18.102.209] xxx.xxx (HOSTNAME)
      2 : [127.0.0.1] xxx.xxx (LOCALHOST)
    Full qualified hostname = xxx.xxx
    DpSysAdmExtCreate: ABAP is active
    DpSysAdmExtCreate: VMC (JAVA VM in WP) is not active
    DpShMCreate: sizeof(wp_adm)          23856     (1704)
    DpShMCreate: sizeof(tm_adm)          4415616     (21968)
    DpShMCreate: sizeof(wp_ca_adm)          24064     (80)
    DpShMCreate: sizeof(appc_ca_adm)     8000     (80)
    DpCommTableSize: max/headSize/ftSize/tableSize=500/8/528056/528064
    DpShMCreate: sizeof(comm_adm)          528064     (1048)
    DpSlockTableSize: max/headSize/ftSize/fiSize/tableSize=0/0/0/0/0
    DpShMCreate: sizeof(slock_adm)          0     (96)
    DpFileTableSize: max/headSize/ftSize/tableSize=0/0/0/0
    DpShMCreate: sizeof(file_adm)          0     (72)
    DpShMCreate: sizeof(vmc_adm)          0     (1544)
    DpShMCreate: sizeof(wall_adm)          (38456/34360/64/184)
    DpShMCreate: sizeof(gw_adm)     48
    DpShMCreate: SHM_DP_ADM_KEY          (addr: 07A90040, size: 5081304)
    DpShMCreate: allocated sys_adm at 07A90040
    DpShMCreate: allocated wp_adm at 07A921A8
    DpShMCreate: allocated tm_adm_list at 07A97ED8
    DpShMCreate: allocated tm_adm at 07A97F08
    DpShMCreate: allocated appc_ca_adm at 07ED3D88
    DpShMCreate: allocated comm_adm at 07ED5CC8
    DpShMCreate: system runs without slock table
    DpShMCreate: system runs without file table
    DpShMCreate: allocated vmc_adm_list at 07F56B88
    DpShMCreate: allocated gw_adm at 07F56BC8
    DpShMCreate: system runs without vmc_adm
    DpShMCreate: allocated ca_info at 07F56BF8
    MtxInit: -2 0 0
    DpRqQInit: Parameter rdisp/queue_lock_level = 2
    Fri Feb 10 13:52:16 2012
    ***LOG S30=> GwStopGateway, gateway stopped () [gwxxrd.c     15085]

    Problem is fixed. One of log file indicate problem in shared memory. Shutdown and restarted server to fix this issue...
    Also modified the boot.ini file. Added the following lines:(no idea about the details of  fastdetect /PAE /3GB /userva=3000)
    [boot loader]
    timeout=5
    default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
    [operating systems]
    multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise" /noexecute=optout /fastdetect /PAE /3GB /userva=3000
    multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise" /fastdetect /NoExecute=OptOut /PAE /3GB /userva=3000
    One of these two steps has fixed the error.
    Thanks

  • Oracle AQ dequeue process

    Hi, i found one strange thing in dequeue process.
    I have a trigger (after insert) called trigA that perform enqueue process,and it is attached to a table called Student.
    And i have a stored procedure called notifyDeq that has beed registered to receive PL/SQL notification and perform dequeue process.
    Suppose there is a empty queue called AQQUEUE, when i insert a new record into table Student, the AQQUEUE contains two message payload.
    Then the message propagation happens. After message propagation, there is remaining one message in AQQUEUE.
    Questions:
    1) Why two messages are inserted into queue while i inserted only one record?
    2) After message propagation, the message have not been passed to notifyDeq stored procedure. But why the AQQUEUE statistic still show that one message has been propagated?
    Many many many thanks!!! Pls help!

    Hi, i found one strange thing in dequeue process.
    I have a trigger (after insert) called trigA that perform enqueue process,and it is attached to a table called Student.
    And i have a stored procedure called notifyDeq that has beed registered to receive PL/SQL notification and perform dequeue process.
    Suppose there is a empty queue called AQQUEUE, when i insert a new record into table Student, the AQQUEUE contains two message payload.
    Then the message propagation happens. After message propagation, there is remaining one message in AQQUEUE.
    Questions:
    1) Why two messages are inserted into queue while i inserted only one record?
    2) After message propagation, the message have not been passed to notifyDeq stored procedure. But why the AQQUEUE statistic still show that one message has been propagated?
    Many many many thanks!!! Pls help!

  • Standalone Enqueue Server and HA

    Hi
    We are implementing HA for NW04s AS Java and AS ABAP. As per the latest SAP recommendations, we have decided to decouple Central Service Instance for AS ABAP too (ASCS) and will implement the Standalone Enqueue server and enqueue replication server.
    My question is that:
    Given that the Central Service Instance already has the Enqueue Process decoupled from the Central Instance,
    <b>a) do we still need to install the Standalone Enqueue Server separately?
    OR
    b) is an SCS equivalent to the Standalone Enqueue Server?</b>
    IF the answer is a), does the SCS contain only the Message Service?

    When you de-couple the Central Instance for ABAP, you will get enqueue server and message server for ABAP as part of ASCS. That provides enqueue and message server functionality for ABAP portion of you Add-In system.
    You still need to install SCS for Java portion of your Add-In system.
    Thanks & Regards,
    Venkat

  • Java enqueue service and ABAP Enqueue service

    If  SAP netweaver AS and Java installed in one Server on same database, how many enqueue service will be there?
    ABAP and Java should have separate enqueue process or they will share the same enqueue service, while ABAB and Java has different database schema?
    Your reply will be highly appreciated,

    Hi,
    For your below question:
    If SAP netweaver AS and Java installed in one Server on same database, how many enqueue service will be there?
    Abap instance has its own enqueue server and java has its own in central service. Normally you can clear your concept, if you can see the Java Cluster.
    Just see the below link
    http://help.sap.com/saphelp_nw70/helpdata/en/2e/611724f410254ca12a3f396ec5ae85/content.htm
    Whatever may be the SAP Web Application Server Installation Scenarios ie, both abap and Java in the same database schema or with separate schema's, Java enqueue ( central services ) exists along with peer Abap enqueue work process.
    For more detail go through the ADM200 which speaks about the Java architecture and its corresponding tools..
    Hope i have answered you
    Rgds
    Radhakrishna D S

  • Help regarding dialog work process

    hello experts,
                          In S.A.P abap or abap+java,why we need atleast 2 dialog work process.Is that 2 dialog work process are used for any extra functions?

    Hi,
    it is mandatory to have two dialog work processes within an ABAP-Instance.
    There is no way around.
    It is the same for enqueue process, you have to have exactly one for your ABAP system.
    (Remember: an ABAP system can persist of many instances, but only one central instance).
    Hope, this is helpful.
    Kind regards,
    Achim
    P.S. Never the less, this is the wrong Forum for your question.

  • Filter Coding Issues

    I've been following (roughly) the simple virus scanner interface that SUN provides, and adapted it into a slightly heavier weight filter that interfaces with libclamav. At first both were compiled using GCC, and I thought due to some of the weird problems I had when debugging flags were inserted, maybe Sun Studio would give better results. It hasn't, and I'm at a bit of a loss as to what to do next.
    The symptom is that parts of the message just dissapear, and I see the old mime boundaries within the message body, so it seems like there's some pointer indicating where the message starts that's being corrupted by something in my code.
    Interestingly, if I stop processing the message while still inside the headers, there is no problem, but that's not a very effective virus scanner if it can only look at the content type and filename of the part now is it?
    This happens regardless of whether I use GCC or CC, and I'm using 0.88.1 of clamav. The output message is shown last. It should be fairly obvious what's wrong with it.
    Here's my code, perhaps someone can tell me what I'm doing wrong.
    ** WARNING ** This IS NOT polished code, so please don't expect it to be perfect. It's clean, but includes absolute pathnames, and some other nauties that should be removed before anyone even thinks of reusing this. Once it actually works, I'll do the nessisary code cleanup, and release this to the community to do whatever anyone wants with.
    Makefile
    SERVER_ROOT=/opt/SUNWmsgsr
    INSTALL_LOCATION=/var/opt/SUNWmsgsr/site-programs/
    INCLUDE=-I${SERVER_ROOT}/include
    LIBPATH=-L${SERVER_ROOT}/lib
    CLAMLIBS=`/usr/local/bin/clamav-config --libs` -lclamav
    CLAMFLAGS=`/usr/local/bin/clamav-config --cflags`
    LIBS=-lmtasdk ${CLAMLIBS}
    FLAGS=${CLAMFLAGS}
    all:
            cc ${FLAGS} -o msgsr_clamav msgsr_clamav.c \
                    ${INCLUDE} ${LIBPATH} ${LIBS}
    install:
            cp msgsr_clamav ${INSTALL_LOCATION}
            cp msgsr_clamav.cnf ${INSTALL_LOCATION}************************************************
    Expansions
    CLAMLIBS=-L/usr/local/lib -lz -lbz2 -lpthread -lclamav
    CLAMFLAGS=-I/usr/local/include -xO4************************************************
    msgsr_clamav.c
    * msgsr_clamav
    * Interface the Sun Java System Message Server with LibClamAV
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <pthread.h>
    #include "clamav.h"     // LibClamAV Header
    #include "mtasdk.h"
    * A structure to store channel options
    typedef struct {
         /* Produce debug output? */
         int debug;
         // Maximum size (in bytes) attachment to scan
         int scan_maxsize;
         // Scan recursion level
         int scan_recursion_level;
         // Max files
         int scan_maxfiles;
         // Path to ClamAV Virus Database
         char db_dir[BIGALFA_SIZE+3];
         // Used Internally by ClamAV. Stored here for ease of access
         struct cl_node *root;
         unsigned int signo;
         struct cl_stat dbstat;
         pthread_mutex_t reload_mutex;
         // MIME types to ignore
         char ignore_mime_types[BIGALFA_SIZE+3];
         // Types of files to ignore
         char ignore_file_types[BIGALFA_SIZE+3];
         /* Unwanted MIME content types (ALWAYS stripped, never scanned) */
         char bad_mime_types[BIGALFA_SIZE+3];
         /* Unwanted file types (ALWAYS stripped, never scanned)*/
         char bad_file_types[BIGALFA_SIZE+3];
         /* Length of bmt string */
         size_t bmt_len;
         /* Length of bft string */
         size_t bft_len;
    } our_options_t;
    // A structure passed per message to contain message specific data, including open files, etc.
    typedef struct {
         // The filename of the temp file in use so it can be unlinked when we're done with it.
         char temp_file_name[BIGALFA_SIZE * 2 + 10];
         // The file * to the temp file in use, so we don't have to reopen it across calls to decode_inspect
         FILE *temp_file;
         // A pointer to the single instance of our_options_t that is shared across all threads
         our_options_t * options;
    } msg_temp_data_t;
    * Forward declarations
    static void error_exit(int ires, const char *msg);
    static void error_report(our_options_t *options, int ires, const char *func);
    static void error_reports(our_options_t *options, const char* errStr, const char *func);
    static int is_bad_mime_type(our_options_t *options, mta_decode_t *dctx, char *buf, size_t maxbuflen);
    static int is_bad_file_type(our_options_t *options, mta_opt_t *params, const char *param_name, char *buf, size_t maxbuflen);
    static int load_options(our_options_t *options);
    static mta_dq_process_message_t process_message;
    static mta_decode_read_t decode_read;
    static mta_decode_inspect_t decode_inspect;
    * main() -- Initialize the MTA SDK, load our options, and then
    * start the message processing loop.
    int main()
         int ires,ret;
         char error_msg[BIGALFA_SIZE+3];
         our_options_t options;
         * Initialize the MTA SDK
         * See explanatory comment 1
         if ((ires = mtaInit(0)))
              error_exit(ires, "Unable to initialize the MTA SDK");
         * Load our channel options
         * See explanatory comment 2
         if ((ires = load_options(&options)))
              error_exit(ires, "Unable to load our channel options");
         * Initialize the ClamAV Virus Engine and Database
         // Preconditions to initializing the ClamAV database
         options.root=NULL; options.signo=0;
         // Load the virus database
         mtaLog("cl_loaddbdir() loading database from %s",options.db_dir);
         if ((ret = cl_loaddbdir(options.db_dir, &options.root, &options.signo)))
              sprintf(error_msg,"cl_loaddbdir() error: %s", cl_strerror(ret));
              error_exit(MTA_NO,error_msg);
         mtaLog("cl_loaddbdir() loaded %d virus definitions",options.signo);
         // Internalize the virus database structure
         mtaLog("cl_build() initializing database");
         if((ret = cl_build(options.root)))
              sprintf(error_msg,"cl_build() error: %s", cl_strerror(ret));
              error_exit(MTA_NO,error_msg);
         // Keep track of database updates
         memset(&options.dbstat, 0, sizeof(struct cl_stat));
         cl_statinidir(options.db_dir, &options.dbstat);
         // Initialize our reload mutex
         if (ret = pthread_mutex_init(&options.reload_mutex,NULL))
              sprintf(error_msg,"pthread_mutex_init() error: %d", ret);
              error_exit(MTA_NO,error_msg);
         * Now process the queued messages. Be sure to indicate a
         * thread stack size sufficient to accomodate message
         * enqueue processing.
         * See explanatory comment 3
         if ((ires = mtaDequeueStart((void *)&options,
         process_message, NULL, 0)))
         error_exit(ires, "Error during dequeue processing");
         * All done
         cl_free(options.root);
         mtaDone();
         return(0);
    *Reloads the virus database and re-initializes the in memory structure
    * Loads a new virus database, then if all succeeds, it
    * swaps the new database with the old one.  It's assumed
    * clamav releases the database gracefully, but another mutex
    * may be required if this is not the case.
    static int reload_database(our_options_t *options)
         struct cl_node *newroot = NULL,*oldroot;
         char error_msg[BIGALFA_SIZE+3];
         int ret;
         unsigned int signo=0;
         if (pthread_mutex_trylock(&options->reload_mutex)) {     // Only one reload at a time thank you.
              if(cl_statchkdir(&options->dbstat) == 1) {     // Make sure we actually need an update
                   mtaLog("reload_database() Virus database is stale... reloading");
                   mtaLog("cl_loaddbdir() reloading database from %s",options->db_dir);
                   // Load the new virus database
                   if ((ret = cl_loaddbdir(options->db_dir, &newroot, &signo)))
                        mtaLog("cl_loaddbdir() error: %s", cl_strerror(ret));
                        return (-1);
                   mtaLog("cl_loaddbdir() loaded %d virus definitions",options->signo);
                   // Internalize the virus database structure
                   mtaLog("cl_build() re-initializing database");
                   if((ret = cl_build(newroot)))
                        mtaLog("cl_build() error: %s", cl_strerror(ret));
                        mtaLog("reload_database() Database reload aborted");
                        cl_free(newroot);
                        return (-2);
                   // Save a pointer to the old root
                   oldroot = options->root;
                   // Swap in the new root and signo
                   options->root = newroot;
                   options->signo = signo;
                   // Release the old root
                   cl_free(oldroot);
                   mtaLog("database_reload() Successfully loaded new virus database");
                   // Keep track of database updates
                   cl_statfree(&options->dbstat);
                   cl_statinidir(options->db_dir, &options->dbstat);
              pthread_mutex_unlock(&options->reload_mutex);
    * process_message() -- This routine is called by
    * mtaDequeueStart() to process each queued
    * message. We don&#31258; make use of ctx2, but
    * ctx1 is a pointer to our channel options.
    * See explanatory comment 4
    static int process_message(void **ctx2, void *ctx1, mta_dq_t *dq, const char *env_from, size_t env_from_len)
         const char *adr;
         int disp, ires;
         size_t len;
         mta_nq_t *nq;
         msg_temp_data_t msg_data;
         * Initializations
         nq = NULL;
         msg_data.options = (our_options_t *)ctx1;
         msg_data.temp_file = NULL;
         * Check the virus database to make sure it isn't stale
         * If it it's not currently reloading, and is stale, reload it.
         //if(cl_statchkdir(&(msg_data.options->dbstat)) == 1)
         //     reload_database(msg_data.options);
         * A little macro to do error checking on mta*() calls
         #define CHECK(f,x) \
         if ((ires = x)) { error_report(msg_data.options, ires, f); goto \
              done_bad; }
         * Start a message enqueue. Use the dequeue context to copy
         * envelope flags fromt the current message to this new
         * message being enqueued.
         * See explanatory comment 5
         CHECK("mtaEnqueueStart", mtaEnqueueStart(&nq, env_from, env_from_len, MTA_DQ_CONTEXT, dq, 0));
         * Process the envelope recipient list
         * See explanatory comment 6
         while (!(ires = mtaDequeueRecipientNext(dq, &adr, &len, 0)))
              * Add this envelope recipient address to the message
              * being enqueued. Use the dequeue context to copy
              * envelope flags for this recipient from the current
              * message to the new message.
              ires = mtaEnqueueTo(nq, adr, len, MTA_DQ_CONTEXT,
              dq, MTA_ENV_TO, 0);
              /* See explanatory comment 7 */
              disp = (ires) ? MTA_DISP_DEFERRED : MTA_DISP_RELAYED;
              CHECK("mtaDequeueRecipientDisposition", mtaDequeueRecipientDisposition(dq, adr, len,disp, 0));
         * A normal exit from the loop occurs when
         * mtaDequeueRecipientNext() returns an MTA_EOF status.
         * Any other status signifies an error.
         if (ires != MTA_EOF)
              error_report(msg_data.options, ires, "mtaDequeueRecipientNext");
              goto done_bad;
         * Begin the MIME decode of the message
         * See explanatory comment 8
         CHECK("mtaDecodeMessage",
              mtaDecodeMessage(
              /* Private context is our message data structure */
              (void *)&msg_data,
              /* Input is the message being dequeued */
              MTA_DECODE_DQ, (void *)dq,
              /* Output is the message being enqueued */
              MTA_DECODE_NQ, (void *)nq,
              /* Inspection routine */
              decode_inspect,
              /* Convert non-MIME formats to MIME */
              MTA_DECODE_THURMAN,
              0));
         * Finish the enqueue
         * NOTE: IT&#25285; IMPORTANT TO DO THIS before DOING THE
         * DEQUEUE. YOU WILL LOSE MAIL IF YOU DO THE DEQUEUE FIRST
         * and then THE ENQUEUE FAILS.
         * See explanatory text 9
         CHECK("mtaEnqueueFinish", mtaEnqueueFinish(nq, 0));
         nq = NULL;
         * Finish the dequeue
         CHECK("mtaDequeueFinish", mtaDequeueMessageFinish(dq, 0));
         * All done with this message
         return(MTA_OK);
    done_bad:
         * Abort any ongoing enqueue or dequeue
         if (nq)
              mtaEnqueueFinish(nq, MTA_ABORT, 0);
         if (dq)
              mtaDequeueMessageFinish(dq, MTA_ABORT, 0);
         * And return our error status
         return(ires);
    #undef CHECK
    * decode_inspect() -- This is the routine that inspects each
    * message part, deciding whether to accept
    * or reject it.
    * See explanatory comment 10
    static int decode_inspect(void *ctx, mta_decode_t *dctx, int data_type,const char *data, size_t data_len)
         char buf[BIGALFA_SIZE * 2 + 10];
         const char *virname;
         int i;
         static unsigned int part_c = 1;
         msg_temp_data_t *msg_data = (msg_temp_data_t *)ctx;
         strncpy(buf,data,data_len);
         buf[data_len] = 0;
         mtaLog("decode_inspect() (%d,%ud): %s",data_type,dctx,buf);
         switch (data_type)
              case MTA_DATA_HEADER:
              * See if the part has:
              * 1. A bad MIME content-type,
              * 2. A bad file name extension in the (deprecated)
              * NAME= content-type parameter, or
              * 3. A bad file name extension in the
              * FILENAME= content-disposition parameter.
              i = 0;
              if ((i = is_bad_mime_type((void *)msg_data->options, dctx, buf, sizeof(buf))) ||
                   is_bad_file_type((void *)msg_data->options,mtaDecodeMessageInfoParams(dctx,MTA_DECODE_CTYPE_PARAMS, NULL),"NAME", buf, sizeof(buf)) ||
                   is_bad_file_type((void *)msg_data->options,mtaDecodeMessageInfoParams(dctx,MTA_DECODE_CDISP_PARAMS, NULL),"FILENAME", buf, sizeof(buf)))
                   char msg[BIGALFA_SIZE*4 + 10];
                   * Replace this part with a text message indicating
                   * that the part&#30196; content has been deleted.
                   * See explanatory comment 11
                   if (i)
                        i = sprintf(msg,
                             "The content of this message part has been removed.\n"
                             "It contained a potentially harmful media type of %.*s",
                             strlen(buf)-2, buf+1);
                   else
                        i = sprintf(msg,
                             "The content of this message part has been removed.\n"
                             "It contained a potentially harmful file named '%s'", buf);
                   mtaLog("decode_inspect(): %s",msg);
                   return(mtaDecodeMessagePartDelete(dctx,
                        MTA_REASON, msg, i,
                        MTA_DECODE_CTYPE, "text", 4,
                        MTA_DECODE_CSUBTYPE, "plain", 5,
                        MTA_DECODE_CCHARSET, "us-ascii", 8,
                        MTA_DECODE_CDISP, "inline", 6,
                        MTA_DECODE_CLANG, "en", 2, 0));
              } break; // case MTA_DATA_HEADER:
              case MTA_DATA_TEXT:
              case MTA_DATA_BINARY:
                   if (msg_data->temp_file == NULL)
                        sprintf(msg_data->temp_file_name,"/tmp/%i.tmp",part_c++);
                        mtaLog("messageDecode(): Opening Temp File %s",msg_data->temp_file_name);
                        msg_data->temp_file = fopen(msg_data->temp_file_name,"wb");
                   fwrite(data,data_len,1,msg_data->temp_file);
                   return(MTA_OK);
                   break;
              case MTA_DATA_NONE:
                   fflush(msg_data->temp_file);
                   fclose(msg_data->temp_file);
                   msg_data->temp_file = NULL;
                   struct cl_limits limits;
                   memset(&limits, 0, sizeof(struct cl_limits));
                   /* maximal number of files in archive */;
                   limits.maxfiles = 1000;
                   /* maximal archived file size */
                   limits.maxfilesize = 10 * 1048576; /* 10 MB */
                   /* maximal recursion level */
                   limits.maxreclevel = 5;
                   /* maximal compression ratio */
                   limits.maxratio = 200;
                   /* disable memory limit for bzip2 scanner */
                   limits.archivememlim = 0;
                   i = cl_scanfile(msg_data->temp_file_name, &virname, NULL, msg_data->options->root,&limits,CL_SCAN_STDOPT);
                   unlink (msg_data->temp_file_name);
                   if(i == CL_VIRUS) {
                        char msg[BIGALFA_SIZE*4 + 10];
                        size_t idlen;
                        i = sprintf(msg,
                             "The content of this message part has been removed.\n"
                             "It contained the virus %s in a file named '%s'", virname,buf);
                        mtaDequeueInfo(dctx,MTA_ENV_ID,&buf,&idlen);
                        buf[idlen] = '\0';
                        mtaLog("decode_inspect(): Detected %s virus in part %i of msg ID %s",virname,0,buf);
                        return(mtaDecodeMessagePartDelete(dctx,
                             MTA_REASON, msg, i,
                             MTA_DECODE_CTYPE, "text", 4,
                             MTA_DECODE_CSUBTYPE, "plain", 5,
                             MTA_DECODE_CCHARSET, "us-ascii", 8,
                             MTA_DECODE_CDISP, "inline", 6,
                             MTA_DECODE_CLANG, "en", 2, 0));
                   } else {
                        if(i != CL_CLEAN)
                             mtaLog("decode_inspect() Error: %s scanning file %s",cl_strerror(i),msg_data->temp_file_name);
                        else
                             mtaLog("decode_inspect(): Part in file %s is clean",msg_data->temp_file_name);
                        //return(mtaDecodeMessagePartCopy(dctx, 0));
                        return(MTA_OK); break;
         return(MTA_OK);
    * is_bad_mime_type() -- See if the part&#30196; media type is in our
    * bad MIME content types, for example:
    * application/vbscript
    * See explanatory comment 13
    static int is_bad_mime_type(our_options_t *options,
    mta_decode_t *dctx, char *buf,
    size_t maxbuflen)
         const char *csubtype, *ctype;
         size_t i, len1, len2;
         char *ptr;
         * Sanity checks
         if (!options || !options->bmt_len ||
              !options->bad_mime_types[0] ||
              !dctx)
              return(0);
         * Get the MIME content type
         ctype = mtaDecodeMessageInfoString(dctx, MTA_DECODE_CTYPE,NULL, &len1);
         csubtype = mtaDecodeMessageInfoString(dctx,MTA_DECODE_CSUBTYPE,NULL, &len2);
         * Build the string: <0x01>type/subtype<0x01><0x00>
         ptr = buf;
         *ptr++ = (char)0x01;
         for (i = 0; i < len1; i++)
              *ptr++ = tolower(*ctype++);
         *ptr++ = '/';
         for (i = 0; i < len2; i++)
              *ptr++ = tolower(*csubtype++);
         *ptr++ = (char)0x01;
         *ptr = '\0';
         * Now see if the literal just built occurs in the list of
         * bad MIME content types
         return((strstr(options->bad_mime_types, buf)) ? -1 : 0);
    * is_bad_file_type() -- See if the part has an associated file
    * name whose file extension is in our list
    * of bad file names, such as .vbs.
    * See explanatory comment 14
    static int is_bad_file_type(our_options_t *options,
    mta_opt_t *params,
    const char *param_name, char *buf,
    size_t maxbuflen)
         const char *ptr1;
         char fext[BIGALFA_SIZE+2], *ptr2;
         size_t i, len;
         * Sanity checks
         if (!options || !options->bft_len || !params || !param_name)
              return(0);
         len = 0;
         buf[0] = '\0';
         if (mtaOptionString(params, param_name, 0, buf, &len,
              maxbuflen - 1) ||
              !len || !buf[0])
              * No file name parameter specified
              return(0);
         * A file name parameter was specified. Parse it to
         * extract the file extension portion, if any.
         ptr1 = strrchr(buf, '.');
         if (!ptr1)
              * No file extension specified
              return(0);
         * Now store the string created earlier in fext[]
         * Note that we drop the &#12539;&#12539;from the extension.
         ptr1++; /* Skip over the &#12539;&#12539;*/
         ptr2 = fext;
         *ptr2++ = (char)0x01;
         len = len - (ptr1 - buf);
         for (i = 0; i < len; i++)
              *ptr2++ = tolower(*ptr1++);
         *ptr2++ = (char)0x01;
         *ptr2++ = '\0';
         * Now return -1 if the string occurs in
         * options->bad_file_types.
         return((strstr(options->bad_file_types, fext)) ? -1 : 0);
    * load_options() -- Load our channel options from the channel&#30196;
    * option file
    * See explanatory comment 15
    static int load_options(our_options_t *options)
         char buf[BIGALFA_SIZE+1];
         size_t buflen, i;
         mta_opt_t *channel_opts;
         int ires;
         const char *ptr0;
         char *ptr1;
         * Initialize the our private channel option structure
         memset(options, 0, sizeof(our_options_t));
         * Set internal defaults for important features
         options->scan_maxsize = 10 * 1024 * 1024; // 10 MB
         options->scan_recursion_level = 10;
         options->scan_maxfiles = 200;
         strcpy(options->db_dir,cl_retdbdir()); // Default ClamAV Directory
         * Access the channel&#30196; option file
         * See explanatory comment 16
         channel_opts = NULL;
         if ((ires = mtaOptionStart(&channel_opts, "/var/opt/SUNWmsgsr/site-programs/msgsr_clamav.cnf", 0, 0)))
              mtaLog("Unable to access our channel option file");
              return(ires);
         * DEBUG=0|1
         options->debug = 0;
         mtaOptionInt(channel_opts, "DEBUG", 0, &options->debug);
         if (options->debug)
              mtaDebug(MTA_DEBUG_SDK, 0);
         * BAD_MIME_TYPES=type1/subtype1[,type2/subtype2[,...]]
         buf[0] = '\0';
         mtaOptionString(channel_opts, "BAD_MIME_TYPES", 0, buf,
         &buflen, sizeof(buf));
         * Now translate the comma separated list:
         * Type1/Subtype1[,Type2/Subtype2[,...]]
         * to
         *<0x01>type1/subtype1[<0x01>type2/subtype2[<0x01>...]]<0x01>
         ptr0 = buf;
         ptr1 = options->bad_mime_types;
         *ptr1++ = (char)0x01;
         for (i = 0; i < buflen; i++)
              if (*ptr0 != ',')
                   *ptr1++ = tolower(*ptr0++);
              else
                   *ptr1++ = (char)0x01;
                   ptr0++;
         *ptr1++ = (char)0x01;
         *ptr1 = '\0';
         options->bmt_len = ptr1 - options->bad_mime_types;
         * BAD_FILE_TYPES=["."]Ext1[,["."]Ext2[,...]]
         buf[0] = '\0';
         buflen = 0;
         mtaOptionString(channel_opts, "BAD_FILE_TYPES", 0, buf,
         &buflen, sizeof(buf));
         * Now translate the comma separated list:
         * ["."]Ext1[,["."]Ext2[,...]]
         * to
         * <0x01>ext1[<0x01>ext2[<0x01>...]]<0x01>
         ptr0 = buf;
         ptr1 = options->bad_file_types;
         *ptr1++ = (char)0x01;
         for (i = 0; i < buflen; i++)
              switch(*ptr0)
                   default : /* copy after translating to lower case */
                        *ptr1++ = tolower(*ptr0++);
                        break;
                   case '.' : /* discard */
                        break;
                   case ',' : /* end current type */
                        *ptr1++ = (char)0x01;
                        ptr0++;
                   break;
         *ptr1++ = (char)0x01;
         *ptr1 = '\0';
         options->bft_len = ptr1 - options->bad_file_types;
         * Dispose of the mta_opt_t context
         * See explanatory comment 17
         mtaOptionFinish(channel_opts);
         * And return a success
         return(MTA_OK);
    * error_report() &#12539;Report an error condition when debugging is
    * enabled.
    static void error_report(our_options_t *options, int ires,
    const char *func)
         if (options->debug)
              mtaLog("%s() returned %d; %s",
                   (func ? func : "?"), ires, mtaStrError(ires,0));
    static void error_reports(our_options_t *options, const char* errStr,
    const char *func)
         if (options->debug)
              mtaLog("%s() reported: %s",
                   (func ? func : "?"), errStr);
    * error_exit() -- Exit with an error status and error message.
    static void error_exit(int ires, const char *msg)
         mtaLog("%s%s%s", (msg ? msg : ""), (msg ? "; " : ""),
         mtaStrError(ires,0));
         exit(1);
    msgsr_clamav.cnf
    DEBUG=1
    BAD_MIME_TYPES=application/vbscript
    BAD_FILE_TYPES=bat,pif,vb,vbs,chs,exe************************************************
    broken message
    Return-path: <[email protected]>
    Received: from virusscan-daemon.apple.california.com by apple.california.com
    (Sun Java System Messaging Server 6.2-3.04 (built Jul 15 2005))
    id <[email protected]> for [email protected]; Thu,
    20 Apr 2006 07:30:13 -0700 (PDT)
    Received: from california.com ([209.159.129.16])
    by apple.california.com (Sun Java System Messaging Server 6.2-3.04 (built Jul
    15 2005)) with ESMTP id <[email protected]> for
    [email protected]; Thu, 20 Apr 2006 07:30:05 -0700 (PDT)
    Received: from [61.23.221.222] by apple.california.com (mshttpd); Thu,
    20 Apr 2006 14:30:05 +0000 (GMT)
    Content-return: allowed
    Date: Thu, 20 Apr 2006 14:30:05 +0000 (GMT)
    From: [email protected]
    Subject: Re: testing
    In-reply-to: <[email protected]>
    To: [email protected]
    Message-id: <[email protected]>
    MIME-version: 1.0
    X-Mailer: Sun Java(tm) System Messenger Express 6.2-3.04 (built Jul 15 2005)
    Content-type: multipart/alternative;
    boundary="Boundary_(ID_iOVR4MBjhWJn/mh7Ij+BUQ)"
    Content-language: en
    X-Accept-Language: en
    Priority: normal
    References: <[email protected]>
    Original-recipient: rfc822;[email protected]
    This is a multi-part message in MIME format.
    --Boundary_(ID_iOVR4MBjhWJn/mh7Ij+BUQ)
    Content-type: text/plain; charset=us-ascii
    Content-transfer-encoding: 7bit
    Content-disposition: inline
    Data is missing from here
    ----ec04832708e231d6e2f
    --Boundary_(ID_iOVR4MBjhWJn/mh7Ij+BUQ)
    Content-type: text/html; charset=us-ascii
    Content-transfer-encoding: quoted-printable
    Content-disposition: inline
    Data is missing from here
    nal Message -----=3Cbr=3EFrom=3A chales=40california=2Ecom=3Cbr=3EDate=3A=
    Thursday=2C April 20=2C 2006 11=3A19 pm=3Cbr=3ESubject=3A testing=3Cbr=3E=
    To=3A chales=40california=2Ecom=3Cbr=3E=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B 1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B=
    3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B 5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B=
    7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B 9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B=
    1=3Cbr=3E=26gt=3B 2=3Cbr=3E=26gt=3B 3=3Cbr=3E=26gt=3B 4=3Cbr=3E=26gt=3B=
    5=3Cbr=3E=26gt=3B 6=3Cbr=3E=26gt=3B 7=3Cbr=3E=26gt=3B 8=3Cbr=3E=26gt=3B=
    9=3Cbr=3E=26gt=3B 0=3Cbr=3E=26gt=3B =3Cbr=3E=26gt=3B
    ----ec04832708e231d6e2f
    --Boundary_(ID_iOVR4MBjhWJn/mh7Ij+BUQ)
    Content-type: text/x-vcard; name=chales.vcf; charset=us-ascii
    Content-transfer-encoding: base64
    Content-disposition: attachment; filename=chales.vcf
    Content-description: Card for <[email protected]>
    bA0KdGVsO3dvcms6NTEwLTI4Ny04NDUwDQp1cmw6aHR0cDovL3d3dy5jYWxpZm9ybmlh
    LmNvbS8NCm9yZzpDYWxpZm9ybmlhQ29tLCBJbmM7DQp2ZXJzaW9uOjIuMQ0KZW1haWw7
    aW50ZXJuZXQ6Y2hhbGVzQGNhbGlmb3JuaWEuY29tDQp0aXRsZTpTeXN0ZW0gQWRtaW5p
    c3RyYXRvcg0KZW5kOnZjYXJkDQo=
    ----ec04832708e231d6e2f--
    Boundary_(ID_iOVR4MBjhWJn/mh7Ij+BUQ)

    Ok, so it's not my code. Using the virus_scanner_simple.c example from SUN, if you change the decode_inspect routine to return MTA_OK for every call (which should technically just let the message pass) it has the same behavior as my program. (Not all that suprising since mine is a derivative of said program)
    That said, this now looks like a library issue. I'm using Sun Java System Messaging Server 6.2-3.04 (built Jul 15 2005) according to the SMTP prompt, and was wondering if perhaps I should apply:
    http://sunsolve.sun.com/search/document.do?assetkey=1-21-118207-42-1&searchclause=6306404
    The issue seems to be in the mtaDecodeMessage function, and occurs when the decode_inspect function is allowed to parse the message body, not just the message headers.
    The machine is a Sun Ultra 4500 running Solaris 10. Here's the banner:
    SunOS cookie 5.10 Generic_118822-23 sun4u sparc SUNW,Ultra-Enterprise
    Has anyone else had similar problems using the MTA SDK? Is there anything I'm missing here (besides the above mentioned patch) that might fix this?

Maybe you are looking for