Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / dtmail / MailSession.C
1 /*
2  *+SNOTICE
3  *
4  *      $TOG: MailSession.C /main/9 1999/03/26 16:51:51 mgreess $
5  *
6  *      RESTRICTED CONFIDENTIAL INFORMATION:
7  *      
8  *      The information in this document is subject to special
9  *      restrictions in a confidential disclosure agreement between
10  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
11  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
12  *      Sun's specific written approval.  This document and all copies
13  *      and derivative works thereof must be returned or destroyed at
14  *      Sun's request.
15  *
16  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
17  *
18  *+ENOTICE
19  */
20
21 #include <unistd.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24
25 #include <X11/Intrinsic.h>
26 #include <DtMail/DtMail.hh>
27 #include <DtMail/DtMailError.hh>
28 #include <DtMail/DtMailXtProc.h>
29 #include <DtMail/IO.hh>
30
31 #include "MailSession.hh"
32 #include "MemUtils.hh"
33 #include "RoamMenuWindow.h"
34
35 DtMail::Session * MailSession::_app_session = NULL;
36 int MailSession::_num_deactivated = 0;
37
38 MailSession::MailSession(DtMailEnv & error, XtAppContext context)
39 : _open_mailboxes(128)
40 {
41     error.clear();
42
43     if (_app_session) {
44         error.setError(DTME_ObjectInUse);
45         return;
46     }
47
48     _app_session = new DtMail::Session(error, "dtmail");
49     if (error.isSet())
50     {
51         // Benign error
52         if ((DTMailError_t)error == DTME_NoMsgCat) error.clear();
53
54         // Else need to translate the error into an DTME_* error
55         // defined in DtMailError.hh
56     }
57
58     XtAppAddInput(context,
59                   _app_session->eventFileDesc(error),
60                   (XtPointer)XtInputReadMask,
61                   DtMailXtInputProc,
62                   _app_session);
63
64 #if 0
65     //
66     // Used to be both XtInputReadMask and XtInputExceptMask
67     // went to the same procedure.  Resulted in problems in
68     // when using R6 polling instead of R5 select.  Now
69     // use separate input handlers.
70     //
71     XtAppAddInput(context,
72                   _app_session->eventFileDesc(error),
73                   (XtPointer)XtInputExceptMask,
74                   DtMailXtExceptProc,
75                   _app_session);
76 #endif
77
78     DtMailDamageContext = context;
79 }
80
81 MailSession::~MailSession(void)
82 {
83     for (int mb = 0; mb < _open_mailboxes.length(); mb++)
84     {
85         delete _open_mailboxes[mb]->handle;
86         delete _open_mailboxes[mb]->path;
87     }
88
89     delete _app_session;
90 }
91
92 Boolean
93 MailSession::isMboxOpen(const char *path)
94 {
95     int pos = locate(path);
96     if (pos >= 0) return (TRUE);
97     return (FALSE);
98 }
99
100 RoamMenuWindow *
101 MailSession::getRMW(const char *path)
102 {
103     int slot = locate(path);
104     if (slot >= 0)
105       return(_open_mailboxes[slot]->rmw);
106     return NULL;
107 }
108
109 RoamMenuWindow *
110 MailSession::getRMW(DtMail::MailBox *mbox)
111 {
112     int slot = locate(mbox);
113     return(_open_mailboxes[slot]->rmw);
114 }
115
116 DtMail::MailBox *
117 MailSession::open(
118     DtMailEnv & error, 
119     const char * path,
120     DtMailCallback cb_func, 
121     void * client_data,
122     DtMailBoolean auto_create, 
123     DtMailBoolean request_lock,
124     DtMailBoolean auto_parse)
125 {
126     // First, see if we have this open in this process.
127     int slot = locate(path);
128
129     // We do not allow open an already opened mailbox
130     // because this may cause memory fault when a message is
131     // deleted from one RMW and the other RMW would like to
132     // read the already deleted message.
133     // (1) set error to DTME_AlreadyOpened
134     // (2) Return a NULL
135     if (slot >= 0)
136     {
137         error.setError(DTME_AlreadyOpened);
138         if (client_data == NULL)
139         {
140             _open_mailboxes[slot]->open_ref_count += 1;
141             return _open_mailboxes[slot]->handle;
142         } else return NULL;
143     }
144
145     // Create a handle for determining what to do next. This will
146     // add us to the file session so we will start getting call
147     // back requests on this file.
148     DtMail::MailBox * mailbox = _app_session->mailBoxConstruct(
149                                                 error, DtMailFileObject,
150                                                 (void *)path,
151                                                 cb_func, client_data);
152     if (error.isSet())
153     {
154         error.setError(DTME_ObjectCreationFailed);
155         delete mailbox;
156         return NULL;
157     }
158     
159     // Does this file exist? If it doesn't and create is
160     // on then make one. If create is off, then raise an
161     // error.
162     mailbox->open(error, 
163               auto_create, 
164               DTMAIL_DEFAULT_OPEN_MODE, 
165               DTMAIL_DEFAULT_CREATE_MODE,
166               request_lock,
167               auto_parse);
168  
169     // Need to translate from BE error to a FE error that the
170     // user can understand.  Opening a mail container can result
171     // in a variety of errors.  Translate those that are considered
172     // to be relevant (for now) - the set can always be extended.
173     // Toss others into an UnknownFormat error.
174     if (error.isSet())
175     {
176         delete mailbox;
177         return(NULL);
178     }
179
180     addToList(mailbox, path, (RoamMenuWindow *) client_data);
181     return mailbox;
182 }
183
184 void
185 MailSession::close(DtMailEnv & error, const DtMail::MailBox * mb)
186 {
187     // Find the mail box slot.
188     int slot = locate(mb);
189     if (slot < 0)
190     {
191         error.setError(DTME_ObjectInvalid);
192         return;
193     }
194
195     MailBoxItem * mbi = _open_mailboxes[slot];
196     mbi->open_ref_count -= 1;
197     if (mbi->open_ref_count <= 0)
198     {
199         if (! _open_mailboxes[slot]->is_active) _num_deactivated--;
200
201         delete mbi->handle;
202         delete mbi->path;
203
204         _open_mailboxes.remove(slot);
205         delete mbi;
206     }
207 }
208
209 void 
210 MailSession::convert(
211     DtMailEnv & error, 
212     const char *,               // old_path
213     const char *,               // new_path
214     DtMailStatusCallback,       // cb_func
215     void *)                     // client_data
216 {
217     error.clear();
218 }
219
220 void
221 MailSession::copy(
222     DtMailEnv & error, 
223     DtMail::Message &,          // msg
224     const char *)               // path
225 {
226     error.clear();
227 }
228
229 int
230 MailSession::locate(const char *path)
231 {
232     int slot;
233     struct stat pathbuf;
234
235     SafeStat(path, &pathbuf);
236     for (slot = 0; slot < _open_mailboxes.length(); slot++)
237     {
238         if (strcmp(_open_mailboxes[slot]->path, path) == 0)
239           return slot;
240
241         if (! _open_mailboxes[slot]->stated)
242         {
243             _open_mailboxes[slot]->stated = TRUE;
244             SafeStat(
245                 _open_mailboxes[slot]->path,
246                 &_open_mailboxes[slot]->statbuf);
247         }
248         
249         if (pathbuf.st_ino == _open_mailboxes[slot]->statbuf.st_ino &&
250             pathbuf.st_dev == _open_mailboxes[slot]->statbuf.st_dev)
251           return slot;
252     }
253
254     return -1;
255 }
256
257 int
258 MailSession::locate(const DtMail::MailBox *mb)
259 {
260     for (int slot = 0; slot < _open_mailboxes.length(); slot++)
261       if (mb == _open_mailboxes[slot]->handle)
262         return slot;
263
264     return -1;
265 }
266
267 int
268 MailSession::locate(const RoamMenuWindow *rmw)
269 {
270     for (int slot = 0; slot < _open_mailboxes.length(); slot++)
271       if (rmw == _open_mailboxes[slot]->rmw)
272         return slot;
273
274     return -1;
275 }
276
277 int
278 MailSession::isActiveRMW(RoamMenuWindow *rmw)
279 {
280     int slot = locate((const RoamMenuWindow *) rmw);
281     if (slot < 0) return 0;
282     
283     return _open_mailboxes[slot]->is_active;
284 }
285
286 void
287 MailSession::activateRMW(RoamMenuWindow *rmw)
288 {
289     int slot = locate((const RoamMenuWindow *) rmw);
290     if (slot < 0) return;
291     
292     if (! _open_mailboxes[slot]->is_active)
293     {
294         DtMail::MailBox *mailbox = rmw->mailbox();
295         mailbox->enableMailRetrieval();
296
297         DtMailEnv mail_error;
298         mail_error.clear();
299         rmw->checkForMail(mail_error);
300
301         _open_mailboxes[slot]->is_active = TRUE;
302         _num_deactivated--;
303     }
304 }
305
306 void
307 MailSession::deactivateRMW(RoamMenuWindow *rmw)
308 {
309     int slot = locate((const RoamMenuWindow *) rmw);
310     if (slot < 0) return;
311     
312     if (_open_mailboxes[slot]->is_active)
313     {
314         DtMail::MailBox *mailbox = rmw->mailbox();
315         mailbox->disableMailRetrieval();
316
317         _open_mailboxes[slot]->is_active = FALSE;
318         _num_deactivated++;
319     }
320 }
321
322 void
323 MailSession::addToList(
324                 DtMail::MailBox *mb,
325                 const char *path,
326                 RoamMenuWindow *rmw)
327 {
328     MailBoxItem * mbi = new MailBoxItem;
329
330     mbi->handle = mb;
331     mbi->is_active = TRUE;
332     mbi->stated = FALSE;
333     mbi->open_ref_count = 1;
334     mbi->path = strdup_n(path);
335     mbi->rmw = rmw;
336     
337     _open_mailboxes.append(mbi);
338 }
339
340 Tt_status 
341 MailSession::lockCB(Tt_message, Tttk_op, const char*, uid_t, int, void*)
342 {
343     // We never give up the lock during a copy!
344     return TT_ERR_INVALID;
345 }