Remove reallyoldsun defines
[oweals/cde.git] / cde / programs / dtmail / libDtMail / Common / DtMailServer.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *      $TOG: DtMailServer.C /main/23 1999/01/29 14:46:18 mgreess $
27  *
28  *      RESTRICTED CONFIDENTIAL INFORMATION:
29  *      
30  *      The information in this document is subject to special
31  *      restrictions in a confidential disclosure agreement between
32  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
33  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
34  *      Sun's specific written approval.  This document and all copies
35  *      and derivative works thereof must be returned or destroyed at
36  *      Sun's request.
37  *
38  *      Copyright 1993, 1995, 1995 Sun Microsystems, Inc.  All rights reserved.
39  *
40  *+ENOTICE
41  */
42
43 #include <ctype.h>
44 #include <errno.h>
45 #include <pwd.h>
46 #include <setjmp.h>
47 #include <signal.h>
48 #include <stdio.h>
49 #include <stdarg.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <sys/types.h>
53 #include <sys/time.h>
54 #include <time.h>
55 #include <unistd.h>
56
57 #include <DtMail/DtMailError.hh>
58 #include <DtMail/DtMailServer.hh>
59 #include <DtMail/IO.hh>
60
61 #if defined(USE_ITIMER_REAL)
62 #define SIGNAL_TYPE     SIGALRM
63 #define ITIMER_TYPE     ITIMER_REAL
64 #else
65 #define SIGNAL_TYPE     SIGVTALRM
66 #define ITIMER_TYPE     ITIMER_VIRTUAL
67 #endif
68
69 #define dtmasTAGCLR()   *_transtag = '\0'; _transnum=0;
70 #define dtmasTAGGEN()   (sprintf(_transtag, "a%04d", ++_transnum), _transtag)
71 #define dtmasTAGGET()   (_transtag)
72
73 static jmp_buf  restart;
74
75 DtMailServer::DtMailServer(
76                 char                    *folder,
77                 DtMail::Session         *session,
78                 DtMail::MailBox         *mailbox,
79                 DtMailAppendCallback    append_mailbox_cb,
80                 void                    *append_mailbox_cb_data)
81 {
82     struct passwd       pw;
83
84     GetPasswordEntry(pw);
85
86     if (folder)
87       _folder           = strdup(folder);
88     else
89       _folder           = "INBOX";
90     _session            = session;
91     _mailbox            = mailbox;
92
93     _append_mailbox_cb  = append_mailbox_cb;
94     _append_mailbox_cb_data
95                         = append_mailbox_cb_data;
96     _protologging       = get_mailrc_value(
97                                         _session, _folder,
98                                         DTMAS_PROPKEY_PROTOLOGGING,
99                                         (Boolean) False);
100     _protologgingplus   = get_mailrc_value(
101                                         _session, _folder,
102                                         DTMAS_PROPKEY_PROTOLOGGINGPLUS,
103                                         (Boolean) False);
104     _errorstring        = NULL;
105     _password           = get_mailrc_value(
106                                         _session, _folder,
107                                         DTMAS_PROPKEY_PASSWORD,
108                                         NULL, DTM_TRUE);
109     _removeafterdelivery
110                         = get_mailrc_value(
111                                         _session, _folder,
112                                         DTMAS_PROPKEY_REMOVEAFTERDELIVERY,
113                                         True);
114     _retrieveold        = get_mailrc_value(
115                                         _session, _folder,
116                                         DTMAS_PROPKEY_RETRIEVEOLD,
117                                         True);
118     _retrieveerrors     = 0;
119     _servername         = get_mailrc_value(
120                                         _session, _folder,
121                                         DTMAS_PROPKEY_SERVERNAME,
122                                         DTMAS_PROPDFLT_SERVERNAME);
123     _shroud             = NULL;
124     _sizelimit          = 0;
125     _sockfp             = NULL;
126     dtmasTAGCLR();
127     _transnum           = 0;
128     _timeout            = get_mailrc_value(
129                                         _session, _folder,
130                                         DTMAS_PROPKEY_TIMEOUT,
131                                         DTMAS_TIMEOUT);
132     _username           = get_mailrc_value(
133                                         _session, _folder,
134                                         DTMAS_PROPKEY_USERNAME,
135                                         pw.pw_name);
136 }
137
138 DtMailServer::~DtMailServer()
139 {
140     if (_errorstring) free(_errorstring);
141     if (_folder) free(_folder);
142     if (_password) free(_password);
143     if (_servername) free(_servername);
144     if (_shroud) free(_shroud);
145     if (_username) free(_username);
146 }
147
148 void
149 DtMailServer::set_password(char *password)
150 {
151     if (NULL == password) return;
152
153     if (NULL != _password) free(_password);
154     _password = NULL;
155     if (NULL != password) _password = strdup(password);
156 }
157
158 //
159 // Read message content and append to mailbox
160 //
161 //      len     - Length of message.
162 //
163 #define SA_HANDLER_TYPE void (*)(int)
164
165 DTMailError_t
166 DtMailServer::ptrans_retrieve_readandappend(
167                                 DtMailEnv       &error,
168                                 long            len)
169 {
170     static char *pname = "DtMailServer::ptrans_retrieve_readandappend";
171     static char *from = "From ";
172     struct sigaction action, o_action;
173     int from_done = FALSE;
174     int done = FALSE;
175     size_t nread = 0;
176     char *s, *t;
177
178     memset((char*) &action, 0, sizeof(struct sigaction));
179     memset((char*) &o_action, 0, sizeof(struct sigaction));
180     action.sa_handler = (SA_HANDLER_TYPE) SIG_IGN;
181     sigaction(SIGINT, (const struct sigaction *) &action, &o_action);
182
183     while (! done)
184     {
185         size_t  nbytes;
186
187         if (nread < len)
188         {
189             if (DTMAS_MSGBUFSIZE - 1 > len - nread)
190               nbytes = (size_t) len - nread;
191             else
192               nbytes = DTMAS_MSGBUFSIZE - 1;
193
194             if (0 == (nbytes=SockRead(_msgbuf, 1, nbytes, _sockfp)))
195             {
196                 _logger.logError(
197                         DTM_FALSE,
198                         "Failed to retrieve %d bytes.",
199                         len);
200                 return DTME_MailServerAccess_SocketIOError;
201             }
202             _msgbuf[nbytes] = '\0';
203         }
204         else
205         {
206             if (NULL == SockGets(_msgbuf, DTMAS_MSGBUFSIZE, _sockfp))
207             {
208                 _logger.logError(DTM_FALSE, "Failed to retrieve %d bytes", len);
209                 return DTME_MailServerAccess_SocketIOError;
210             }
211             nbytes = strlen(_msgbuf);
212         }
213
214         nread += nbytes;
215
216         // Delete all carriage returns
217         for (s = t = _msgbuf; *s; s++)
218           if (*s != '\r') *t++ = *s;
219         *t = '\0';
220
221         if (_protologgingplus)
222           _logger.logError(
223                         DTM_FALSE,
224                         "INFO: read %d of %d octets %d remaining\n%s< %s\n",
225                         nbytes, len, len-nread, proto_name(), _msgbuf);
226
227         // Determine if we are done with this message.
228         if (proto_is_delimited())
229         {
230           char *s = const_cast<char *> (strrchr((const char *) _msgbuf, (int) '.'));
231             
232             if (s &&
233                 (s == _msgbuf || *(s-1) == '\n') &&
234                 (*s == '.') &&
235                 (*(s+1) == '\n'))
236             {
237                 *s = '\0';
238                 done = TRUE;
239             }
240         }
241         else if (nread >= len)
242           done = TRUE;
243     
244         if (0 < (nbytes = strlen(_msgbuf)))
245         {
246             if (! from_done && strncmp(_msgbuf, from, strlen(from)))
247             {
248                 time_t clock;
249                 char buffer[BUFSIZ];
250
251                 clock = time(&clock);
252                 sprintf(buffer, "%s %s %s",
253                         from, _servername, ctime((const time_t *) &clock));
254                 _append_mailbox_cb(
255                                 error, buffer, strlen(buffer),
256                                 _append_mailbox_cb_data);
257             }
258
259             from_done = TRUE;
260             _append_mailbox_cb(error, _msgbuf, nbytes, _append_mailbox_cb_data);
261         }
262
263         if (error.isSet())
264         {
265             error.logError(
266                         DTM_TRUE,
267                         "%s: Failed to append mailbox %s: %s.\n",
268                         pname, _folder, error.errnoMessage());
269             return DTME_AppendMailboxFile_Error;
270         }
271     }
272   
273     // Message separation.
274     _append_mailbox_cb(error, "\n", 1, _append_mailbox_cb_data);
275
276     // Sink the file pointer.
277     sigaction(SIGINT, (const struct sigaction *) &o_action, NULL);
278     return DTME_NoError;
279 }
280
281 //
282 // Assemble command in printf(3) style and send to the server.
283 //
284
285 DTMailError_t
286 DtMailServer::do_send(char *fmt, ... )
287 {
288     static char *pname = "DtMailServer::do_send";
289     char        *buf = new char[DTMAS_POPBUFSIZE+1];
290     int         nbytes;
291     va_list     ap;
292     DtMailEnv   error;
293
294     if (proto_is_tagged())
295     {
296         dtmasTAGGEN();
297         (void) sprintf(buf, "%s ", dtmasTAGGET());
298     }
299     else
300     {
301         dtmasTAGCLR();
302         buf[0] = '\0';
303     }
304
305     va_start(ap, fmt);
306     vsprintf(buf + strlen(buf), fmt, ap);
307     va_end(ap);
308
309     strcat(buf, "\r\n");
310     nbytes = SockWrite(buf, 1, strlen(buf), _sockfp);
311     if (nbytes != strlen(buf))
312     {
313         _logger.logError(DTM_FALSE, "Socket Error:  writing '%s'", buf);
314         delete [] buf;
315         return DTME_MailServerAccess_SocketIOError;
316     }
317
318     if (_protologging)
319     {
320         char *cp;
321         if (_shroud && (cp = strstr(buf, _shroud)))
322           memset(cp, '*', strlen(_shroud));
323         buf[strlen(buf)-1] = '\0';
324
325         _logger.logError(DTM_FALSE, "%s> %s", proto_name(), buf);
326     }
327     delete [] buf;
328     return DTME_NoError;
329 }
330
331 //
332 // Assemble command in printf(3) style, send to server, accept a response.
333 //
334 #if defined(__hpux)
335 #define DTMAS_COMMAND_TERMINATOR        "\n"
336 #else
337 #define DTMAS_COMMAND_TERMINATOR        "\r\n"
338 #endif
339 DTMailError_t
340 DtMailServer::do_transaction(char *fmt, ... )
341 {
342     static char         *pname = "DtMailServer::do_transaction";
343     DTMailError_t       ok;
344     char                *buf = new char[DTMAS_POPBUFSIZE+1];
345     int                 nbytes;
346     va_list             ap;
347
348     if (proto_is_tagged())
349     {
350         dtmasTAGGEN();
351         (void) sprintf(buf, "%s ", dtmasTAGGET());
352     }
353     else
354     {
355         dtmasTAGCLR();
356         buf[0] = '\0';
357     }
358
359     va_start(ap, fmt);
360     vsprintf(buf + strlen(buf), fmt, ap);
361     va_end(ap);
362
363     strcat(buf, DTMAS_COMMAND_TERMINATOR);
364     nbytes = SockWrite(buf, 1, strlen(buf), _sockfp);
365     if (nbytes != strlen(buf))
366     {
367         _logger.logError(DTM_FALSE, "Socket Error:  writing '%s'", buf);
368         delete [] buf;
369         return DTME_MailServerAccess_SocketIOError;
370     }
371
372     if (_protologging)
373     {
374         char *cp;
375         if (_shroud && (cp = strstr(buf, _shroud)))
376           memset(cp, '*', strlen(_shroud));
377         buf[strlen(buf)-1] = '\0';
378
379         _logger.logError(DTM_FALSE, "%s> %s", proto_name(), buf);
380     }
381
382     /* we presume this does its own response echoing */
383     ok = ptrans_parse_response(buf);
384     if (ok != DTME_NoError)
385     {
386       if (NULL == _errorstring)
387         _errorstring = strdup(buf);
388     }
389     delete [] buf;
390     return ok;
391 }
392
393 //
394 // Get the specified mailrc value interpreted as an integer
395 //
396 int
397 DtMailServer::get_mailrc_value(
398                         DtMail::Session *ssn,
399                         char *pfx,
400                         char *id,
401                         int dflt)
402 {
403     char        *string = NULL;
404     int         value = 0;
405
406     string = get_mailrc_value(ssn, pfx, id, (char*) NULL);
407     if (NULL == string)
408       return dflt;
409
410     value = atoi(string);
411     return value;
412 }
413
414 //
415 // Get the specified mailrc value interpreted as an string
416 //
417 char *
418 DtMailServer::get_mailrc_value(
419                         DtMail::Session *ssn,
420                         char *pfx,
421                         char *id,
422                         char *dflt,
423                         DtMailBoolean decrypt)
424 {
425     DtMailEnv           error;
426     DtMail::MailRc      *mailrc = ssn->mailRc(error);
427     const char          *value = NULL;
428     static char         idbuf[DTMAS_IDSIZE+1];
429     char                *charval = NULL;
430
431     DTMAS_CONCAT_MAILRC_KEY(idbuf, pfx, id);
432     mailrc->getValue(error, idbuf, &value, decrypt);
433     if (error.isSet())
434     {
435         if (NULL != dflt)
436           charval = strdup(dflt);
437     }
438     else
439       charval = strdup(value);
440
441     if (NULL != value) free((void*) value);
442     return charval;
443 }
444
445 //
446 // Get the specified mailrc value interpreted as an string
447 //
448 Boolean
449 DtMailServer::get_mailrc_value(
450                         DtMail::Session *ssn,
451                         char *pfx,
452                         char *id,
453                         Boolean dflt)
454 {
455     DtMailEnv           error;
456     DtMail::MailRc      *mailrc = ssn->mailRc(error);
457     const char          *value = NULL;
458     static char         idbuf[DTMAS_IDSIZE+1];
459     Boolean             boolval = FALSE;
460
461     DTMAS_CONCAT_MAILRC_KEY(idbuf, pfx, id);
462     mailrc->getValue(error, idbuf, &value);
463     if (error.isSet())
464       boolval = dflt;
465     else
466       boolval = TRUE;
467
468     if (NULL != value) free((void*) value);
469     return boolval;
470 }
471
472 //
473 // Returns TRUE if the folder being accessed is the inbox.
474 //
475 Boolean
476 DtMailServer::is_inbox()
477 {
478     if (NULL==_folder || 0==strncmp(_folder, DTMAS_INBOX, strlen(DTMAS_INBOX)))
479       return TRUE;
480     
481     return FALSE;
482 }
483
484 //
485 // Send message to the front end for display in the status line.
486 //
487 void
488 DtMailServer::send_info_message(DtMailCallbackOp op)
489 {
490     const char *errmsg = (const char *) _info;
491
492 #if defined(SEPARATE_FRONT_AND_BACK_END)
493     DtMailEnv error;
494     DtMailEventPacket event;
495
496     event.key = _mailbox->getObjectKey();
497     event.target = DTM_TARGET_MAILBOX;
498     event.target_object = _mailbox;
499     event.operation = (void*) op;
500     if (NULL != errmsg)
501       event.argument = strdup(errmsg);
502     else
503       event.argument = NULL;
504     event.event_time = time(NULL);
505
506     _session->writeEventData(error, &event, sizeof(event));
507 #else
508     _mailbox->callCallback(op, strdup(errmsg));
509 #endif
510 }
511
512 //
513 // Retrieve messages from server using given protocol method table
514 //
515 void
516 DtMailServer::retrieve_messages(DtMailEnv &error)
517 {
518     DTMailError_t       ok = DTME_NoError;
519     int                 js;
520     struct sigaction    action, o_action;
521     int                 *msgsizes = (int*) NULL;
522     int                 *msgisold = (int*) NULL;
523
524     _transnum = 0;
525
526     /* set up the server-nonresponse timeout */
527     memset((char*) &action, 0, sizeof(struct sigaction));
528     memset((char*) &o_action, 0, sizeof(struct sigaction));
529     action.sa_handler = (SA_HANDLER_TYPE) vtalarm_handler;
530
531     sigaction(SIGNAL_TYPE, (const struct sigaction *) &action, &o_action);
532
533     if ((js = setjmp(restart)) == 1)
534     {
535         _logger.logError(
536                 DTM_TRUE,
537                 "Timeout after %d seconds waiting for %s.\n",
538                 _timeout, _servername);
539         ok = DTME_MailServerAccess_Error;
540     }
541     else if (js == 2)
542     {
543         /* error message printed at point of longjmp */
544         ok = DTME_MailServerAccess_Error;
545     }
546     else
547     {
548         char    buf[DTMAS_POPBUFSIZE+1];
549         int     len, num, count, numnew;
550         int     deletions = 0;
551         int     sockfd = -1;
552
553         if (proto_requires_password() && NULL == _password)
554         {
555             ok = DTME_MailServerAccess_MissingPassword;
556             goto restoreSignal;
557         }
558
559         vtalarm_setitimer(_timeout);
560         _info.vSetError(DTME_MailServerAccessInfo_SocketOpen,
561                         DTM_FALSE, NULL, _username, _servername);
562         send_info_message(DTMC_SERVERACCESSINFO);
563         if (NULL != _errorstring)
564         {
565             free(_errorstring);
566             _errorstring = NULL;
567         }
568         _sockfp = SockOpen(_servername, proto_port(), &_errorstring);
569         if (NULL == _sockfp)
570         {
571             if (NULL == _errorstring)
572               _errorstring = strdup(_logger.errnoMessage());
573             ok = DTME_MailServerAccess_SocketIOError;
574             goto restoreSignal;
575         }
576         else if (_protologging)
577         {
578             _logger.logError(DTM_FALSE, "%s> %s", proto_name(), "SockOpen");
579         }
580
581         /* accept greeting message from mail server */
582         vtalarm_setitimer(_timeout);
583         ok = ptrans_parse_response(buf);
584         if (ok != DTME_NoError) goto closeServer;
585
586         /* try to get authorized to fetch mail */
587         vtalarm_setitimer(_timeout);
588         _shroud = _password;
589         ok = ptrans_authorize(buf);
590         _shroud = (char*) NULL;
591         if (ok != DTME_NoError) goto closeServer;
592
593         /* compute number of messages and number of new messages waiting */
594         vtalarm_setitimer(_timeout);
595         ok = ptrans_fldstate_read(&count, &numnew);
596         if (ok != DTME_NoError) goto closeServer;
597
598         /* show user how many messages we downloaded */
599         if (_protologging)
600         {
601             if (count == 0)
602               _logger.logError(
603                                 DTM_FALSE,
604                                 "INFO: No mail from %s@%s",
605                                 _username, _servername);
606             else
607             {
608                 if (numnew != -1 && (count - numnew) > 0)
609                   _logger.logError(
610                                 DTM_FALSE,
611                                 "INFO: %d message%s (%d seen) from %s@%s.",
612                                 count, count > 1 ? "s" : "", count-numnew,
613                                 _username, _servername);
614                 else
615                     _logger.logError(
616                                 DTM_FALSE,
617                                 "INFO: %d message%s from %s@%s.",
618                                 count, count > 1 ? "s" : "",
619                                 _username, _servername);
620             }
621         }
622
623         if (count > 0)
624         {
625             int nmsgtofetch = 0;
626             int fetched = 0;
627
628             /* we may need to get sizes in order to check message limits */
629             if (_sizelimit)
630             {
631                 msgsizes = (int *)malloc(sizeof(int) * count);
632
633                 vtalarm_setitimer(_timeout);
634                 ok = ptrans_msgsizes(count, msgsizes);
635                 if (ok != DTME_NoError) goto closeServer;
636             }
637
638             if (! _retrieveold)
639             {
640                 msgisold = (int*) malloc(sizeof(int) * count);
641
642                 for (num = 1; num <= count; num++)
643                 {
644                     vtalarm_setitimer(_timeout);
645                     msgisold[num-1] = ptrans_msgisold(num);
646                 }
647             }
648
649             for (num = 1; num <= count; num++)
650             {
651                 int toolarge =  msgsizes && (msgsizes[num-1] > _sizelimit);
652                 int ignoreold = msgisold && msgisold[num-1];
653
654                 if (! (toolarge || ignoreold)) nmsgtofetch++;
655             }
656
657             if (! nmsgtofetch)
658             {
659                 _info.vSetError(DTME_MailServerAccessInfo_NoMessages,
660                                 DTM_FALSE, NULL, _username, _servername);
661                 send_info_message(DTMC_SERVERACCESSINFO);
662             }
663
664             /*
665              * In IMAP4 you can retrieve a message without marking it as
666              * having been seen while in POP3 and IMAP2BIS this is NOT
667              * possible.  The proto_is_peek_capable encapsulates this
668              * capability.
669              *
670              * The problem is when there is any kind of transient error
671              * (DNS lookup failure, or sendmail refusing delivery due to
672              * process-table limits) during retrieval, the message will
673              * be marked "seen" on the server without having been retrieved
674              * by dtmail.
675              *
676              * We need to keep track of any errors which take place in a
677              * given retrieval pass (_retrieveerrors).  If there were any
678              * errors during the previous pass, all messages which were new
679              * at that time will be delivered.
680              */
681
682             /* read, forward, and delete messages */
683             _retrieveerrors = 0;
684             for (num = 1, fetched = 0; nmsgtofetch && num <= count; num++)
685             {
686                 int     toolarge =  msgsizes && (msgsizes[num-1] > _sizelimit);
687                 int     ignoreold = msgisold && msgisold[num-1];
688
689                 /*
690                  * We may want to reject this message if it is
691                  * too large or old
692                  */
693                 if (toolarge || ignoreold)
694                 {
695                     if (_protologging)
696                     {
697                         _logger.logError(DTM_FALSE,"skipping message %d",num);
698                         if (toolarge)
699                           _logger.logError(
700                                         DTM_FALSE,
701                                         " (oversized, %d bytes)",
702                                         msgsizes[num-1]);
703                     }
704                     if (toolarge)
705                     {
706                         _info.vSetError(
707                                 DTME_MailServerAccessInfo_MessageTooLarge,
708                                 DTM_FALSE, NULL, msgsizes[num-1]);
709                         send_info_message(DTMC_SERVERACCESSINFOERROR);
710                     }
711                 }
712                 else
713                 {
714                     vtalarm_setitimer(_timeout);
715
716                     /*
717                      * Fetch a message from the server.
718                      */
719                     fetched++;
720                     _info.vSetError(DTME_MailServerAccessInfo_RetrievingMessage,
721                                     DTM_FALSE, NULL,
722                                     fetched, nmsgtofetch,
723                                     _username, _servername);
724                     send_info_message(DTMC_SERVERACCESSINFO);
725
726                     ok = ptrans_retrieve_start(num, &len);
727                     if (ok != DTME_NoError)
728                     {
729                         _retrieveerrors++;
730                         goto closeServer;
731                     }
732
733                     if (_protologging)
734                       _logger.logError(
735                                         DTM_FALSE,
736                                         "INFO: reading message %d (%d bytes)",
737                                         num, len);
738
739                     /* Read the message and append it to the mailbox. */
740                     vtalarm_setitimer(_timeout);
741                     ok = ptrans_retrieve_readandappend(error, len);
742                     if (ok != DTME_NoError)
743                     {
744                         _retrieveerrors++;
745                         goto closeServer;
746                     }
747
748                     /* Tell the server we got it OK and resynchronize. */
749                     vtalarm_setitimer(_timeout);
750                     ok = ptrans_retrieve_end(num);
751                     if (ok != DTME_NoError)
752                     {
753                         _retrieveerrors++;
754                         goto closeServer;
755                     }
756
757                     /* Mark the message seen and remove it from the server. */
758                     if (_removeafterdelivery)
759                     {
760                         deletions++;
761                         if (_protologging) 
762                           _logger.logError(DTM_FALSE, " deleted\n");
763                         vtalarm_setitimer(_timeout);
764                         ok = ptrans_delete(num);
765                         if (ok != DTME_NoError) goto closeServer;
766                     }
767                     else if (_protologging) 
768                       _logger.logError(DTM_FALSE, " not deleted\n");
769                 }
770             }
771
772             /* Remove all messages flagged for deletion. */
773             if (deletions > 0)
774             {
775                 vtalarm_setitimer(_timeout);
776                 ok = ptrans_fldstate_expunge();
777                 if (ok != DTME_NoError) goto closeServer;
778             }
779         }
780         else
781         {
782             _info.vSetError(DTME_MailServerAccessInfo_NoMessages,
783                             DTM_FALSE, NULL, _username, _servername);
784             send_info_message(DTMC_SERVERACCESSINFO);
785         }
786
787     closeServer:
788         vtalarm_setitimer(_timeout);
789         if (ok != DTME_MailServerAccess_SocketIOError)
790           if (ok == DTME_NoError)
791             ok = ptrans_quit();
792           else
793             (void) ptrans_quit();
794         vtalarm_setitimer(0);
795         SockClose(_sockfp);
796         _sockfp = NULL;
797         dtmasTAGCLR();
798     }
799
800 restoreSignal:
801     _sockfp = NULL;
802     if (ok != DTME_NoError)
803     {
804         if (NULL == _errorstring)
805           _errorstring = strdup("");
806         error.vSetError(
807                         ok, DTM_TRUE, NULL,
808                         _username, _servername, proto_name(), _errorstring);
809         _logger.logError(
810                         DTM_TRUE,
811                         "Error while fetching from '%s':  \n%s\n",
812                         _servername, (const char*) error);
813
814     }
815     else
816       error.clear();
817
818     if (_errorstring)
819     {
820         free(_errorstring);
821         _errorstring = NULL;
822     }
823     if (msgsizes != NULL) free(msgsizes);
824     if (msgisold != NULL) free(msgisold);
825     sigaction(SIGNAL_TYPE, (const struct sigaction *) &o_action, NULL);
826 }
827
828 //
829 // Reset the nonresponse-timeout
830 //
831 #if defined(__hpux)
832 #define TV_USEC_TYPE    long
833 #else
834 #define TV_USEC_TYPE    int
835 #endif
836 void
837 DtMailServer::vtalarm_setitimer(int timeout_seconds)
838 {
839     struct itimerval ntimeout;
840
841     ntimeout.it_interval.tv_sec = (time_t) 0;
842     ntimeout.it_interval.tv_usec = (TV_USEC_TYPE) 0;
843     ntimeout.it_value.tv_sec  = (time_t) timeout_seconds;
844     ntimeout.it_value.tv_usec = (TV_USEC_TYPE) 0;
845     setitimer(ITIMER_TYPE, &ntimeout, (struct itimerval*) NULL);
846 }
847
848 //
849 // Handle server-timeout ALARM signal
850 //
851 void
852 DtMailServer::vtalarm_handler(int)
853 {
854     longjmp(restart, 1);
855 }