/* Copyright (C) 2009 RedHat inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "abrtlib.h" static char *append_escaped(char *start, const char *s) { char hex_char_buf[] = "\\x00"; char *dst = start; const unsigned char *p = (unsigned char *)s; while (1) { const unsigned char *old_p = p; while (*p > ' ' && *p <= 0x7e && *p != '\"' && *p != '\'' && *p != '\\') p++; if (dst == start) { if (p != (unsigned char *)s && *p == '\0') { /* entire word does not need escaping and quoting */ strcpy(dst, s); dst += strlen(s); return dst; } *dst++ = '\''; } strncpy(dst, (char *)old_p, (p - old_p)); dst += (p - old_p); if (*p == '\0') { *dst++ = '\''; *dst = '\0'; return dst; } const char *a; switch (*p) { case '\r': a = "\\r"; break; case '\n': a = "\\n"; break; case '\t': a = "\\t"; break; case '\'': a = "\\\'"; break; case '\"': a = "\\\""; break; case '\\': a = "\\\\"; break; case ' ': a = " "; break; default: hex_char_buf[2] = "0123456789abcdef"[*p >> 4]; hex_char_buf[3] = "0123456789abcdef"[*p & 0xf]; a = hex_char_buf; } strcpy(dst, a); dst += strlen(a); p++; } } static char* get_escaped(const char *path, char separator) { unsigned total_esc_len = 0; char *escaped = NULL; int fd = open(path, O_RDONLY); if (fd >= 0) { while (1) { /* read and escape one block */ char buffer[4 * 1024 + 1]; int len = read(fd, buffer, sizeof(buffer) - 1); if (len <= 0) break; buffer[len] = '\0'; escaped = xrealloc(escaped, total_esc_len + (len+1) * 4); char *src = buffer; char *dst = escaped + total_esc_len; while (1) { /* escape till next '\0' char */ char *d = append_escaped(dst, src); total_esc_len += (d - dst); dst = d; src += strlen(src) + 1; if ((src - buffer) >= len) break; *dst++ = separator; } *dst = '\0'; } close(fd); } return escaped; } char* get_cmdline(pid_t pid) { char path[sizeof("/proc/%lu/cmdline") + sizeof(long)*3]; sprintf(path, "/proc/%lu/cmdline", (long)pid); return get_escaped(path, ' '); } char* get_environ(pid_t pid) { char path[sizeof("/proc/%lu/environ") + sizeof(long)*3]; sprintf(path, "/proc/%lu/environ", (long)pid); char *e = get_escaped(path, '\n'); /* Append last '\n' if needed */ if (e && e[0]) { unsigned len = strlen(e); if (e[len-1] != '\n') { e = xrealloc(e, len + 2); e[len] = '\n'; e[len+1] = '\0'; } } return e; }