This has meant very little for a long time as configure.ac just hardcoded these values depending on the current OS versions at the time. The only place where this is really 'needed' is XlationSvc.c in DtSvc so that differences between locale specifications on various versions of an OS can be accounted for. So for now, we just define those when building DtSvc. We could probably safely remove them as well with an update to the Xlate locale DB to remove ancient cruft we don't care about anymore. For various other modules, like dtlogin, dtsession, etc we just use the code that was already being used due to the hardcoded values we've had for the last 10-ish years.
1049 lines
24 KiB
C
1049 lines
24 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
*+SNOTICE
|
|
*
|
|
*
|
|
* $TOG: IO.C /main/33 1999/01/29 14:45:00 mgreess $
|
|
*
|
|
* RESTRICTED CONFIDENTIAL INFORMATION:
|
|
*
|
|
* The information in this document is subject to special
|
|
* restrictions in a confidential disclosure agreement bertween
|
|
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
|
|
* Sun's specific written approval. This documment and all copies
|
|
* and derivative works thereof must be returned or destroyed at
|
|
* Sun's request.
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
*+ENOTICE
|
|
*/
|
|
|
|
#define X_INCLUDE_TIME_H
|
|
#define X_INCLUDE_GRP_H
|
|
#define X_INCLUDE_PWD_H
|
|
#define XOS_USE_NO_LOCKING
|
|
#include <X11/Xos_r.h>
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
//
|
|
// START Order dependent for AIX
|
|
//
|
|
#include <sys/socket.h>
|
|
#if defined(_aix)
|
|
#include <sys/socketvar.h>
|
|
#if defined(BIG_ENDIAN)
|
|
#undef BIG_ENDIAN
|
|
#endif
|
|
#endif
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <arpa/inet.h>
|
|
//
|
|
// END Order dependent for AIX
|
|
//
|
|
#include <sys/stat.h>
|
|
#if !defined(__linux__)
|
|
# include <sys/statvfs.h>
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/uio.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef _AIX
|
|
#include <sys/mntctl.h>
|
|
#include <sys/statfs.h>
|
|
#include <sys/vfs.h>
|
|
#define IOVMAX MSG_MAXIOVLEN
|
|
extern "C"
|
|
{
|
|
fchmod(int, mode_t);
|
|
statfs(const char *, struct statfs *);
|
|
mntctl(int, int, char *);
|
|
ssize_t writev(int, const struct iovec *, int);
|
|
}
|
|
#endif /* _AIX */
|
|
|
|
#include <DtMail/DtMail.hh>
|
|
#include <DtMail/DtMailError.hh>
|
|
#include <DtMail/IO.hh>
|
|
#include <DtMail/Threads.hh>
|
|
|
|
#if !defined(IOV_MAX)
|
|
#if !defined(__linux__)
|
|
#include <sys/stream.h>
|
|
#endif
|
|
#if !defined(DEF_IOV_MAX)
|
|
#define DEF_IOV_MAX 16
|
|
#endif
|
|
#define IOV_MAX DEF_IOV_MAX
|
|
#endif
|
|
|
|
#define IOVEC_IOVBASE_INCREMENTOR(iov, bytes) \
|
|
((caddr_t)((size_t)iov->iov_base+bytes))
|
|
|
|
// The following I/O routines are wrappers for the normal routines,
|
|
// but they deal with EINTR, and partial read/write situations.
|
|
//
|
|
//
|
|
int
|
|
SafeOpen(const char * path, int oflag, mode_t mode)
|
|
{
|
|
int status;
|
|
|
|
do {
|
|
status = open(path, oflag, mode);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeClose(int fd)
|
|
{
|
|
int status;
|
|
do {
|
|
status = close(fd);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeLink(const char * existingPath, const char * newPath)
|
|
{
|
|
int status;
|
|
do {
|
|
status = link(existingPath, newPath);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeRename(const char * oldPath, const char * newPath)
|
|
{
|
|
int status;
|
|
do {
|
|
status = rename(oldPath, newPath);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeRemove(const char *path)
|
|
{
|
|
int status;
|
|
do {
|
|
status = remove(path);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeUnlink(const char *path)
|
|
{
|
|
int status;
|
|
do {
|
|
status = unlink(path);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
ssize_t
|
|
SafeRead(int fd, void * buf, size_t bytes)
|
|
{
|
|
ssize_t status = 0;
|
|
do {
|
|
status = read(fd, buf, bytes);
|
|
} while(status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
ssize_t
|
|
SafeWrite(int fd, const void * buf, size_t bytes)
|
|
{
|
|
ssize_t status = 0;
|
|
do {
|
|
status = write(fd, buf, bytes);
|
|
} while(status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
// SafeWritev -- safe multiply vectored write
|
|
// Description:
|
|
// SafeWritev provides an interrupt safe way to call the writev() system
|
|
// call. In addition, it removes the IOV_MAX limitation on the size of the
|
|
// iovec structure, and it will not return until either all bytes specified
|
|
// by the iovec structure are written or writev() returns an error.
|
|
// Arguments:
|
|
// int fd -- file descriptor to write to
|
|
// struct iovec *iov -- iovec structure describing writes to be done
|
|
// int iovcnt -- number of elements in passed in iov structure
|
|
// Outputs:
|
|
// Will effectively destroy the contents of the passed in iovec structure.
|
|
// The caller must deallocate the storage associated with the structure
|
|
// upon regaining control.
|
|
// Returns:
|
|
// == -1 : error returned from writev() - errno set to specific error number
|
|
// != -1 : number of bytes actually written to the file
|
|
|
|
unsigned long
|
|
SafeWritev(int fd, struct iovec *iov, int iovcnt)
|
|
{
|
|
ssize_t status;
|
|
unsigned long bytesWritten = 0;
|
|
|
|
// outer loop: starting with the first write vector, as long as there is
|
|
// at least one vector left to feed writev(), do so
|
|
//
|
|
for(int curIov = 0; curIov < iovcnt; ) {
|
|
|
|
// inner loop: feed writev() allowing for interrupted system call
|
|
do {
|
|
status = writev(
|
|
fd,
|
|
&iov[curIov],
|
|
(iovcnt-curIov) > IOV_MAX ? IOV_MAX : (iovcnt-curIov));
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
if (status == (ssize_t)-1) // true error from writev??
|
|
return((unsigned long)-1); // yes: bail at this point to caller
|
|
bytesWritten += status; // bump # bytes written count
|
|
|
|
// must now "walk through" the io vector until we are up the to point
|
|
// indicated by the number of bytes written by writev() - any leftover
|
|
// in status indicates a partial write of a vector
|
|
//
|
|
while ((status > 0) && (curIov < iovcnt) && (iov[curIov].iov_len <= status)) {
|
|
status -= iov[curIov++].iov_len;
|
|
}
|
|
|
|
// Check to see if we have reached the end of the io vector array; also
|
|
// check to see if more bytes were written than called for; as crazy as
|
|
// this sounds, in at least one instance when we finish spinning through
|
|
// the io vectors we still had bytes left that had been written but not
|
|
// accounted for in the io vectors (status > 0 && curIov >= iovcnt)
|
|
//
|
|
if (curIov >= iovcnt) { // out of IO vectors?
|
|
if (status > 0) { // yes: all data accounted for?
|
|
DtMailEnv error; // NO:: log error condition
|
|
error.logError(
|
|
DTM_TRUE,
|
|
"SafeWritev: writev(): too many bytes written (%d/%d)\n",
|
|
status, bytesWritten);
|
|
}
|
|
continue; // continue and let for loop exit
|
|
}
|
|
|
|
// Check for a partial write: if the current vector contains more data
|
|
// than what has been written, writev() bailed in the middle of writing
|
|
// a vector - adjust the vector and and feed it back to writev() again
|
|
// OTHERWISE writev() ended with the current vector so move on to the next
|
|
//
|
|
if (iov[curIov].iov_len == status) // full write of this vector?
|
|
curIov++; // yes: move on to the next vector
|
|
else if (status != 0) { // no: adjust this vector and retry
|
|
iov[curIov].iov_len -= status;
|
|
iov[curIov].iov_base = IOVEC_IOVBASE_INCREMENTOR((&iov[curIov]), status);
|
|
}
|
|
}
|
|
return(bytesWritten);
|
|
}
|
|
|
|
#define SWS_BUFFERSIZE 1024
|
|
ssize_t
|
|
SafeWriteStrip(int fd, const void * buf, size_t bytes)
|
|
{
|
|
ssize_t status = 0;
|
|
int i, j;
|
|
char *ptr = (char*)buf, *writebuf;
|
|
|
|
// bug 5856: don't write out control M
|
|
// make a finite size buffer for writing
|
|
writebuf = (char*) malloc(bytes < SWS_BUFFERSIZE ? bytes : SWS_BUFFERSIZE);
|
|
|
|
for (i = 0, j = 0; i < bytes; i++, ptr++) {
|
|
if (*ptr == '\r' && *(ptr+1) == '\n')
|
|
continue;
|
|
writebuf[j++] = *ptr;
|
|
if (j == SWS_BUFFERSIZE || i == (bytes-1)) {
|
|
do {
|
|
status = write(fd, writebuf, j);
|
|
} while(status < 0 && errno == EINTR);
|
|
j = 0;
|
|
}
|
|
}
|
|
free(writebuf);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeStat(const char * path, struct stat * buf)
|
|
{
|
|
int status;
|
|
do {
|
|
status = stat(path, buf);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeFchown(int fd, uid_t owner, gid_t group)
|
|
{
|
|
int status;
|
|
do {
|
|
status = fchown(fd, owner, group);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeLStat(const char * path, struct stat * buf)
|
|
{
|
|
int status;
|
|
do {
|
|
status = lstat(path, buf);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeFStat(int fd, struct stat * buf)
|
|
{
|
|
int status;
|
|
do {
|
|
status = fstat(fd, buf);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
// SafeGuaranteedStat - return stat info for object given path name
|
|
// If NFS attribute caching is enabled (which is the default), a
|
|
// stat/fstat of a NFS file may not return the correct true size of the
|
|
// mailbox if it has been appended to since the last time it was read.
|
|
// To get around this problem, this function will perform a open(),
|
|
// read() of 1 byte, fstat(), close() which will force the attributes
|
|
// for the named file to be retrieved directly from the server.
|
|
//
|
|
int
|
|
SafeGuaranteedStat(const char * path, struct stat * buf)
|
|
{
|
|
int saveErrno;
|
|
|
|
#ifndef O_RSYNC
|
|
int tempFd = SafeOpen(path, O_RDONLY|O_SYNC);
|
|
#else
|
|
int tempFd = SafeOpen(path, O_RDONLY|O_RSYNC|O_SYNC);
|
|
#endif /* O_RSYNC */
|
|
|
|
if (tempFd == -1) {
|
|
return(-1);
|
|
}
|
|
|
|
char tempBuf;
|
|
if (SafeRead(tempFd, &tempBuf, 1) == -1) {
|
|
saveErrno = errno;
|
|
(void) SafeClose(tempFd);
|
|
errno = saveErrno;
|
|
return(-1);
|
|
}
|
|
|
|
if (SafeFStat(tempFd, buf) == -1) {
|
|
saveErrno = errno;
|
|
(void) SafeClose(tempFd);
|
|
errno = saveErrno;
|
|
return(-1);
|
|
}
|
|
|
|
(void) SafeClose(tempFd);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
SafeTruncate(const char * path, off_t len)
|
|
{
|
|
int status;
|
|
do {
|
|
status = truncate((char *)path, len); // The cast is for AIX
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeFTruncate(int fd, off_t len)
|
|
{
|
|
int status;
|
|
do {
|
|
status = ftruncate(fd, len);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeAccess(const char * path, int amode)
|
|
{
|
|
int status;
|
|
do {
|
|
status = access(path, amode);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
#if defined(sun)
|
|
#define LOCKF_SIZE_TYPE long
|
|
#else
|
|
#define LOCKF_SIZE_TYPE off_t
|
|
#endif
|
|
|
|
int
|
|
SafeLockf(int fd, int func, long size)
|
|
{
|
|
int status;
|
|
do {
|
|
status = lockf(fd, func, (LOCKF_SIZE_TYPE) size);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeFChmod(int fd, mode_t mode)
|
|
{
|
|
int status;
|
|
do {
|
|
status = fchmod(fd, mode);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeDup2(int fd1, int fd2)
|
|
{
|
|
int status;
|
|
do {
|
|
status = dup2(fd1, fd2);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeExecvp(const char * file, char *const *argv)
|
|
{
|
|
int status;
|
|
do {
|
|
|
|
status = execvp(file, (char * const *)argv);
|
|
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
int
|
|
SafeWaitpid(pid_t proc, int * p_stat, int options)
|
|
{
|
|
pid_t status;
|
|
do {
|
|
status = waitpid(proc, p_stat, options);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return((int)status);
|
|
}
|
|
|
|
int
|
|
SafeWait(int * p_stat)
|
|
{
|
|
pid_t status;
|
|
do {
|
|
status = wait(p_stat);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return((int)status);
|
|
}
|
|
|
|
int
|
|
SafeUTime(const char * path, utimbuf * ntime)
|
|
{
|
|
int status;
|
|
do {
|
|
status = utime(path, ntime);
|
|
} while (status < 0 && errno == EINTR);
|
|
|
|
return(status);
|
|
}
|
|
|
|
void
|
|
SafePathIsAccessible(DtMailEnv &error, const char *path)
|
|
{
|
|
int status;
|
|
|
|
status = SafeAccess(path, F_OK);
|
|
if (-1 == status)
|
|
{
|
|
if (EACCES == errno)
|
|
error.vSetError(DTME_PathElementPermissions, DTM_FALSE, NULL, path);
|
|
else if (ENOTDIR == errno)
|
|
error.vSetError(DTME_PathElementNotDirectory, DTM_FALSE, NULL, path);
|
|
else if (ENOENT == errno)
|
|
{
|
|
char *s, *t;
|
|
|
|
t = strdup(path);
|
|
s = strrchr(t, '/');
|
|
if (s && s != t)
|
|
{
|
|
*s = '\0';
|
|
status = SafeAccess(t, F_OK);
|
|
if (-1 == status)
|
|
error.vSetError(
|
|
DTME_PathElementDoesNotExist,
|
|
DTM_FALSE, NULL,
|
|
path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined(POSIX_THREADS)
|
|
static void * time_mutex = NULL;
|
|
#endif
|
|
|
|
void
|
|
SafeCtime(const time_t *clock, char * buf, int buflen)
|
|
{
|
|
_Xctimeparams ctime_buf;
|
|
char *result;
|
|
|
|
memset((void*) &ctime_buf, 0, sizeof(_Xctimeparams));
|
|
result = _XCtime(clock, ctime_buf);
|
|
if (result)
|
|
strncpy(buf, result, buflen);
|
|
else
|
|
*buf = '\0';
|
|
}
|
|
|
|
void
|
|
SafeLocaltime(const time_t *clock, tm & result)
|
|
{
|
|
struct tm *time_ptr;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
memset((void*) &localtime_buf, 0, sizeof(_Xltimeparams));
|
|
time_ptr = _XLocaltime(clock, localtime_buf);
|
|
result = *time_ptr;
|
|
}
|
|
|
|
time_t
|
|
SafeMktime(tm * timeptr)
|
|
{
|
|
#if defined(POSIX_THREADS)
|
|
|
|
if (!time_mutex) {
|
|
time_mutex = MutexInit();
|
|
}
|
|
|
|
MutexLock lock_scope(time_mutex);
|
|
#endif
|
|
|
|
return(mktime(timeptr));
|
|
}
|
|
|
|
size_t
|
|
SafeStrftime(char * buf, size_t buf_size,
|
|
const char * format, const tm * timeptr)
|
|
{
|
|
#if defined(POSIX_THREADS)
|
|
|
|
if (!time_mutex) {
|
|
time_mutex = MutexInit();
|
|
}
|
|
|
|
MutexLock lock_scope(time_mutex);
|
|
#endif
|
|
|
|
return(strftime(buf, buf_size, format, timeptr));
|
|
}
|
|
|
|
#define SockINTERNAL_BUFSIZE 2048
|
|
|
|
void *SockOpen(char *host, int clientPort, char **errorstring)
|
|
{
|
|
int sockfd;
|
|
unsigned long inaddr;
|
|
struct sockaddr_in ad;
|
|
struct hostent *hp;
|
|
DtMailEnv error;
|
|
char *errorfmt = NULL;
|
|
|
|
memset(&ad, 0, sizeof(ad));
|
|
ad.sin_family = AF_INET;
|
|
|
|
inaddr = inet_addr(host);
|
|
if (inaddr != -1)
|
|
memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
|
|
else
|
|
{
|
|
hp = gethostbyname(host);
|
|
if (hp == NULL)
|
|
{
|
|
if (NULL != errorstring)
|
|
{
|
|
errorfmt = DtMailEnv::getMessageText(
|
|
SockErrorSet, 2,
|
|
"Unknown host: %s");
|
|
if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
|
|
sprintf(*errorstring, errorfmt, host);
|
|
}
|
|
return (FILE*) NULL;
|
|
}
|
|
memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
|
|
}
|
|
ad.sin_port = htons(clientPort);
|
|
|
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (sockfd < 0)
|
|
{
|
|
if (NULL != errorstring)
|
|
{
|
|
errorfmt = DtMailEnv::getMessageText(
|
|
SockErrorSet, 3,
|
|
"Error creating socket: %s");
|
|
if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
|
|
sprintf(*errorstring, errorfmt, error.errnoMessage());
|
|
}
|
|
return (FILE*) NULL;
|
|
}
|
|
if (connect(sockfd, (struct sockaddr *) &ad, sizeof(ad)) < 0)
|
|
{
|
|
if (NULL != errorstring)
|
|
{
|
|
errorfmt = DtMailEnv::getMessageText(
|
|
SockErrorSet, 3,
|
|
"Error connecting to socket: %s");
|
|
if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
|
|
sprintf(*errorstring, errorfmt, error.errnoMessage());
|
|
}
|
|
close(sockfd);
|
|
return (FILE*) NULL;
|
|
}
|
|
|
|
#if defined(USE_SOCKSTREAM)
|
|
FILE *sockfp = fdopen(sockfd, "r+");
|
|
setvbuf(sockfp, NULL, _IONBF, SockINTERNAL_BUFSIZE);
|
|
return (void*) sockfp;
|
|
#else
|
|
return (void*) sockfd;
|
|
#endif
|
|
}
|
|
|
|
int SockPrintf(void *sockfp, char* format, ...)
|
|
{
|
|
va_list ap;
|
|
char *buf = new char[8192];
|
|
int i;
|
|
|
|
va_start(ap, format);
|
|
vsprintf(buf, format, ap);
|
|
va_end(ap);
|
|
i = SockWrite(buf, 1, strlen(buf), sockfp);
|
|
delete [] buf;
|
|
return i;
|
|
}
|
|
|
|
char *SockGets(char *buf, int len, void *sockfp)
|
|
{
|
|
#if defined(USE_SOCKSTREAM)
|
|
char *in = fgets(buf, len, (FILE*) sockfp);
|
|
fseek((FILE*) sockfp, 0L, SEEK_CUR); /* required by POSIX */
|
|
return in;
|
|
#else
|
|
size_t n;
|
|
char *bufp;
|
|
|
|
n = 0;
|
|
bufp = buf-1;
|
|
do
|
|
{
|
|
bufp++;
|
|
read((int) sockfp, (void*) bufp, 1);
|
|
n++;
|
|
} while (*bufp != '\n');
|
|
*(bufp+1) = '\0';
|
|
return buf;
|
|
#endif
|
|
}
|
|
|
|
int SockRead(char *buf, int size, int len, void *sockfp)
|
|
{
|
|
#if defined(USE_SOCKSTREAM)
|
|
int n = fread(buf, size, len, (FILE*) sockfp);
|
|
fseek((FILE*) sockfp, 0L, SEEK_CUR); /* required by POSIX */
|
|
#else
|
|
int n = (int) read((int) sockfp, (void*) buf, (size_t) size * len);
|
|
#endif
|
|
return n;
|
|
}
|
|
|
|
int SockWrite(char *buf, int size, int len, void *sockfp)
|
|
{
|
|
int n;
|
|
|
|
#if defined(USE_SOCKSTREAM)
|
|
n = fwrite(buf, size, len, (FILE*) sockfp);
|
|
fseek((FILE*) sockfp, 0L, SEEK_CUR); /* required by POSIX */
|
|
#else
|
|
n = write((int) sockfp, buf, size * len);
|
|
#endif
|
|
|
|
return n;
|
|
}
|
|
|
|
void SockClose(void *sockfp)
|
|
{
|
|
#if defined(USE_SOCKSTREAM)
|
|
fclose((FILE*) sockfp);
|
|
#else
|
|
close((int) sockfp);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
GetGroupName(char * grp_name)
|
|
{
|
|
struct group *grp;
|
|
_Xgetgrparams grp_buf;
|
|
|
|
memset((void*) &grp_buf, 0, sizeof(_Xgetgrparams));
|
|
grp = _XGetgrgid(getegid(), grp_buf);
|
|
|
|
if (grp) {
|
|
strcpy(grp_name, grp->gr_name);
|
|
}
|
|
else {
|
|
strcpy(grp_name, "UNKNOWN_GROUP");
|
|
}
|
|
|
|
}
|
|
|
|
gid_t
|
|
GetIdForGroupName(char * grp_name)
|
|
{
|
|
assert(grp_name != NULL);
|
|
struct group *grp;
|
|
_Xgetgrparams grp_buf;
|
|
|
|
memset((void*) &grp_buf, 0, sizeof(_Xgetgrparams));
|
|
grp = _XGetgrnam(grp_name, grp_buf);
|
|
|
|
return(grp ? grp->gr_gid : (gid_t)-1);
|
|
}
|
|
|
|
void
|
|
GetPasswordEntry(passwd & result)
|
|
{
|
|
static struct passwd passwordEntry;
|
|
static int oneTimeFlag = 0;
|
|
|
|
if (!oneTimeFlag) {
|
|
_Xgetpwparams pw_buf;
|
|
struct passwd *tresult;
|
|
|
|
memset((void*) &pw_buf, 0, sizeof(_Xgetpwparams));
|
|
#if defined(_AIX)
|
|
_Xos_processLock;
|
|
tresult = getpwuid(getuid());
|
|
_Xos_processUnlock;
|
|
#else
|
|
tresult = _XGetpwuid(getuid(), pw_buf);
|
|
#endif
|
|
|
|
assert(tresult != NULL);
|
|
memcpy(&passwordEntry, tresult, sizeof(struct passwd));
|
|
passwordEntry.pw_name = strdup(passwordEntry.pw_name);
|
|
passwordEntry.pw_passwd = strdup(passwordEntry.pw_passwd);
|
|
#if !defined(_AIX) && !defined(__linux__) && !defined(CSRG_BASED)
|
|
passwordEntry.pw_age = strdup(passwordEntry.pw_age);
|
|
passwordEntry.pw_comment = strdup(passwordEntry.pw_comment);
|
|
#endif
|
|
passwordEntry.pw_gecos = strdup(passwordEntry.pw_gecos);
|
|
passwordEntry.pw_dir = strdup(passwordEntry.pw_dir);
|
|
passwordEntry.pw_shell = strdup(passwordEntry.pw_shell);
|
|
oneTimeFlag++;
|
|
}
|
|
|
|
memcpy(&result, &passwordEntry, sizeof(struct passwd));
|
|
return;
|
|
}
|
|
#if defined(MAILGROUP_REQUIRED)
|
|
int isSetMailGidNeeded(const char * mailboxPath)
|
|
{
|
|
|
|
assert(mailboxPath);
|
|
|
|
char inbox_path[1024];
|
|
char mbox_path[1024];
|
|
struct passwd *pw;
|
|
struct stat buf;
|
|
struct stat buf1;
|
|
_Xgetpwparams pw_buf;
|
|
|
|
memset((void*) &pw_buf, 0, sizeof(_Xgetpwparams));
|
|
pw = _XGetpwuid(getuid(), pw_buf);
|
|
|
|
// construct the lockfile name for the user.
|
|
char *lock_file = (char *)calloc(1,strlen(pw->pw_name) + 6);
|
|
strcpy(lock_file,pw->pw_name);
|
|
strcat(lock_file,".lock");
|
|
|
|
// parse the mailfolder name from the path
|
|
char *p = strrchr(mailboxPath,'/');
|
|
int len = (NULL!=0) ? strlen(mailboxPath)-strlen(p) : strlen(mailboxPath);
|
|
char *str = (char *) calloc(1, len+1);
|
|
strncpy(str, mailboxPath, len);
|
|
str[len] = '\0';
|
|
|
|
stat(str,&buf);
|
|
|
|
// Default or system mailbox dir name.
|
|
strcpy(inbox_path, "/var/spool/mail");
|
|
stat(inbox_path,&buf1);
|
|
free(str);
|
|
|
|
if( ( (buf.st_dev == buf1.st_dev) && (buf.st_ino == buf1.st_ino) ) )
|
|
{
|
|
if( !strcmp((p+1),pw->pw_name) || !strcmp((p+1),lock_file) )
|
|
{
|
|
if( access(mailboxPath,R_OK) == -1 )
|
|
{
|
|
free(lock_file);
|
|
return (1);
|
|
}
|
|
}
|
|
free(lock_file);
|
|
return ( 0 );
|
|
}
|
|
else
|
|
{
|
|
free(lock_file);
|
|
return ( 1 );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _AIX
|
|
/*
|
|
* NAME: get_stat
|
|
*
|
|
* FUNCTION:
|
|
* gather mount status for all virtual mounts for this host.
|
|
*
|
|
* EXECUTION ENVIRONMENT: Part of user command.
|
|
*
|
|
* ON ENTRY:
|
|
* vmountpp pointer to a buffer in which to put mount info
|
|
*
|
|
* NOTES:
|
|
* get_stat() was lifted and slightly modified from
|
|
* AIX Version 3 df.c.
|
|
*
|
|
* RETURNS:
|
|
* < 0 error in mntctl()
|
|
* > 0 for number of struct vmounts (mount points) in
|
|
* buffer which is pointed to by pointer left at
|
|
* *vmountpp.
|
|
*/
|
|
int get_stat(
|
|
struct vmount **vmountpp) /* place to tell where buffer is */
|
|
{
|
|
size_t size;
|
|
struct vmount *vm;
|
|
int nmounts;
|
|
int count;
|
|
|
|
size = BUFSIZ; /* initial default size */
|
|
count = 10; /* don't try forever */
|
|
|
|
while (count--) { /* don't try it forever */
|
|
if ((vm = (struct vmount*) malloc(size)) == NULL) {
|
|
return(-1);
|
|
}
|
|
|
|
/*
|
|
* perform the QUERY mntctl - if it returns > 0, that is the
|
|
* number of vmount structures in the buffer. If it returns
|
|
* -1, an error occurred. If it returned 0, then look in
|
|
* first word of buffer for needed size.
|
|
*/
|
|
if ((nmounts = mntctl(MCTL_QUERY, size, (caddr_t)vm)) > 0) {
|
|
*vmountpp = vm; /* OK, got it, now return */
|
|
return(nmounts);
|
|
} else {
|
|
if (nmounts == 0) {
|
|
size = *(int *)vm; /* the buffer wasn't big enough */
|
|
free((void *)vm); /* get required buffer size */
|
|
} else {
|
|
free((void *)vm);/* some other kind of error occurred*/
|
|
return(-1);
|
|
}
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/*
|
|
* NAME: get_vmount
|
|
*
|
|
* FUNCTION:
|
|
* Determines, via the filesystems vmount structures,
|
|
* the vmount id of the the filesystem id provided as
|
|
* an argument (enables ultimate access to the actual
|
|
* name of the filesystem).
|
|
*
|
|
* EXECUTION ENVIRONMENT: Part of user command.
|
|
*
|
|
* RETURNS:
|
|
* ptr to structure with vmount id of filesystem or NULL
|
|
*/
|
|
struct vmount *get_vmount(fsid_t *fsid)
|
|
{
|
|
struct vmount *inu_vmount_p=NULL;
|
|
int inu_vmount_num;
|
|
struct vmount *vm;
|
|
int nmount;
|
|
|
|
/* make sure we have all the virtual mount status of this host */
|
|
if(inu_vmount_p == NULL)
|
|
inu_vmount_num = get_stat(&inu_vmount_p);
|
|
|
|
/* get the number of struct vmount in the vmount buffer */
|
|
nmount = inu_vmount_num;
|
|
|
|
/* go thru all the structures in the vmount buffer */
|
|
for (vm = inu_vmount_p; nmount; nmount--,
|
|
vm = (struct vmount *)((char *)vm + vm->vmt_length)) {
|
|
if(( vm->vmt_fsid.fsid_dev == fsid->fsid_dev ) &&
|
|
( vm->vmt_fsid.fsid_type == fsid->fsid_type ))
|
|
return(vm);
|
|
}
|
|
return((struct vmount *)NULL);
|
|
}
|
|
#endif /* _AIX */
|
|
|
|
int FileSystemSpace(const char *file_path, size_t bytes, char **fsname)
|
|
{
|
|
int fserror=FALSE;
|
|
struct stat stat_buf;
|
|
size_t req_space = 0;
|
|
#if !defined(__linux__)
|
|
struct statvfs statvfs_buf;
|
|
#endif
|
|
|
|
if (stat(file_path,&stat_buf) < 0) return 0;
|
|
#if !defined(__linux__)
|
|
if (statvfs(file_path,&statvfs_buf) < 0) return 0;
|
|
#endif
|
|
|
|
#ifdef _AIX
|
|
struct statfs statfs_buf;
|
|
|
|
if (statfs(file_path,&statfs_buf) < 0) return 0;
|
|
if (statfs_buf.f_vfstype == MNT_NFS)
|
|
{
|
|
struct vmount *vm;
|
|
vm = get_vmount(&(statfs_buf.f_fsid));
|
|
strcpy (statfs_buf.f_fname, vmt2dataptr (vm, VMT_STUB));
|
|
}
|
|
#endif /* _AIX */
|
|
|
|
if (bytes != 0)
|
|
{
|
|
|
|
// The following code became redundant as the writeMailBox method now
|
|
// checks for No space from the SafeWritev call.
|
|
#if 0
|
|
// CDExc20314
|
|
// This check does not work (HP, IBM, Sun return -1; DEC returns 0)
|
|
// Since the calling code has already created the file and is only
|
|
// check that there is enough space, we don't need to check that
|
|
// there are enough inodes.
|
|
//
|
|
// special case where the filesystem is out of inodes.
|
|
if(statvfs_buf.f_ffree < 10) fserror = TRUE;
|
|
#endif
|
|
|
|
if (! fserror)
|
|
{
|
|
req_space = (size_t) ((bytes > stat_buf.st_size) ?
|
|
(bytes-stat_buf.st_size) :
|
|
0);
|
|
#if !defined(__linux__)
|
|
if ( (statvfs_buf.f_bfree*statvfs_buf.f_bsize) >
|
|
(req_space + statvfs_buf.f_bsize) )
|
|
return 1;
|
|
else
|
|
fserror = TRUE;
|
|
#endif
|
|
}
|
|
}
|
|
else fserror = TRUE;
|
|
|
|
if (fserror)
|
|
{
|
|
#ifdef _AIX
|
|
*fsname = (char*) calloc(1, strlen(statfs_buf.f_fname)+1);
|
|
strcpy (*fsname, statfs_buf.f_fname);
|
|
#else
|
|
*fsname = (char*) calloc(1, strlen(file_path)+1);
|
|
strcpy (*fsname, file_path);
|
|
#endif
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|