You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.7 KiB
216 lines
5.7 KiB
/*
|
|
* Copyright (C) 2024 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* Licensed 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.
|
|
*/
|
|
|
|
#define LOG_TAG "ASL"
|
|
#include <utils/Log.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <vector>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
|
|
#define ROOTDIR "/mnt/linux"
|
|
#define UNUSED(x) (void)(x)
|
|
#define DEBUG 0
|
|
|
|
|
|
struct args_t {
|
|
bool bPrintUsage;
|
|
bool bAndroidServerMode;
|
|
bool bHasCommands;
|
|
std::string sPidFile;
|
|
std::string sCommandName;
|
|
std::vector<std::string> vCommandArgs;
|
|
};
|
|
|
|
void usage() {
|
|
printf("Usage:\n");
|
|
printf(" asl\n");
|
|
printf(" asl <linux-bin>\n");
|
|
printf(" asl -s -p <pid_file> <linux-bin>\n");
|
|
printf("Arguments:\n");
|
|
printf(" -s : android server mode.\n");
|
|
printf(" -p : linux pid file path.\n");
|
|
printf(" linux-bin : abs path in linux root.\n");
|
|
}
|
|
|
|
args_t parse(int argc, char *argv[]) {
|
|
args_t args = {};
|
|
for (int i = 1; i < argc; ++i) {
|
|
if (std::string(argv[i]) == std::string("-h")) {
|
|
args.bPrintUsage = true;
|
|
return std::move(args);
|
|
} else if (std::string(argv[i]) == std::string("-s")) {
|
|
args.bAndroidServerMode = true;
|
|
} else if (std::string(argv[i]) == std::string("-p")) {
|
|
if (i + 1 >= argc) { // ERR
|
|
args.bPrintUsage = true;
|
|
return std::move(args);
|
|
}
|
|
args.sPidFile = argv[++i];
|
|
} else { /** Command In Chroot **/
|
|
args.bHasCommands = true;
|
|
args.sCommandName = argv[i++];
|
|
for (; i < argc ; ++i) {
|
|
args.vCommandArgs.push_back(argv[i]);
|
|
}
|
|
}
|
|
}
|
|
return std::move(args);
|
|
}
|
|
|
|
int readpid(const std::string &pid_file) {
|
|
std::ifstream file(pid_file);
|
|
int pid = -1;
|
|
if (!file.good()) {
|
|
ALOGE("pid file %s is not exsited!", pid_file.c_str());
|
|
} else if (file.is_open()) {
|
|
file >> pid;
|
|
file.close();
|
|
ALOGI("pid file %s is opened! pid=%d", pid_file.c_str(), pid);
|
|
return pid;
|
|
}
|
|
return pid;
|
|
}
|
|
|
|
void setenvs() {
|
|
const char *PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
const char *HOME = "/root";
|
|
const char *DISPLAY=":0";
|
|
const char *PULSE_SERVER="tcp:127.0.0.1:4713";
|
|
|
|
if (setenv("PATH", PATH, 1) == -1) {
|
|
perror("setenv");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (setenv("HOME", HOME, 1) == -1) {
|
|
perror("setenv");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (setenv("DISPLAY", DISPLAY, 1) == -1) {
|
|
perror("setenv");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (setenv("PULSE_SERVER", PULSE_SERVER, 1) == -1) {
|
|
perror("setenv");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void execute(bool bHasCommands, const std::string &commands, const std::vector<std::string> &parms) {
|
|
const char *BASH = "/bin/bash";
|
|
|
|
char *args[6];
|
|
int cst = 0;
|
|
args[cst++] = (char*)"bash";
|
|
args[cst++] = (char*)"--rcfile";
|
|
args[cst++] = (char*)"~/.bashrc";
|
|
args[cst++] = (char*)"-c";
|
|
std::stringstream ss;
|
|
ss << commands;
|
|
for (int i = 0; i < parms.size(); ++i) {
|
|
ss << " " << parms[i];
|
|
}
|
|
args[cst++] = (char*)ss.str().c_str();
|
|
args[cst++] = NULL;
|
|
|
|
#if DEBUG
|
|
printf("--- linux command ---\n");
|
|
for (int i = 0; i < cst; ++i) {
|
|
printf("[%d] %s\n", i, args[i]);
|
|
}
|
|
#endif
|
|
|
|
if (!bHasCommands) {
|
|
execl(BASH, "bash", NULL);
|
|
} else {
|
|
execvp(BASH, args);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (getuid() != 0) {
|
|
fprintf(stderr, "Permission Denied.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
args_t args = parse(argc, argv);
|
|
#if DEBUG
|
|
printf("* print usage: %d\n", args.bPrintUsage);
|
|
printf("* android server mode: %d\n", args.bAndroidServerMode);
|
|
printf("* has linux command: %d\n", args.bHasCommands);
|
|
printf("* linux pid file path: %s\n", args.sPidFile.c_str());
|
|
printf("* linux command: %s\n", args.sCommandName.c_str());
|
|
#endif
|
|
if (args.bPrintUsage) {
|
|
usage();
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
if (chroot(ROOTDIR) == -1) {
|
|
perror("chroot");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (chdir("/") == -1) {
|
|
perror("chdir");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
pid_t pid = fork();
|
|
if (pid == -1) {
|
|
perror("fork");
|
|
exit(EXIT_FAILURE);
|
|
} else if (pid == 0) { // sub process
|
|
setenvs();
|
|
execute(args.bHasCommands, args.sCommandName, args.vCommandArgs);
|
|
perror("exec");
|
|
exit(EXIT_FAILURE);
|
|
} else { // father process
|
|
int status;
|
|
pid_t wpid = waitpid(pid, &status, 0);
|
|
if (WIFEXITED(status)) {
|
|
ALOGI("process exited with status %d, pid=%d\n", WEXITSTATUS(status), wpid);
|
|
}
|
|
}
|
|
|
|
if (args.bAndroidServerMode) {
|
|
sleep(1);
|
|
int fpid = readpid(args.sPidFile);
|
|
while (1) {
|
|
if (kill(fpid, 0) == -1) {
|
|
if (errno == ESRCH) {
|
|
ALOGI("server exited %d\n", fpid);
|
|
break;
|
|
} else {
|
|
perror("kill");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
exit(EXIT_SUCCESS);
|
|
} |