|
@@ -280,6 +280,160 @@ checkSHA256() {
|
|
fi
|
|
fi
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+fixSystem() {
|
|
|
|
+ FILE="$1"
|
|
|
|
+ echo '#define PROC_PIDPATHINFO_MAXSIZE (1024)' >> "$FILE"
|
|
|
|
+ echo 'static int file_exist(const char *filename) {' >> "$FILE"
|
|
|
|
+ echo ' struct stat buffer;' >> "$FILE"
|
|
|
|
+ echo ' int r = stat(filename, &buffer);' >> "$FILE"
|
|
|
|
+ echo ' return (r == 0);' >> "$FILE"
|
|
|
|
+ echo '}' >> "$FILE"
|
|
|
|
+ echo '' >> "$FILE"
|
|
|
|
+ echo 'static char *searchpath(const char *binaryname){' >> "$FILE"
|
|
|
|
+ echo ' if (strstr(binaryname, "/") != NULL){' >> "$FILE"
|
|
|
|
+ echo ' if (file_exist(binaryname)){' >> "$FILE"
|
|
|
|
+ echo ' char *foundpath = malloc((strlen(binaryname) + 1) * (sizeof(char)));' >> "$FILE"
|
|
|
|
+ echo ' strcpy(foundpath, binaryname);' >> "$FILE"
|
|
|
|
+ echo ' return foundpath;' >> "$FILE"
|
|
|
|
+ echo ' } else {' >> "$FILE"
|
|
|
|
+ echo ' return NULL' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *pathvar = getenv("PATH");' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *dir = strtok(pathvar,":");' >> "$FILE"
|
|
|
|
+ echo ' while (dir != NULL){' >> "$FILE"
|
|
|
|
+ echo ' char searchpth[PROC_PIDPATHINFO_MAXSIZE];' >> "$FILE"
|
|
|
|
+ echo ' strcpy(searchpth, dir);' >> "$FILE"
|
|
|
|
+ echo ' strcat(searchpth, "/");' >> "$FILE"
|
|
|
|
+ echo ' strcat(searchpth, binaryname);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' if (file_exist(searchpth)){' >> "$FILE"
|
|
|
|
+ echo ' char *foundpath = malloc((strlen(searchpth) + 1) * (sizeof(char)));' >> "$FILE"
|
|
|
|
+ echo ' strcpy(foundpath, searchpth);' >> "$FILE"
|
|
|
|
+ echo ' return foundpath;' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' dir = strtok(NULL, ":");' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' return NULL;' >> "$FILE"
|
|
|
|
+ echo '}' >> "$FILE"
|
|
|
|
+ echo '' >> "$FILE"
|
|
|
|
+ echo 'static bool isShellScript(const char *path){' >> "$FILE"
|
|
|
|
+ echo ' FILE *file = fopen(path, "r");' >> "$FILE"
|
|
|
|
+ echo ' uint8_t header[2];' >> "$FILE"
|
|
|
|
+ echo ' if (fread(header, sizeof(uint8_t), 2, file) == 2){' >> "$FILE"
|
|
|
|
+ echo " if (header[0] == '#' && header[1] == '!'){" >> "$FILE"
|
|
|
|
+ echo ' fclose(file);' >> "$FILE"
|
|
|
|
+ echo ' return true;' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' fclose(file);' >> "$FILE"
|
|
|
|
+ echo ' return false;' >> "$FILE"
|
|
|
|
+ echo '}' >> "$FILE"
|
|
|
|
+ echo '' >> "$FILE"
|
|
|
|
+ echo 'static char *getInterpreter(char *path){' >> "$FILE"
|
|
|
|
+ echo ' FILE *file = fopen(path, "r");' >> "$FILE"
|
|
|
|
+ echo ' char *interpreterLine = NULL;' >> "$FILE"
|
|
|
|
+ echo ' unsigned long lineSize = 0;' >> "$FILE"
|
|
|
|
+ echo ' getline(&interpreterLine, &lineSize, file);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *rawInterpreter = (interpreterLine+2);' >> "$FILE"
|
|
|
|
+ echo ' rawInterpreter = strtok(rawInterpreter, " ");' >> "$FILE"
|
|
|
|
+ echo ' rawInterpreter = strtok(rawInterpreter, "\n");' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *interpreter = malloc((strlen(rawInterpreter)+1) * sizeof(char));' >> "$FILE"
|
|
|
|
+ echo ' strcpy(interpreter, rawInterpreter);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' free(interpreterLine);' >> "$FILE"
|
|
|
|
+ echo ' fclose(file);' >> "$FILE"
|
|
|
|
+ echo ' return interpreter;' >> "$FILE"
|
|
|
|
+ echo '}' >> "$FILE"
|
|
|
|
+ echo '' >> "$FILE"
|
|
|
|
+ echo 'static char *fixedCmd(const char *cmdStr){' >> "$FILE"
|
|
|
|
+ echo ' char *cmdCpy = malloc((strlen(cmdStr)+1) * sizeof(char));' >> "$FILE"
|
|
|
|
+ echo ' strcpy(cmdCpy, cmdStr);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *cmd = strtok(cmdCpy, " ");' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' uint8_t size = strlen(cmd) + 1;' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *args = cmdCpy + (size + 1);' >> "$FILE"
|
|
|
|
+ echo ' if ((strlen(cmdStr) - strlen(cmd)) == 0)' >> "$FILE"
|
|
|
|
+ echo ' args = NULL;' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *abs_path = searchpath(cmd);' >> "$FILE"
|
|
|
|
+ echo ' if (abs_path){' >> "$FILE"
|
|
|
|
+ echo ' bool isScript = isShellScript(abs_path);' >> "$FILE"
|
|
|
|
+ echo ' if (isScript){' >> "$FILE"
|
|
|
|
+ echo ' char *interpreter = getInterpreter(abs_path);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' uint8_t commandSize = strlen(interpreter) + 1 + strlen(abs_path);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' if (args){' >> "$FILE"
|
|
|
|
+ echo ' commandSize += 1 + strlen(args);' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *rawCommand = malloc(sizeof(char) * (commandSize + 1));' >> "$FILE"
|
|
|
|
+ echo ' strcpy(rawCommand, interpreter);' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, " ");' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, abs_path);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' if (args){' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, " ");' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, args);' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' rawCommand[(commandSize)+1] = "\0";' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' free(interpreter);' >> "$FILE"
|
|
|
|
+ echo ' free(abs_path);' >> "$FILE"
|
|
|
|
+ echo ' free(cmdCpy);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' return rawCommand;' >> "$FILE"
|
|
|
|
+ echo ' } else {' >> "$FILE"
|
|
|
|
+ echo ' uint8_t commandSize = strlen(abs_path);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' if (args){' >> "$FILE"
|
|
|
|
+ echo ' commandSize += 1 + strlen(args);' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' char *rawCommand = malloc(sizeof(char) * (commandSize + 1));' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, abs_path);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' if (args){' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, " ");' >> "$FILE"
|
|
|
|
+ echo ' strcat(rawCommand, args);' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' rawCommand[(commandSize)+1] = "\0";' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' free(abs_path);' >> "$FILE"
|
|
|
|
+ echo ' free(cmdCpy);' >> "$FILE"
|
|
|
|
+ echo ' ' >> "$FILE"
|
|
|
|
+ echo ' return rawCommand;' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' return cmdCpy;' >> "$FILE"
|
|
|
|
+ echo '}' >> "$FILE"
|
|
|
|
+ echo '' >> "$FILE"
|
|
|
|
+ echo 'int RunCmd(const char *cmd) {' >> "$FILE"
|
|
|
|
+ echo ' pid_t pid;' >> "$FILE"
|
|
|
|
+ echo ' char *rawCmd = fixedCmd(cmd);' >> "$FILE"
|
|
|
|
+ echo ' char *argv[] = {"sh", "-c", (char*)rawCmd, NULL};' >> "$FILE"
|
|
|
|
+ echo ' int status;' >> "$FILE"
|
|
|
|
+ echo ' status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);' >> "$FILE"
|
|
|
|
+ echo ' if (status == 0) {' >> "$FILE"
|
|
|
|
+ echo ' if (waitpid(pid, &status, 0) == -1) {' >> "$FILE"
|
|
|
|
+ echo ' perror("waitpid");' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' } else {' >> "$FILE"
|
|
|
|
+ echo ' printf("posix_spawn: %s\n", strerror(status));' >> "$FILE"
|
|
|
|
+ echo ' }' >> "$FILE"
|
|
|
|
+ echo ' free(rawCmd);' >> "$FILE"
|
|
|
|
+ echo ' return status;' >> "$FILE"
|
|
|
|
+ echo '}' >> "$FILE"
|
|
|
|
+}
|
|
|
|
+
|
|
#=====================
|
|
#=====================
|
|
#OSGT10.1
|
|
#OSGT10.1
|
|
#---------------------
|
|
#---------------------
|
|
@@ -399,23 +553,7 @@ patchNcurses() {
|
|
echo "extern char **environ;" >> tput.patched.c
|
|
echo "extern char **environ;" >> tput.patched.c
|
|
echo "" >> tput.patched.c
|
|
echo "" >> tput.patched.c
|
|
cat progs/tput.c | tail -n 350 | head -n 50 >> tput.patched.c
|
|
cat progs/tput.c | tail -n 350 | head -n 50 >> tput.patched.c
|
|
- echo "int RunCmd(const char *cmd) {" >> tput.patched.c
|
|
|
|
- echo " pid_t pid;" >> tput.patched.c
|
|
|
|
- echo ' char *argv[] = {"sh", "-c", (char*)cmd, NULL};' >> tput.patched.c
|
|
|
|
- echo ' int status;' >> tput.patched.c
|
|
|
|
- echo ' status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ)' >> tput.patched.c
|
|
|
|
- echo ' if (status == 0) {' >> tput.patched.c
|
|
|
|
- echo ' if (waitpid(pid, &status, 0) != -1) {' >> tput.patched.c
|
|
|
|
- echo ' printf("Child exted in ATV Patched RunCmd with status %i\n", status);' >> tput.patched.c
|
|
|
|
- echo ' } else {' >> tput.patched.c
|
|
|
|
- echo ' perror("waitpid");' >> tput.patched.c
|
|
|
|
- echo ' }' >> tput.patched.c
|
|
|
|
- echo ' } else {' >> tput.patched.c
|
|
|
|
- echo ' printf("posix_spawn: %s\n", strerror(status));' >> tput.patched.c
|
|
|
|
- echo ' }' >> tput.patched.c
|
|
|
|
- echo ' return status;' >> tput.patched.c
|
|
|
|
- echo '}' >> tput.patched.c
|
|
|
|
- echo "" >> tput.patched.c
|
|
|
|
|
|
+ fixSystem "tput.patched.c"
|
|
cat progs/tput.c | tail -n 301 | sed 's/system(init_prog)/RunCmd(init_prog)/g' >> tput.patched.c
|
|
cat progs/tput.c | tail -n 301 | sed 's/system(init_prog)/RunCmd(init_prog)/g' >> tput.patched.c
|
|
cp tput.patched.c progs/tput.c
|
|
cp tput.patched.c progs/tput.c
|
|
fi
|
|
fi
|
|
@@ -1983,23 +2121,7 @@ patchBerkeleyDB() {
|
|
echo "extern char **environ;" >> shell.patched.c
|
|
echo "extern char **environ;" >> shell.patched.c
|
|
echo "" >> shell.patched.c
|
|
echo "" >> shell.patched.c
|
|
cat ../lang/sql/sqlite/src/shell.c | tail -n 4847 | head -n 2622 >> shell.patched.c
|
|
cat ../lang/sql/sqlite/src/shell.c | tail -n 4847 | head -n 2622 >> shell.patched.c
|
|
- echo "int RunCmd(const char *cmd) {" >> shell.patched.c
|
|
|
|
- echo " pid_t pid;" >> shell.patched.c
|
|
|
|
- echo ' char *argv[] = {"sh", "-c", (char*)cmd, NULL};' >> shell.patched.c
|
|
|
|
- echo ' int status;' >> shell.patched.c
|
|
|
|
- echo ' status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);' >> shell.patched.c
|
|
|
|
- echo ' if (status == 0) {' >> shell.patched.c
|
|
|
|
- echo ' if (waitpid(pid, &status, 0) != -1) {' >> shell.patched.c
|
|
|
|
- echo ' printf("Child exted in ATV Patched RunCmd with status %i\n", status);' >> shell.patched.c
|
|
|
|
- echo ' } else {' >> shell.patched.c
|
|
|
|
- echo ' perror("waitpid");' >> shell.patched.c
|
|
|
|
- echo ' }' >> shell.patched.c
|
|
|
|
- echo ' } else {' >> shell.patched.c
|
|
|
|
- echo ' printf("posix_spawn: %s\n", strerror(status));' >> shell.patched.c
|
|
|
|
- echo ' }' >> shell.patched.c
|
|
|
|
- echo ' return status;' >> shell.patched.c
|
|
|
|
- echo '}' >> shell.patched.c
|
|
|
|
- echo "" >> shell.patched.c
|
|
|
|
|
|
+ fixSystem "shell.patched.c"
|
|
cat ../lang/sql/sqlite/src/shell.c | tail -n 2226 | sed 's/system(zCmd)/RunCmd(zCmd)/g' >> shell.patched.c
|
|
cat ../lang/sql/sqlite/src/shell.c | tail -n 2226 | sed 's/system(zCmd)/RunCmd(zCmd)/g' >> shell.patched.c
|
|
cp shell.patched.c ../lang/sql/sqlite/src/shell.c
|
|
cp shell.patched.c ../lang/sql/sqlite/src/shell.c
|
|
fi
|
|
fi
|
|
@@ -2454,23 +2576,7 @@ patchGcrypt() {
|
|
echo "" >> random.patched.c
|
|
echo "" >> random.patched.c
|
|
echo "extern char **environ;" >> random.patched.c
|
|
echo "extern char **environ;" >> random.patched.c
|
|
echo "" >> random.patched.c
|
|
echo "" >> random.patched.c
|
|
- echo "int RunCmd(const char *cmd) {" >> random.patched.c
|
|
|
|
- echo " pid_t pid;" >> random.patched.c
|
|
|
|
- echo ' char *argv[] = {"sh", "-c", (char*)cmd, NULL};' >> random.patched.c
|
|
|
|
- echo ' int status;' >> random.patched.c
|
|
|
|
- echo ' status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);' >> random.patched.c
|
|
|
|
- echo ' if (status == 0) {' >> random.patched.c
|
|
|
|
- echo ' if (waitpid(pid, &status, 0) != -1) {' >> random.patched.c
|
|
|
|
- echo ' printf("Child exted in ATV Patched RunCmd with status %i\n", status);' >> random.patched.c
|
|
|
|
- echo ' } else {' >> random.patched.c
|
|
|
|
- echo ' perror("waitpid");' >> random.patched.c
|
|
|
|
- echo ' }' >> random.patched.c
|
|
|
|
- echo ' } else {' >> random.patched.c
|
|
|
|
- echo ' printf("posix_spawn: %s\n", strerror(status));' >> random.patched.c
|
|
|
|
- echo ' }' >> random.patched.c
|
|
|
|
- echo ' return status;' >> random.patched.c
|
|
|
|
- echo '}' >> random.patched.c
|
|
|
|
- echo "" >> random.patched.c
|
|
|
|
|
|
+ fixSystem "random.patched.c"
|
|
cat tests/random.c | tail -n 727 | sed 's/system (cmdline)/RunCmd(cmdline)/g' >> random.patched.c
|
|
cat tests/random.c | tail -n 727 | sed 's/system (cmdline)/RunCmd(cmdline)/g' >> random.patched.c
|
|
cp random.patched.c tests/random.c
|
|
cp random.patched.c tests/random.c
|
|
fi
|
|
fi
|
|
@@ -2670,23 +2776,7 @@ patchNpth() {
|
|
echo "extern char **environ;" >> npth.patched.c
|
|
echo "extern char **environ;" >> npth.patched.c
|
|
echo "" >> npth.patched.c
|
|
echo "" >> npth.patched.c
|
|
cat src/npth.c | tail -n 757 | head -n 537 >> npth.patched.c
|
|
cat src/npth.c | tail -n 757 | head -n 537 >> npth.patched.c
|
|
- echo "int RunCmd(const char *cmd) {" >> npth.patched.c
|
|
|
|
- echo " pid_t pid;" >> npth.patched.c
|
|
|
|
- echo ' char *argv[] = {"sh", "-c", (char*)cmd, NULL};' >> npth.patched.c
|
|
|
|
- echo ' int status;' >> npth.patched.c
|
|
|
|
- echo ' status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);' >> npth.patched.c
|
|
|
|
- echo ' if (status == 0) {' >> npth.patched.c
|
|
|
|
- echo ' if (waitpid(pid, &status, 0) != -1) {' >> npth.patched.c
|
|
|
|
- echo ' printf("Child exted in ATV Patched RunCmd with status %i\n", status);' >> npth.patched.c
|
|
|
|
- echo ' } else {' >> npth.patched.c
|
|
|
|
- echo ' perror("waitpid");' >> npth.patched.c
|
|
|
|
- echo ' }' >> npth.patched.c
|
|
|
|
- echo ' } else {' >> npth.patched.c
|
|
|
|
- echo ' printf("posix_spawn: %s\n", strerror(status));' >> npth.patched.c
|
|
|
|
- echo ' }' >> npth.patched.c
|
|
|
|
- echo ' return status;' >> npth.patched.c
|
|
|
|
- echo '}' >> npth.patched.c
|
|
|
|
- echo "" >> npth.patched.c
|
|
|
|
|
|
+ fixSystem "npth.patched.c"
|
|
cat src/npth.c | tail -n 220 | sed 's/system(cmd)/RunCmd(cmd)/g' >> npth.patched.c
|
|
cat src/npth.c | tail -n 220 | sed 's/system(cmd)/RunCmd(cmd)/g' >> npth.patched.c
|
|
cp npth.patched.c src/npth.c
|
|
cp npth.patched.c src/npth.c
|
|
fi
|
|
fi
|
|
@@ -2959,23 +3049,7 @@ patchGpg() {
|
|
echo "extern char **environ;" >> "exec.patched.c"
|
|
echo "extern char **environ;" >> "exec.patched.c"
|
|
echo "" >> "exec.patched.c"
|
|
echo "" >> "exec.patched.c"
|
|
cat "g10/exec.c" | head -n 111 | tail -n 57 >> "exec.patched.c"
|
|
cat "g10/exec.c" | head -n 111 | tail -n 57 >> "exec.patched.c"
|
|
- echo "int RunCmd(const char *cmd) {" >> "exec.patched.c"
|
|
|
|
- echo " pid_t pid;" >> "exec.patched.c"
|
|
|
|
- echo ' char *argv[] = {"sh", "-c", (char*)cmd, NULL};' >> "exec.patched.c"
|
|
|
|
- echo ' int status;' >> "exec.patched.c"
|
|
|
|
- echo ' status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);' >> "exec.patched.c"
|
|
|
|
- echo ' if (status == 0) {' >> "exec.patched.c"
|
|
|
|
- echo ' if (waitpid(pid, &status, 0) != -1) {' >> "exec.patched.c"
|
|
|
|
- echo ' printf("Child exted in ATV Patched RunCmd with status %i\n", status);' >> "exec.patched.c"
|
|
|
|
- echo ' } else {' >> "exec.patched.c"
|
|
|
|
- echo ' perror("waitpid");' >> "exec.patched.c"
|
|
|
|
- echo ' }' >> "exec.patched.c"
|
|
|
|
- echo ' } else {' >> "exec.patched.c"
|
|
|
|
- echo ' printf("posix_spawn: %s\n", strerror(status));' >> "exec.patched.c"
|
|
|
|
- echo ' }' >> "exec.patched.c"
|
|
|
|
- echo ' return status;' >> "exec.patched.c"
|
|
|
|
- echo '}' >> "exec.patched.c"
|
|
|
|
- echo "" >> "exec.patched.c"
|
|
|
|
|
|
+ fixSystem "exec.patched.c"
|
|
cat "g10/exec.c" | tail -n 524 | sed 's/=system(info->command)/=RunCmd(info->command)/g' >> "exec.patched.c"
|
|
cat "g10/exec.c" | tail -n 524 | sed 's/=system(info->command)/=RunCmd(info->command)/g' >> "exec.patched.c"
|
|
cp "exec.patched.c" "g10/exec.c"
|
|
cp "exec.patched.c" "g10/exec.c"
|
|
fi
|
|
fi
|