sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, const void* pBuffer, sal_Int32 BytesToSend) { int nRet=0; OSL_ASSERT(pPipe); if ( pPipe == 0 ) { OSL_TRACE("osl_sendPipe : Invalid socket"); errno=EINVAL; return -1; } nRet = send(pPipe->m_Socket, (sal_Char*)pBuffer, BytesToSend, 0); if ( nRet <= 0 ) { OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno)); } return nRet; }
void _imp_getProcessLocale( rtl_Locale ** ppLocale ) { static char *locale = NULL; /* basic thread safeness */ // pthread_mutex_lock( &aLocalMutex ); /* Only fetch the locale once and cache it */ if ( NULL == locale ) { locale = (char *)malloc( 128 ); if ( locale ) macosx_getLocale( locale, 128 ); else fprintf( stderr, "nlsupport.c: locale allocation returned NULL!\n" ); } /* handle the case where OS specific method of finding locale fails */ if ( NULL == locale ) { /* simulate behavior of setlocale */ locale = getenv( "LC_ALL" ); if( NULL == locale ) locale = getenv( "LC_CTYPE" ); if( NULL == locale ) locale = getenv( "LANG" ); if( NULL == locale ) locale = "C"; } /* return the locale */ *ppLocale = _parse_locale( locale ); setenv( "LC_ALL", locale, 1); setenv("LC_CTYPE", locale, 1 ); setenv("LANG", locale, 1 ); #if OSL_DEBUG_LEVEL > 1 OSL_TRACE("_imp_getProcessLocale() returning %s as current locale.", locale ); #endif // pthread_mutex_unlock( &aLocalMutex ); }
oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) { int s, flags; oslPipe pAcceptedPipe; OSL_ASSERT(pPipe); if ( pPipe == 0 ) { return NULL; } OSL_ASSERT(strlen(pPipe->m_Name) > 0); #if defined(LINUX) pPipe->m_bIsAccepting = sal_True; #endif s = accept(pPipe->m_Socket, NULL, NULL); #if defined(LINUX) pPipe->m_bIsAccepting = sal_False; #endif if (s < 0) { OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno)); return NULL; } #if defined(LINUX) if ( pPipe->m_bIsInShutdown ) { close(s); return NULL; } #endif /* LINUX */ else { /* alloc memory */ pAcceptedPipe = __osl_createPipeImpl(); OSL_ASSERT(pAcceptedPipe); if(pAcceptedPipe==NULL) { close(s); return NULL; } /* set close-on-exec flag */ if (!((flags = fcntl(s, F_GETFD, 0)) < 0)) { flags |= FD_CLOEXEC; if (fcntl(s, F_SETFD, flags) < 0) { OSL_TRACE("osl_acceptPipe: error changing socket flags. " "Errno: %d; %s",errno,strerror(errno)); } } pAcceptedPipe->m_Socket = s; } return pAcceptedPipe; }
void SAL_CALL osl_closePipe( oslPipe pPipe ) { int nRet; #if defined(LINUX) size_t len; struct sockaddr_un addr; int fd; #endif int ConnFD; if( ! pPipe ) { return; } if( pPipe->m_bClosed ) { return; } ConnFD = pPipe->m_Socket; /* Thread does not return from accept on linux, so connect to the accepting pipe */ #if defined(LINUX) if ( pPipe->m_bIsAccepting ) { pPipe->m_bIsInShutdown = sal_True; pPipe->m_Socket = -1; fd = socket(AF_UNIX, SOCK_STREAM, 0); if ( fd < 0 ) { OSL_TRACE("socket in osl_destroyPipe failed with error: %s", strerror(errno)); return; } memset(&addr, 0, sizeof(addr)); OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, pPipe->m_Name, sizeof(addr.sun_path) - 1); len = sizeof(addr); nRet = connect( fd, (struct sockaddr *)&addr, len); if ( nRet < 0 ) { OSL_TRACE("connect in osl_destroyPipe failed with error: %s", strerror(errno)); } close(fd); } #endif /* LINUX */ nRet = shutdown(ConnFD, 2); if ( nRet < 0 ) { OSL_TRACE("shutdown in destroyPipe failed : '%s'",strerror(errno)); } nRet = close(ConnFD); if ( nRet < 0 ) { OSL_TRACE("close in destroyPipe failed : '%s'",strerror(errno)); } /* remove filesystem entry */ if ( strlen(pPipe->m_Name) > 0 ) { unlink(pPipe->m_Name); } pPipe->m_bClosed = sal_True; /* OSL_TRACE("Out osl_destroyPipe"); */ }
oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security) { int Flags; size_t len; struct sockaddr_un addr; sal_Char name[PATH_MAX + 1]; size_t nNameLength = 0; int bNameTooLong = 0; oslPipe pPipe; if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0) { strncpy(name, PIPEDEFAULTPATH, sizeof(name)); } else if (access(PIPEALTERNATEPATH, R_OK|W_OK) == 0) { strncpy(name, PIPEALTERNATEPATH, sizeof(name)); } else if (!cpyBootstrapSocketPath (name, sizeof (name))) { return NULL; } name[sizeof(name) - 1] = '\0'; // ensure the string is NULL-terminated nNameLength = strlen(name); bNameTooLong = nNameLength > sizeof(name) - 2; if (!bNameTooLong) { size_t nRealLength = 0; strcat(name, "/"); ++nNameLength; if (Security) { sal_Char Ident[256]; Ident[0] = '\0'; OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident))); nRealLength = snprintf(&name[nNameLength], sizeof(name) - nNameLength, SECPIPENAMEMASK, Ident, pszPipeName); } else { nRealLength = snprintf(&name[nNameLength], sizeof(name) - nNameLength, PIPENAMEMASK, pszPipeName); } bNameTooLong = nRealLength > sizeof(name) - nNameLength - 1; } if (bNameTooLong) { OSL_TRACE("osl_createPipe: pipe name too long"); return NULL; } /* alloc memory */ pPipe = __osl_createPipeImpl(); if (pPipe == NULL) { OSL_TRACE("__osl_createPipe socket failed"); return NULL; } /* create socket */ pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0); if ( pPipe->m_Socket < 0 ) { OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s",errno, strerror(errno)); __osl_destroyPipeImpl(pPipe); return NULL; } /* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/ /* set close-on-exec flag */ if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1) { Flags |= FD_CLOEXEC; if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1) { OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s",errno,strerror(errno)); } } memset(&addr, 0, sizeof(addr)); OSL_TRACE("osl_createPipe : Pipe Name '%s'",name); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, name, sizeof(addr.sun_path) - 1); #if defined(FREEBSD) len = SUN_LEN(&addr); #else len = sizeof(addr); #endif if ( Options & osl_Pipe_CREATE ) { struct stat status; /* check if there exists an orphan filesystem entry */ if ( ( stat(name, &status) == 0) && ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) ) { if ( connect(pPipe->m_Socket,(struct sockaddr *)&addr,len) >= 0 ) { OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s",errno,strerror(errno)); close (pPipe->m_Socket); __osl_destroyPipeImpl(pPipe); return NULL; } unlink(name); } /* ok, fs clean */ if ( bind(pPipe->m_Socket, (struct sockaddr *)&addr, len) < 0 ) { OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s",errno,strerror(errno)); close (pPipe->m_Socket); __osl_destroyPipeImpl(pPipe); return NULL; } /* Only give access to all if no security handle was specified, otherwise security depends on umask */ if ( !Security ) chmod(name,S_IRWXU | S_IRWXG |S_IRWXO); strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name) - 1); if ( listen(pPipe->m_Socket, 5) < 0 ) { OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s",errno,strerror(errno)); unlink(name); /* remove filesystem entry */ close (pPipe->m_Socket); __osl_destroyPipeImpl(pPipe); return NULL; } return (pPipe); } else { /* osl_pipe_OPEN */ if ( access(name, F_OK) != -1 ) { if ( connect( pPipe->m_Socket, (struct sockaddr *)&addr, len) >= 0 ) { return (pPipe); } OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s",errno,strerror(errno)); } close (pPipe->m_Socket); __osl_destroyPipeImpl(pPipe); return NULL; } }
static void ChildStatusProc(void *pData) { pid_t pid = -1; int status = 0; int channel[2]; ProcessData data; ProcessData *pdata; int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 }; pdata = (ProcessData *)pData; /* make a copy of our data, because forking will only copy our local stack of the thread, so the process data will not be accessible in our child process */ memcpy(&data, pData, sizeof(data)); if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == -1) status = errno; fcntl(channel[0], F_SETFD, FD_CLOEXEC); fcntl(channel[1], F_SETFD, FD_CLOEXEC); /* Create redirected IO pipes */ if ( status == 0 && data.m_pInputWrite ) if (pipe( stdInput ) == -1) status = errno; if ( status == 0 && data.m_pOutputRead ) if (pipe( stdOutput ) == -1) status = errno; if ( status == 0 && data.m_pErrorRead ) if (pipe( stdError ) == -1) status = errno; if ( (status == 0) && ((pid = fork()) == 0) ) { /* Child */ int chstatus = 0; sal_Int32 nWrote; if (channel[0] != -1) close(channel[0]); if ((data.m_uid != (uid_t)-1) && ((data.m_uid != getuid()) || (data.m_gid != getgid()))) { OSL_ASSERT(geteuid() == 0); /* must be root */ if (! INIT_GROUPS(data.m_name, data.m_gid) || (setuid(data.m_uid) != 0)) OSL_TRACE("Failed to change uid and guid, errno=%d (%s)\n", errno, strerror(errno)); #if defined(LINUX) || defined (FREEBSD) unsetenv("HOME"); #else putenv("HOME="); #endif } if (data.m_pszDir) chstatus = chdir(data.m_pszDir); if (chstatus == 0 && ((data.m_uid == (uid_t)-1) || ((data.m_uid == getuid()) && (data.m_gid == getgid())))) { int i; for (i = 0; data.m_pszEnv[i] != NULL; i++) { if (strchr(data.m_pszEnv[i], '=') == NULL) { unsetenv(data.m_pszEnv[i]); /*TODO: check error return*/ } else { putenv(data.m_pszEnv[i]); /*TODO: check error return*/ } } OSL_TRACE("ChildStatusProc : starting '%s'",data.m_pszArgs[0]); /* Connect std IO to pipe ends */ /* Write end of stdInput not used in child process */ if (stdInput[1] != -1) close( stdInput[1] ); /* Read end of stdOutput not used in child process */ if (stdOutput[0] != -1) close( stdOutput[0] ); /* Read end of stdError not used in child process */ if (stdError[0] != -1) close( stdError[0] ); /* Redirect pipe ends to std IO */ if ( stdInput[0] != STDIN_FILENO ) { dup2( stdInput[0], STDIN_FILENO ); if (stdInput[0] != -1) close( stdInput[0] ); } if ( stdOutput[1] != STDOUT_FILENO ) { dup2( stdOutput[1], STDOUT_FILENO ); if (stdOutput[1] != -1) close( stdOutput[1] ); } if ( stdError[1] != STDERR_FILENO ) { dup2( stdError[1], STDERR_FILENO ); if (stdError[1] != -1) close( stdError[1] ); } pid=execv(data.m_pszArgs[0], (sal_Char **)data.m_pszArgs); } OSL_TRACE("Failed to exec, errno=%d (%s)\n", errno, strerror(errno)); OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]); /* if we reach here, something went wrong */ nWrote = write(channel[1], &errno, sizeof(errno)); if (nWrote != sizeof(errno)) OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno)); if (channel[1] != -1) close(channel[1]); _exit(255); } else { /* Parent */ int i = -1; if (channel[1] != -1) close(channel[1]); /* Close unused pipe ends */ if (stdInput[0] != -1) close( stdInput[0] ); if (stdOutput[1] != -1) close( stdOutput[1] ); if (stdError[1] != -1) close( stdError[1] ); if (pid > 0) { while (((i = read(channel[0], &status, sizeof(status))) < 0)) { if (errno != EINTR) break; } } if (channel[0] != -1) close(channel[0]); if ((pid > 0) && (i == 0)) { pid_t child_pid; osl_acquireMutex(ChildListMutex); pdata->m_pProcImpl->m_pid = pid; pdata->m_pProcImpl->m_pnext = ChildList; ChildList = pdata->m_pProcImpl; /* Store used pipe ends in data structure */ if ( pdata->m_pInputWrite ) *(pdata->m_pInputWrite) = osl_createFileHandleFromFD( stdInput[1] ); if ( pdata->m_pOutputRead ) *(pdata->m_pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] ); if ( pdata->m_pErrorRead ) *(pdata->m_pErrorRead) = osl_createFileHandleFromFD( stdError[0] ); osl_releaseMutex(ChildListMutex); osl_setCondition(pdata->m_started); do { child_pid = waitpid(pid, &status, 0); } while ( 0 > child_pid && EINTR == errno ); if ( child_pid < 0) { OSL_TRACE("Failed to wait for child process, errno=%d (%s)\n", errno, strerror(errno)); /* We got an other error than EINTR. Anyway we have to wake up the waiting thread under any circumstances */ child_pid = pid; } if ( child_pid > 0 ) { oslProcessImpl* pChild; osl_acquireMutex(ChildListMutex); pChild = ChildList; /* check if it is one of our child processes */ while (pChild != NULL) { if (pChild->m_pid == child_pid) { if (WIFEXITED(status)) pChild->m_status = WEXITSTATUS(status); else pChild->m_status = -1; osl_setCondition(pChild->m_terminated); } pChild = pChild->m_pnext; } osl_releaseMutex(ChildListMutex); } } else { OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]); OSL_TRACE("Failed to launch child process, child reports errno=%d (%s)\n", status, strerror(status)); /* Close pipe ends */ if ( pdata->m_pInputWrite ) *pdata->m_pInputWrite = NULL; if ( pdata->m_pOutputRead ) *pdata->m_pOutputRead = NULL; if ( pdata->m_pErrorRead ) *pdata->m_pErrorRead = NULL; if (stdInput[1] != -1) close( stdInput[1] ); if (stdOutput[0] != -1) close( stdOutput[0] ); if (stdError[0] != -1) close( stdError[0] ); //if pid > 0 then a process was created, even if it later failed //e.g. bash searching for a command to execute, and we still //need to clean it up to avoid "defunct" processes if (pid > 0) { pid_t child_pid; do { child_pid = waitpid(pid, &status, 0); } while ( 0 > child_pid && EINTR == errno ); } /* notify (and unblock) parent thread */ osl_setCondition(pdata->m_started); } } }
static oslSocket receiveFdPipe(int PipeFD) { oslSocket pSocket = 0; struct msghdr msghdr; struct iovec iov[1]; char buffer[2]; sal_Int32 nRead; int newfd=-1; int nRetCode=0; /* char *ptr; */ #if defined(IOCHANNEL_TRANSFER_BSD) OSL_TRACE("IOCHANNEL_TRANSFER_BSD receive\n"); iov[0].iov_base = buffer; iov[0].iov_len = sizeof(buffer); msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = iov; msghdr.msg_iovlen = 1; msghdr.msg_accrights = (caddr_t) &newfd; /* addr of descriptor */ msghdr.msg_accrightslen = sizeof(int); /* receive 1 descriptor */ #else struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN); OSL_TRACE(" !!!! IOCHANNEL_TRANSFER_BSD_RENO receive"); iov[0].iov_base = buffer; iov[0].iov_len = sizeof(buffer); msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = iov; msghdr.msg_iovlen = 1; msghdr.msg_control = (caddr_t) cmptr; msghdr.msg_controllen = CONTROLLEN; #endif #if defined(IOCHANNEL_TRANSFER_BSD) if ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 ) { OSL_TRACE("receiveFdPipe : received '%i' bytes\n",nRead); } #else if ( ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 ) && ( msghdr.msg_controllen == CONTROLLEN ) ) { OSL_TRACE("receiveFdPipe : received '%i' bytes\n",nRead); memcpy(&newfd, CMSG_DATA(cmptr), sizeof(int)); } #endif else { OSL_TRACE("receiveFdPipe : receiving failed (%s)",strerror(errno)); } if ( newfd >= 0 ) { pSocket = __osl_createSocketImpl(newfd); nRetCode=1; OSL_TRACE("received fd %i\n",newfd); } OSL_TRACE("receiveFdPipe : writing back %i",nRetCode); nRead=write(PipeFD,&nRetCode,sizeof(nRetCode)); #if defined(IOCHANNEL_TRANSFER_BSD_RENO) free(cmptr); #endif return pSocket; }
static sal_Bool sendFdPipe(int PipeFD, int SocketFD) { sal_Bool bRet = sal_False; struct iovec iov[1]; struct msghdr msg; char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */ int nSend; int RetCode=0; #if defined(IOCHANNEL_TRANSFER_BSD) OSL_TRACE("IOCHANNEL_TRANSFER_BSD send"); /* OSL_TRACE("sending fd %i\n",SocketFD); */ iov[0].iov_base = buf; iov[0].iov_len = sizeof(buf); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_accrights = (caddr_t) &SocketFD; /* addr of descriptor */ msg.msg_accrightslen = sizeof(int); /* pass 1 descriptor */ buf[1] = 0; /* zero status means OK */ buf[0] = 0; /* null byte flag to recv_fd() */ #else struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN); OSL_TRACE("!!!!!! IOCHANNEL_TRANSFER_BSD_RENO send"); /* OSL_TRACE("sending fd %i\n",SocketFD); */ iov[0].iov_base = buf; iov[0].iov_len = sizeof(buf); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = (caddr_t) cmptr; msg.msg_controllen = CONTROLLEN; cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CONTROLLEN; memcpy(CMSG_DATA(cmptr), &SocketFD, sizeof(int)); #endif if ( ( nSend = sendmsg(PipeFD, &msg, 0) ) > 0 ) { bRet = sal_True; OSL_TRACE("sendFdPipe : send '%i' bytes\n",nSend); } else { OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno)); } nSend=read(PipeFD,&RetCode,sizeof(RetCode)); if ( nSend > 0 && RetCode == 1 ) { OSL_TRACE("sendFdPipe : resource was received\n"); } else { OSL_TRACE("sendFdPipe : resource wasn't received\n"); } #if defined(IOCHANNEL_TRANSFER_BSD_RENO) free(cmptr); #endif return bRet; }