Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtmail / libDtMail / Common / IO.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 librararies 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  *
27  *      $TOG: IO.C /main/33 1999/01/29 14:45:00 mgreess $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 #define X_INCLUDE_TIME_H
45 #define X_INCLUDE_GRP_H
46 #define X_INCLUDE_PWD_H
47 #define XOS_USE_NO_LOCKING
48 #include <X11/Xos_r.h>
49
50 #include <assert.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdlib.h>
57 //
58 // START Order dependent for AIX
59 //
60 #include <sys/socket.h>
61 #if defined(_aix)
62 #include <sys/socketvar.h>
63 #if defined(BIG_ENDIAN)
64 #undef BIG_ENDIAN
65 #endif
66 #endif
67 #include <netinet/in.h>
68 #include <netdb.h>
69 #include <arpa/inet.h>
70 //
71 // END Order dependent for AIX
72 //
73 #include <sys/stat.h>
74 #if !defined(linux)
75 #  include <sys/statvfs.h>
76 #endif
77 #include <sys/types.h>
78 #include <sys/wait.h>
79 #include <sys/uio.h>
80 #include <unistd.h>
81
82 #ifdef _AIX
83 #include <sys/mntctl.h>
84 #include <sys/statfs.h>
85 #include <sys/vfs.h>
86 #define IOVMAX MSG_MAXIOVLEN
87 extern "C"
88 {
89           fchmod(int, mode_t);
90           statfs(const char *, struct statfs *);
91           mntctl(int, int, char *);
92   ssize_t writev(int, const struct iovec *, int);
93 }
94 #if (OSMAJORVERSION==4) && (OSMINORVERSION==2)
95 /* Temporary hack till the /usr/lpp/xlC/include/unistd.h file is fixed. */
96 extern "C" { int lockf(int, int, off_t); }
97 #endif
98 #endif /* _AIX */
99
100 #ifdef __osf__
101 extern "C" { int statvfs(const char *, struct statvfs *); }
102 #endif /* __osf__ */
103
104 #include <DtMail/DtMail.hh>
105 #include <DtMail/DtMailError.hh>
106 #include <DtMail/IO.hh>
107 #include <DtMail/Threads.hh>
108
109 #if !defined(IOV_MAX)
110   #if !defined(linux)
111     #include <sys/stream.h>
112   #endif
113   #if !defined(DEF_IOV_MAX)
114     #define DEF_IOV_MAX 16
115   #endif
116   #define IOV_MAX DEF_IOV_MAX
117 #endif
118
119 #define IOVEC_IOVBASE_INCREMENTOR(iov, bytes) \
120         ((caddr_t)((size_t)iov->iov_base+bytes))
121
122 // The following I/O routines are wrappers for the normal routines,
123 // but they deal with EINTR, and partial read/write situations.
124 //
125 //
126 int
127 SafeOpen(const char * path, int oflag, mode_t mode)
128 {
129     int status;
130     
131     do {
132         status = open(path, oflag, mode);
133     } while (status < 0 && errno == EINTR);
134
135     return(status);
136 }
137
138 int
139 SafeClose(int fd)
140 {
141     int status;
142     do {
143         status = close(fd);
144     } while (status < 0 && errno == EINTR);
145
146     return(status);
147 }
148
149 int
150 SafeLink(const char * existingPath, const char * newPath)
151 {
152   int status;
153   do {
154     status = link(existingPath, newPath);
155   } while (status < 0 && errno == EINTR);
156
157   return(status);
158 }
159
160 int
161 SafeRename(const char * oldPath, const char * newPath)
162 {
163   int status;
164   do {
165     status = rename(oldPath, newPath);
166   } while (status < 0 && errno == EINTR);
167
168   return(status);
169 }
170
171 int
172 SafeRemove(const char *path)
173 {
174     int status;
175     do {
176       status = remove(path);
177     } while (status < 0 && errno == EINTR);
178
179     return(status);
180 }
181
182 int
183 SafeUnlink(const char *path)
184 {
185     int status;
186     do {
187       status = unlink(path);
188     } while (status < 0 && errno == EINTR);
189
190     return(status);
191 }
192
193 ssize_t
194 SafeRead(int fd, void * buf, size_t bytes)
195 {
196     ssize_t status = 0;
197     do {
198         status = read(fd, buf, bytes);
199     } while(status < 0 && errno == EINTR);
200
201     return(status);
202 }
203
204 ssize_t
205 SafeWrite(int fd, const void * buf, size_t bytes)
206 {
207     ssize_t status = 0;
208     do {
209         status = write(fd, buf, bytes);
210     } while(status < 0 && errno == EINTR);
211     
212     return(status);
213 }
214
215 // SafeWritev -- safe multiply vectored write
216 // Description:
217 //   SafeWritev provides an interrupt safe way to call the writev() system
218 //   call. In addition, it removes the IOV_MAX limitation on the size of the
219 //   iovec structure, and it will not return until either all bytes specified
220 //   by the iovec structure are written or writev() returns an error.
221 // Arguments:
222 //   int fd     -- file descriptor to write to
223 //   struct iovec *iov -- iovec structure describing writes to be done
224 //   int iovcnt -- number of elements in passed in iov structure
225 // Outputs:
226 //   Will effectively destroy the contents of the passed in iovec structure.
227 //   The caller must deallocate the storage associated with the structure
228 //   upon regaining control.
229 // Returns:
230 //   == -1 : error returned from writev() - errno set to specific error number
231 //   != -1 : number of bytes actually written to the file
232
233 unsigned long
234 SafeWritev(int fd, struct iovec *iov, int iovcnt)
235 {
236   ssize_t status;
237   unsigned long bytesWritten = 0;
238
239   // outer loop: starting with the first write vector, as long as there is
240   // at least one vector left to feed writev(), do so
241   //
242   for(int curIov = 0; curIov < iovcnt; ) {
243
244     // inner loop: feed writev() allowing for interrupted system call
245     do {
246       status = writev(
247                 fd,
248                 &iov[curIov],
249                 (iovcnt-curIov) > IOV_MAX ? IOV_MAX : (iovcnt-curIov));
250     } while (status < 0 && errno == EINTR);
251
252     if (status == (ssize_t)-1)          // true error from writev??
253       return((unsigned long)-1);        // yes: bail at this point to caller
254     bytesWritten += status;             // bump # bytes written count
255
256     // must now "walk through" the io vector until we are up the to point
257     // indicated by the number of bytes written by writev() - any leftover
258     // in status indicates a partial write of a vector
259     //
260     while ((status > 0) && (curIov < iovcnt) && (iov[curIov].iov_len <= status)) {
261       status -= iov[curIov++].iov_len;
262     }
263
264     // Check to see if we have reached the end of the io vector array; also
265     // check to see if more bytes were written than called for; as crazy as
266     // this sounds, in at least one instance when we finish spinning through
267     // the io vectors we still had bytes left that had been written but not
268     // accounted for in the io vectors (status > 0 && curIov >= iovcnt)
269     //
270     if (curIov >= iovcnt) {             // out of IO vectors?
271       if (status > 0) {                 // yes: all data accounted for?
272         DtMailEnv error;                // NO:: log error condition
273         error.logError(
274                 DTM_TRUE,
275                 "SafeWritev: writev(): too many bytes written (%d/%d)\n",
276                 status, bytesWritten);
277       }
278       continue;                         // continue and let for loop exit
279     }
280     
281     // Check for a partial write: if the current vector contains more data
282     // than what has been written, writev() bailed in the middle of writing
283     // a vector - adjust the vector and and feed it back to writev() again
284     // OTHERWISE writev() ended with the current vector so move on to the next
285     //
286     if (iov[curIov].iov_len == status)  // full write of this vector?
287       curIov++;                         // yes: move on to the next vector
288     else if (status != 0) {             // no: adjust this vector and retry
289       iov[curIov].iov_len -= status;
290       iov[curIov].iov_base = IOVEC_IOVBASE_INCREMENTOR((&iov[curIov]), status);
291     }
292   }
293   return(bytesWritten);
294 }
295
296 #define SWS_BUFFERSIZE 1024
297 ssize_t
298 SafeWriteStrip(int fd, const void * buf, size_t bytes)
299 {
300     ssize_t status = 0;
301     int i, j;
302     char *ptr = (char*)buf, *writebuf; 
303     
304     // bug 5856: dont write out control M 
305     // make a finite size buffer for writing
306     writebuf = (char*) malloc(bytes < SWS_BUFFERSIZE ? bytes : SWS_BUFFERSIZE); 
307
308     for (i = 0, j = 0; i < bytes; i++, ptr++) {
309         if (*ptr == '\r' && *(ptr+1) == '\n')
310                 continue;
311         writebuf[j++] = *ptr;
312         if (j == SWS_BUFFERSIZE || i == (bytes-1)) {
313                 do {
314                         status = write(fd, writebuf, j);
315                 } while(status < 0 && errno == EINTR);
316                 j = 0;
317         }
318     }
319     free(writebuf);
320     
321     return(status);
322 }
323
324 int
325 SafeStat(const char * path, struct stat * buf)
326 {
327     int status;
328     do {
329         status = stat(path, buf);
330     } while (status < 0 && errno == EINTR);
331
332     return(status);
333 }
334
335 int
336 SafeFchown(int fd, uid_t owner, gid_t group)
337 {
338   int status;
339   do {
340     status = fchown(fd, owner, group);
341   } while (status < 0 && errno == EINTR);
342
343   return(status);
344 }
345
346 int
347 SafeLStat(const char * path, struct stat * buf)
348 {
349     int status;
350     do {
351         status = lstat(path, buf);
352     } while (status < 0 && errno == EINTR);
353
354     return(status);
355 }
356
357 int
358 SafeFStat(int fd, struct stat * buf)
359 {
360     int status;
361     do {
362         status = fstat(fd, buf);
363     } while (status < 0 && errno == EINTR);
364
365     return(status);
366 }
367
368 // SafeGuaranteedStat - return stat info for object given path name
369 // If NFS attribute caching is enabled (which is the default), a
370 // stat/fstat of a NFS file may not return the correct true size of the
371 // mailbox if it has been appended to since the last time it was read.
372 // To get around this problem, this function will perform a open(),
373 // read() of 1 byte, fstat(), close() which will force the attributes
374 // for the named file to be retrieved directly from the server.
375 // 
376 int
377 SafeGuaranteedStat(const char * path, struct stat * buf)
378 {
379   int saveErrno;
380
381 #ifndef O_RSYNC
382   int tempFd = SafeOpen(path, O_RDONLY|O_SYNC);
383 #else
384   int tempFd = SafeOpen(path, O_RDONLY|O_RSYNC|O_SYNC);
385 #endif /* O_RSYNC */
386
387   if (tempFd == -1) {
388     return(-1);
389   }
390
391   char tempBuf;  
392   if (SafeRead(tempFd, &tempBuf, 1) == -1) {
393     saveErrno = errno;
394     (void) SafeClose(tempFd);
395     errno = saveErrno;
396     return(-1);
397   }
398
399   if (SafeFStat(tempFd, buf) == -1) {
400     saveErrno = errno;
401     (void) SafeClose(tempFd);
402     errno = saveErrno;
403     return(-1);
404   }
405
406   (void) SafeClose(tempFd);
407
408   return(0);
409 }
410
411 int
412 SafeTruncate(const char * path, off_t len)
413 {
414     int status;
415     do {
416         status = truncate((char *)path, len);   // The cast is for AIX
417     } while (status < 0 && errno == EINTR);
418
419     return(status);
420 }
421
422 int
423 SafeFTruncate(int fd, off_t len)
424 {
425     int status;
426     do {
427         status = ftruncate(fd, len);
428     } while (status < 0 && errno == EINTR);
429
430     return(status);
431 }
432
433 int
434 SafeAccess(const char * path, int amode)
435 {
436     int status;
437     do {
438         status = access(path, amode);
439     } while (status < 0 && errno == EINTR);
440
441     return(status);
442 }
443
444 #if defined(sun)
445 #define LOCKF_SIZE_TYPE long
446 #else
447 #define LOCKF_SIZE_TYPE off_t
448 #endif
449
450 int
451 SafeLockf(int fd, int func, long size)
452 {
453     int status;
454     do {
455         status = lockf(fd, func, (LOCKF_SIZE_TYPE) size);
456     } while (status < 0 && errno == EINTR);
457
458     return(status);
459 }
460
461 int
462 SafeFChmod(int fd, mode_t mode)
463 {
464     int status;
465     do {
466         status = fchmod(fd, mode);
467     } while (status < 0 && errno == EINTR);
468
469     return(status);
470 }
471
472 int
473 SafeDup2(int fd1, int fd2)
474 {
475     int status;
476     do {
477         status = dup2(fd1, fd2);
478     } while (status < 0 && errno == EINTR);
479
480     return(status);
481 }
482
483 int
484 SafeExecvp(const char * file, char *const *argv)
485 {
486     int status;
487     do {
488
489         status = execvp(file, (char * const *)argv);
490
491     } while (status < 0 && errno == EINTR);
492
493     return(status);
494 }
495
496 int
497 SafeWaitpid(pid_t proc, int * p_stat, int options)
498 {
499     pid_t status;
500     do {
501         status = waitpid(proc, p_stat, options);
502     } while (status < 0 && errno == EINTR);
503
504     return((int)status);
505 }
506
507 int
508 SafeWait(int * p_stat)
509 {
510     pid_t status;
511     do {
512         status = wait(p_stat);
513     } while (status < 0 && errno == EINTR);
514
515     return((int)status);
516 }
517
518 int
519 SafeUTime(const char * path, utimbuf * ntime)
520 {
521     int status;
522     do {
523         status = utime(path, ntime);
524     } while (status < 0 && errno == EINTR);
525
526     return(status);
527 }
528
529 void
530 SafePathIsAccessible(DtMailEnv &error, const char *path)
531 {
532     int status;
533
534     status = SafeAccess(path, F_OK);
535     if (-1 == status)
536     {
537         if (EACCES == errno)
538           error.vSetError(DTME_PathElementPermissions, DTM_FALSE, NULL, path);
539         else if (ENOTDIR == errno)
540           error.vSetError(DTME_PathElementNotDirectory, DTM_FALSE, NULL, path);
541         else if (ENOENT == errno)
542         {
543             char *s, *t;
544
545             t = strdup(path);
546             s = strrchr(t, '/');
547             if (s && s != t)
548             {
549                 *s = '\0';
550                 status = SafeAccess(t, F_OK);
551                 if (-1 == status)
552                   error.vSetError(
553                                 DTME_PathElementDoesNotExist,
554                                 DTM_FALSE, NULL,
555                                 path);
556             }
557         }
558     }
559 }
560
561 #if defined(POSIX_THREADS)
562 static void * time_mutex = NULL;
563 #endif
564
565 void
566 SafeCtime(const time_t *clock, char * buf, int buflen)
567 {
568   _Xctimeparams ctime_buf;
569   char *result;
570
571   memset((void*) &ctime_buf, 0, sizeof(_Xctimeparams));
572   result = _XCtime(clock, ctime_buf);
573   if (result)
574     strncpy(buf, result, buflen);
575   else
576     *buf = '\0';
577 }
578
579 void
580 SafeLocaltime(const time_t *clock, tm & result)
581 {
582   struct tm     *time_ptr;
583   _Xltimeparams localtime_buf;
584
585   memset((void*) &localtime_buf, 0, sizeof(_Xltimeparams));
586   time_ptr = _XLocaltime(clock, localtime_buf);
587   result = *time_ptr;
588 }
589
590 time_t
591 SafeMktime(tm * timeptr)
592 {
593 #if defined(POSIX_THREADS)
594
595     if (!time_mutex) {
596         time_mutex = MutexInit();
597     }
598
599     MutexLock lock_scope(time_mutex);
600 #endif
601
602     return(mktime(timeptr));
603 }
604
605 size_t
606 SafeStrftime(char * buf, size_t buf_size,
607              const char * format, const tm * timeptr)
608 {
609 #if defined(POSIX_THREADS)
610
611     if (!time_mutex) {
612         time_mutex = MutexInit();
613     }
614
615     MutexLock lock_scope(time_mutex);
616 #endif
617
618     return(strftime(buf, buf_size, format, timeptr));
619 }
620
621 #define  SockINTERNAL_BUFSIZE   2048
622
623 void *SockOpen(char *host, int clientPort, char **errorstring)
624 {
625     int sockfd;
626 #if defined(__osf__)
627     in_addr_t inaddr;
628 #else
629     unsigned long inaddr;
630 #endif
631     struct sockaddr_in ad;
632     struct hostent *hp;
633     DtMailEnv error;
634     char *errorfmt = NULL;
635
636     memset(&ad, 0, sizeof(ad));
637     ad.sin_family = AF_INET;
638
639     inaddr = inet_addr(host);
640     if (inaddr != -1)
641       memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
642     else
643     {
644         hp = gethostbyname(host);
645         if (hp == NULL)
646         {
647             if (NULL != errorstring)
648             {
649                 errorfmt = DtMailEnv::getMessageText(
650                                                 SockErrorSet, 2,
651                                                 "Unknown host:  %s");
652                 if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
653                 sprintf(*errorstring, errorfmt, host);
654             }
655             return (FILE*) NULL;
656         }
657         memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
658     }
659     ad.sin_port = htons(clientPort);
660     
661     sockfd = socket(AF_INET, SOCK_STREAM, 0);
662     if (sockfd < 0)
663     {
664         if (NULL != errorstring)
665         {
666             errorfmt = DtMailEnv::getMessageText(
667                                                 SockErrorSet, 3,
668                                                 "Error creating socket: %s");
669             if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
670             sprintf(*errorstring, errorfmt, error.errnoMessage());
671         }
672         return (FILE*) NULL;
673     }
674     if (connect(sockfd, (struct sockaddr *) &ad, sizeof(ad)) < 0)
675     {
676         if (NULL != errorstring)
677         {
678             errorfmt = DtMailEnv::getMessageText(
679                                         SockErrorSet, 3,
680                                         "Error connecting to socket:  %s");
681             if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
682             sprintf(*errorstring, errorfmt, error.errnoMessage());
683         }
684         close(sockfd);
685         return (FILE*) NULL;
686     }
687
688 #if defined(USE_SOCKSTREAM)
689     FILE *sockfp = fdopen(sockfd, "r+");
690     setvbuf(sockfp, NULL, _IONBF, SockINTERNAL_BUFSIZE);
691     return (void*) sockfp;
692 #else
693     return (void*) sockfd;
694 #endif
695 }
696
697 int SockPrintf(void *sockfp, char* format, ...)
698 {
699     va_list ap;
700     char *buf = new char[8192];
701     int i;
702
703     va_start(ap, format);
704     vsprintf(buf, format, ap);
705     va_end(ap);
706     i = SockWrite(buf, 1, strlen(buf), sockfp);
707     delete [] buf;
708     return i;
709 }
710
711 char *SockGets(char *buf, int len, void *sockfp)
712 {
713 #if defined(USE_SOCKSTREAM)
714     char *in = fgets(buf, len, (FILE*) sockfp);
715     fseek((FILE*) sockfp, 0L, SEEK_CUR);        /* required by POSIX */
716     return in;
717 #else
718     size_t n;
719     char *bufp;
720     
721     n = 0;
722     bufp = buf-1;
723     do
724     {
725         bufp++;
726         read((int) sockfp, (void*) bufp, 1);
727         n++;
728     } while (*bufp != '\n');
729     *(bufp+1) = '\0';
730     return buf;
731 #endif
732 }
733
734 int SockRead(char *buf, int size, int len, void *sockfp)
735 {
736 #if defined(USE_SOCKSTREAM)
737     int n = fread(buf, size, len, (FILE*) sockfp);
738     fseek((FILE*) sockfp, 0L, SEEK_CUR);        /* required by POSIX */
739 #else
740     int n = (int) read((int) sockfp, (void*) buf, (size_t) size * len);
741 #endif
742     return n;
743 }
744
745 int SockWrite(char *buf, int size, int len, void *sockfp)
746 {
747     int n;
748
749 #if defined(USE_SOCKSTREAM)
750     n = fwrite(buf, size, len, (FILE*) sockfp);
751     fseek((FILE*) sockfp, 0L, SEEK_CUR);        /* required by POSIX */
752 #else
753     n = write((int) sockfp, buf, size * len);
754 #endif
755
756     return n;
757 }
758
759 void SockClose(void *sockfp)
760 {
761 #if defined(USE_SOCKSTREAM)
762     fclose((FILE*) sockfp);
763 #else
764     close((int) sockfp);
765 #endif
766 }
767
768 void
769 GetGroupName(char * grp_name)
770 {
771     struct group *grp;
772     _Xgetgrparams grp_buf;
773
774     memset((void*) &grp_buf, 0, sizeof(_Xgetgrparams));
775     grp = _XGetgrgid(getegid(), grp_buf);
776
777     if (grp) {
778         strcpy(grp_name, grp->gr_name);
779     }
780     else {
781         strcpy(grp_name, "UNKNOWN_GROUP");
782     }
783
784 }
785
786 gid_t
787 GetIdForGroupName(char * grp_name)
788 {
789   assert(grp_name != NULL);
790   struct group *grp;
791   _Xgetgrparams grp_buf;
792   
793   memset((void*) &grp_buf, 0, sizeof(_Xgetgrparams));
794   grp = _XGetgrnam(grp_name, grp_buf);
795     
796   return(grp ? grp->gr_gid : (gid_t)-1);
797 }
798
799 void
800 GetPasswordEntry(passwd & result)
801 {
802   static struct passwd passwordEntry;
803   static int oneTimeFlag = 0;
804
805   if (!oneTimeFlag) {
806     _Xgetpwparams pw_buf;
807     struct passwd *tresult;
808
809     memset((void*) &pw_buf, 0, sizeof(_Xgetpwparams));
810 #if defined(_AIX)
811     _Xos_processLock;
812     tresult = getpwuid(getuid());
813     _Xos_processUnlock;
814 #else
815     tresult = _XGetpwuid(getuid(), pw_buf);
816 #endif
817
818     assert(tresult != NULL);
819     memcpy(&passwordEntry, tresult, sizeof(struct passwd));
820     passwordEntry.pw_name = strdup(passwordEntry.pw_name);
821     passwordEntry.pw_passwd = strdup(passwordEntry.pw_passwd);
822 #if !defined(_AIX) && !defined(linux)
823 #ifndef __osf__
824     passwordEntry.pw_age = strdup(passwordEntry.pw_age);
825 #endif
826     passwordEntry.pw_comment = strdup(passwordEntry.pw_comment);
827 #endif
828     passwordEntry.pw_gecos = strdup(passwordEntry.pw_gecos);
829     passwordEntry.pw_dir = strdup(passwordEntry.pw_dir);
830     passwordEntry.pw_shell = strdup(passwordEntry.pw_shell);
831     oneTimeFlag++;
832   }
833
834   memcpy(&result, &passwordEntry, sizeof(struct passwd));
835   return;
836 }
837 #if defined(MAILGROUP_REQUIRED)
838 int isSetMailGidNeeded(const char * mailboxPath)
839 {
840
841   assert(mailboxPath);
842
843     char inbox_path[1024];
844     char mbox_path[1024];
845     struct passwd *pw;
846     struct stat buf;
847     struct stat buf1;
848     _Xgetpwparams pw_buf;
849
850     memset((void*) &pw_buf, 0, sizeof(_Xgetpwparams));
851     pw = _XGetpwuid(getuid(), pw_buf);
852
853     // construct the lockfile name for the user.
854     char *lock_file = (char *)calloc(1,strlen(pw->pw_name) + 6);
855     strcpy(lock_file,pw->pw_name);
856     strcat(lock_file,".lock");
857
858     // parse the mailfolder name from the path
859     char *p = strrchr(mailboxPath,'/');
860     int len = (NULL!=0) ? strlen(mailboxPath)-strlen(p) : strlen(mailboxPath);
861     char *str = (char *) calloc(1, len+1);
862     strncpy(str, mailboxPath, len);
863     str[len] = '\0';
864     
865     stat(str,&buf);
866
867     // Default or system mailbox dir name.
868     strcpy(inbox_path, "/var/spool/mail");
869     stat(inbox_path,&buf1);
870     free(str);
871
872     if( ( (buf.st_dev == buf1.st_dev) && (buf.st_ino == buf1.st_ino) ) )
873     {
874         if( !strcmp((p+1),pw->pw_name) || !strcmp((p+1),lock_file) )
875         {  
876            if( access(mailboxPath,R_OK) == -1 )
877            {
878              free(lock_file);
879              return (1);
880            }
881         }
882         free(lock_file);
883         return ( 0 ); 
884     }
885     else
886     {
887         free(lock_file);
888         return ( 1 ); 
889     }
890 }
891 #endif
892
893 #ifdef _AIX
894 /*
895  * NAME: get_stat
896  *
897  * FUNCTION:
898  *      gather mount status for all virtual mounts for this host.
899  *
900  * EXECUTION ENVIRONMENT: Part of user command.
901  *
902  * ON ENTRY:
903  *      vmountpp        pointer to a buffer in which to put mount info
904  *
905  * NOTES:
906  *      get_stat() was lifted and slightly modified from
907  *      AIX Version 3 df.c.
908  *
909  * RETURNS:
910  *      < 0     error in mntctl()
911  *      > 0     for number of struct vmounts (mount points) in
912  *              buffer which is pointed to by pointer left at
913  *              *vmountpp.
914  */
915 int get_stat(
916 struct vmount   **vmountpp)     /* place to tell where buffer is */
917 {
918   size_t                size;
919   register struct vmount        *vm;
920   int                   nmounts;
921   int                   count;
922
923   size = BUFSIZ;                /* initial default size */
924   count = 10;                   /* don't try forever    */
925
926   while (count--) {             /* don't try it forever */
927         if ((vm = (struct vmount*) malloc(size)) == NULL) {
928                 return(-1);
929         }
930
931 /*
932  * perform the QUERY mntctl - if it returns > 0, that is the
933  * number of vmount structures in the buffer.  If it returns
934  * -1, an error occured.  If it returned 0, then look in
935  * first word of buffer for needed size.
936  */
937         if ((nmounts = mntctl(MCTL_QUERY, size, (caddr_t)vm)) > 0) {
938                 *vmountpp = vm;         /* OK, got it, now return */
939                 return(nmounts);
940         } else {
941                 if (nmounts == 0) {
942                         size = *(int *)vm; /* the buffer wasn't big enough */
943                         free((void *)vm);   /* get required buffer size     */
944                 } else {
945                         free((void *)vm);/* some other kind of error occurred*/
946                         return(-1);
947                 }
948         }
949   }
950   return(-1);
951 }
952
953 /*
954  * NAME: get_vmount
955  *
956  * FUNCTION:
957  *        Determines, via the filesystems vmount structures,
958  *        the vmount id of the the filesystem id provided as
959  *        an argument (enables ultimate access to the actual
960  *        name of the filesystem).
961  *
962  * EXECUTION ENVIRONMENT: Part of user command.
963  *
964  * RETURNS:
965  *      ptr to structure with vmount id of filesystem or NULL
966  */
967 struct vmount *get_vmount(fsid_t *fsid)
968 {
969     struct vmount *inu_vmount_p=NULL;
970     int inu_vmount_num;
971     register struct vmount *vm;
972     int nmount;
973
974     /* make sure we have all the virtual mount status of this host */
975     if(inu_vmount_p == NULL)
976         inu_vmount_num = get_stat(&inu_vmount_p);
977
978     /* get the number of struct vmount in the vmount buffer */
979     nmount = inu_vmount_num;
980
981     /* go thru all the structures in the vmount buffer */
982     for (vm = inu_vmount_p; nmount; nmount--,
983             vm = (struct vmount *)((char *)vm + vm->vmt_length)) {
984          if(( vm->vmt_fsid.fsid_dev == fsid->fsid_dev ) &&
985             ( vm->vmt_fsid.fsid_type == fsid->fsid_type ))
986              return(vm);
987     }
988     return((struct vmount *)NULL);
989 }
990 #endif /* _AIX */
991
992 int FileSystemSpace(const char *file_path, size_t bytes, char **fsname)
993 {
994     int                 fserror=FALSE;
995     struct stat         stat_buf;
996     size_t              req_space = 0;
997 #if !defined(linux)
998     struct statvfs      statvfs_buf;
999 #endif
1000
1001     if (stat(file_path,&stat_buf) < 0) return 0;
1002 #if !defined(linux)
1003     if (statvfs(file_path,&statvfs_buf) < 0) return 0;
1004 #endif
1005
1006 #ifdef _AIX
1007     struct statfs       statfs_buf;
1008
1009     if (statfs(file_path,&statfs_buf) < 0) return 0;
1010     if (statfs_buf.f_vfstype == MNT_NFS)
1011     {
1012         struct vmount *vm;
1013         vm = get_vmount(&(statfs_buf.f_fsid));
1014         strcpy (statfs_buf.f_fname, vmt2dataptr (vm, VMT_STUB));
1015     }
1016 #endif /* _AIX */
1017
1018     if (bytes != 0)
1019     {
1020
1021         // The following code became redundant as the writeMailBox method now
1022         // checks for No space from the SafeWritev call.
1023 #if 0
1024         // CDExc20314
1025         // This check does not work (HP, IBM, Sun return -1; DEC returns 0)
1026         // Since the calling code has already created the file and is only
1027         // check that there is enough space, we don't need to check that
1028         // there are enough inodes.
1029         //
1030         // special case where the filesystem is out of inodes.
1031         if(statvfs_buf.f_ffree < 10) fserror = TRUE; 
1032 #endif
1033
1034         if (! fserror)
1035         {
1036             req_space = (size_t) ((bytes > stat_buf.st_size) ?
1037                                   (bytes-stat_buf.st_size) :
1038                                   0);
1039 #if !defined(linux)
1040             if ( (statvfs_buf.f_bfree*statvfs_buf.f_bsize) >
1041                  (req_space + statvfs_buf.f_bsize) )
1042               return 1;
1043             else
1044               fserror = TRUE;
1045 #endif
1046         }
1047     }
1048     else fserror = TRUE;
1049
1050     if (fserror)
1051     {
1052 #ifdef _AIX
1053         *fsname = (char*) calloc(1, strlen(statfs_buf.f_fname)+1);
1054         strcpy (*fsname, statfs_buf.f_fname);
1055 #else
1056         *fsname = (char*) calloc(1, strlen(file_path)+1);
1057         strcpy (*fsname, file_path);
1058 #endif
1059         return 0;
1060     }
1061     return 1;
1062 }