blob: 6791744e200b29d0f4c07ee22cda71d16f29b320 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// Process-related Info
// Date: Wed Apr 11 14:35:56 CST 2018
#include <fcntl.h> // open
#include <stdio.h> // snprintf
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h> // read, gitpid
#include <sstream> // std::ostringstream
#include "butil/fd_guard.h" // butil::fd_guard
#include "butil/logging.h"
#include "butil/popen.h" // read_command_output
#include "butil/process_util.h"
#if defined(OS_MACOSX)
#include <libproc.h> // proc_pidpath
#endif
namespace butil {
ssize_t ReadCommandLine(char* buf, size_t len, bool with_args) {
#if defined(OS_LINUX)
butil::fd_guard fd(open("/proc/self/cmdline", O_RDONLY));
if (fd < 0) {
LOG(ERROR) << "Fail to open /proc/self/cmdline";
return -1;
}
ssize_t nr = read(fd, buf, len);
if (nr <= 0) {
LOG(ERROR) << "Fail to read /proc/self/cmdline";
return -1;
}
#elif defined(OS_MACOSX)
static pid_t pid = getpid();
std::ostringstream oss;
char cmdbuf[32];
snprintf(cmdbuf, sizeof(cmdbuf), "ps -p %ld -o command=", (long)pid);
if (butil::read_command_output(oss, cmdbuf) != 0) {
LOG(ERROR) << "Fail to read cmdline";
return -1;
}
const std::string& result = oss.str();
ssize_t nr = std::min(result.size(), len);
memcpy(buf, result.data(), nr);
#else
#error Not Implemented
#endif
if (with_args) {
if ((size_t)nr == len) {
return len;
}
for (ssize_t i = 0; i < nr; ++i) {
if (buf[i] == '\0') {
buf[i] = '\n';
}
}
return nr;
} else {
for (ssize_t i = 0; i < nr; ++i) {
// The command in macos is separated with space and ended with '\n'
if (buf[i] == '\0' || buf[i] == '\n' || buf[i] == ' ') {
return i;
}
}
if ((size_t)nr == len) {
LOG(ERROR) << "buf is not big enough";
return -1;
}
return nr;
}
}
ssize_t GetProcessAbsolutePath(char *buf, size_t len) {
#if defined(OS_LINUX)
memset(buf, 0, len);
ssize_t nr = readlink("/proc/self/exe", buf, len);
return nr;
#elif defined(OS_MACOSX)
memset(buf, 0, len);
int ret = proc_pidpath(getpid(), buf, len);
return ret;
#endif
}
} // namespace butil