#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
+#include <pwd.h>
#include <apr_getopt.h>
Run(socket, code.c_str(), code.size(), fout, expand);
}
-static void Console(int socket) {
+static void Console(apr_pool_t *pool, int socket) {
+ passwd *passwd;
+ if (const char *username = getenv("LOGNAME"))
+ passwd = getpwnam(username);
+ else
+ passwd = getpwuid(getuid());
+
+ const char *basedir(apr_psprintf(pool, "%s/.cycript", passwd->pw_dir));
+ const char *histfile(apr_psprintf(pool, "%s/history", basedir));
+ size_t histlines(0);
+
+ mkdir(basedir, 0700);
+ read_history(histfile);
+
bool bypass(false);
bool debug(false);
bool expand(false);
fflush(fout);
}
add_history(line);
+ ++histlines;
goto restart;
}
}
std::cerr << error->message_ << std::endl;
add_history(command.c_str());
+ ++histlines;
goto restart;
}
}
}
add_history(command.c_str());
+ ++histlines;
if (debug)
std::cout << code << std::endl;
Run(socket, code, fout, expand);
}
+ _syscall(close(_syscall(open(histfile, O_CREAT | O_WRONLY, 0600))));
+ append_history(histlines, histfile);
+
fputs("\n", fout);
fflush(fout);
}
return base;
}
-int main(int argc, char const * const argv[], char const * const envp[]) {
- _aprcall(apr_app_initialize(&argc, &argv, &envp));
+void InjectLibrary(pid_t pid);
+int Main(int argc, char const * const argv[], char const * const envp[]) {
bool tty(isatty(STDIN_FILENO));
bool compile(false);
fprintf(stderr,
"usage: cycript [-c]"
#ifdef CY_ATTACH
- " [-p <pid>]"
+ " [-p <pid|name>]"
#endif
" [<script> [<arg>...]]\n"
);
case 'p': {
size_t size(strlen(arg));
char *end;
+
pid = strtoul(arg, &end, 0);
if (arg + size != end) {
- fprintf(stderr, "invalid pid for -p\n");
- return 1;
+ // XXX: arg needs to be escaped in some horrendous way of doom
+ const char *command(apr_psprintf(pool, "ps axc|sed -e '/^ *[0-9]/{s/^ *\\([0-9]*\\)\\( *[^ ]*\\)\\{3\\} *-*\\([^ ]*\\)/\\3 \\1/;/^%s /{s/^[^ ]* //;q;};};d'", arg));
+
+ if (FILE *pids = popen(command, "r")) {
+ char value[32];
+ size = 0;
+
+ for (;;) {
+ size_t read(fread(value + size, 1, sizeof(value) - size, pids));
+ if (read == 0)
+ break;
+ else {
+ size += read;
+ if (size == sizeof(value)) {
+ pid = _not(pid_t);
+ goto pclose;
+ }
+ }
+ }
+
+ size:
+ if (size == 0)
+ goto pclose;
+ if (value[size - 1] == '\n') {
+ --size;
+ goto size;
+ }
+
+ value[size] = '\0';
+ size = strlen(value);
+ pid = strtoul(value, &end, 0);
+ if (value + size != end)
+ pid = _not(pid_t);
+
+ pclose:
+ _syscall(pclose(pids));
+ }
+
+ if (pid == _not(pid_t)) {
+ fprintf(stderr, "invalid pid for -p\n");
+ return 1;
+ }
}
} break;
#endif
if (pid == _not(pid_t))
socket = -1;
else {
+ InjectLibrary(pid);
+
socket = _syscall(::socket(PF_UNIX, SOCK_STREAM, 0));
struct sockaddr_un address;
#endif
if (script == NULL && tty)
- Console(socket);
+ Console(pool, socket);
else {
CYDriver driver(script ?: "<stdin>");
cy::parser parser(driver);
return 0;
}
+
+int main(int argc, char const * const argv[], char const * const envp[]) {
+ apr_status_t status(apr_app_initialize(&argc, &argv, &envp));
+ if (status != APR_SUCCESS) {
+ fprintf(stderr, "apr_app_initialize() != APR_SUCCESS\n");
+ return 1;
+ } else try {
+ return Main(argc, argv, envp);
+ } catch (const CYException &error) {
+ CYPool pool;
+ fprintf(stderr, "%s\n", error.PoolCString(pool));
+ return 1;
+ }
+}