time: -200 bytes of text
This commit is contained in:
parent
f93ab47c45
commit
c5cb38f4d9
180
miscutils/time.c
180
miscutils/time.c
@ -100,18 +100,14 @@ static int resuse_end(pid_t pid, resource_t * resp)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print ARGV to FP, with each entry in ARGV separated by FILLER. */
|
/* Print ARGV, with each entry in ARGV separated by FILLER. */
|
||||||
static void fprintargv(FILE * fp, char *const *argv, const char *filler)
|
static void printargv(char *const *argv, const char *filler)
|
||||||
{
|
{
|
||||||
char *const *av;
|
fputs(*argv, stdout);
|
||||||
|
while (*++argv) {
|
||||||
av = argv;
|
fputs(filler, stdout);
|
||||||
fputs(*av, fp);
|
fputs(*argv, stdout);
|
||||||
while (*++av) {
|
|
||||||
fputs(filler, fp);
|
|
||||||
fputs(*av, fp);
|
|
||||||
}
|
}
|
||||||
die_if_ferror(fp, "output");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the number of kilobytes corresponding to a number of pages PAGES.
|
/* Return the number of kilobytes corresponding to a number of pages PAGES.
|
||||||
@ -124,28 +120,26 @@ static void fprintargv(FILE * fp, char *const *argv, const char *filler)
|
|||||||
|
|
||||||
static unsigned long ptok(unsigned long pages)
|
static unsigned long ptok(unsigned long pages)
|
||||||
{
|
{
|
||||||
static unsigned long ps = 0;
|
static unsigned long ps;
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
static long size = LONG_MAX;
|
|
||||||
|
|
||||||
/* Initialization. */
|
/* Initialization. */
|
||||||
if (ps == 0)
|
if (ps == 0)
|
||||||
ps = (long) getpagesize();
|
ps = getpagesize();
|
||||||
|
|
||||||
/* Conversion. */
|
/* Conversion. */
|
||||||
if (pages > (LONG_MAX / ps)) { /* Could overflow. */
|
if (pages > (LONG_MAX / ps)) { /* Could overflow. */
|
||||||
tmp = pages / 1024; /* Smaller first, */
|
tmp = pages / 1024; /* Smaller first, */
|
||||||
size = tmp * ps; /* then larger. */
|
return tmp * ps; /* then larger. */
|
||||||
} else { /* Could underflow. */
|
|
||||||
tmp = pages * ps; /* Larger first, */
|
|
||||||
size = tmp / 1024; /* then smaller. */
|
|
||||||
}
|
}
|
||||||
return size;
|
/* Could underflow. */
|
||||||
|
tmp = pages * ps; /* Larger first, */
|
||||||
|
return tmp / 1024; /* then smaller. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* summarize: Report on the system use of a command.
|
/* summarize: Report on the system use of a command.
|
||||||
|
|
||||||
Copy the FMT argument to FP except that `%' sequences
|
Print the FMT argument except that `%' sequences
|
||||||
have special meaning, and `\n' and `\t' are translated into
|
have special meaning, and `\n' and `\t' are translated into
|
||||||
newline and tab, respectively, and `\\' is translated into `\'.
|
newline and tab, respectively, and `\\' is translated into `\'.
|
||||||
|
|
||||||
@ -183,25 +177,23 @@ static unsigned long ptok(unsigned long pages)
|
|||||||
to kbytes by multiplying by the page size, dividing by 1024,
|
to kbytes by multiplying by the page size, dividing by 1024,
|
||||||
and dividing by elapsed real time.
|
and dividing by elapsed real time.
|
||||||
|
|
||||||
FP is the stream to print to.
|
|
||||||
FMT is the format string, interpreted as described above.
|
FMT is the format string, interpreted as described above.
|
||||||
COMMAND is the command and args that are being summarized.
|
COMMAND is the command and args that are being summarized.
|
||||||
RESP is resource information on the command. */
|
RESP is resource information on the command. */
|
||||||
|
|
||||||
static void summarize(FILE * fp, const char *fmt, char **command,
|
static void summarize(const char *fmt, char **command, resource_t * resp)
|
||||||
resource_t * resp)
|
|
||||||
{
|
{
|
||||||
unsigned long r; /* Elapsed real milliseconds. */
|
unsigned long r; /* Elapsed real milliseconds. */
|
||||||
unsigned long v; /* Elapsed virtual (CPU) milliseconds. */
|
unsigned long v; /* Elapsed virtual (CPU) milliseconds. */
|
||||||
|
|
||||||
if (WIFSTOPPED(resp->waitstatus))
|
if (WIFSTOPPED(resp->waitstatus))
|
||||||
fprintf(fp, "Command stopped by signal %d\n",
|
printf("Command stopped by signal %d\n",
|
||||||
WSTOPSIG(resp->waitstatus));
|
WSTOPSIG(resp->waitstatus));
|
||||||
else if (WIFSIGNALED(resp->waitstatus))
|
else if (WIFSIGNALED(resp->waitstatus))
|
||||||
fprintf(fp, "Command terminated by signal %d\n",
|
printf("Command terminated by signal %d\n",
|
||||||
WTERMSIG(resp->waitstatus));
|
WTERMSIG(resp->waitstatus));
|
||||||
else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
|
else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
|
||||||
fprintf(fp, "Command exited with non-zero status %d\n",
|
printf("Command exited with non-zero status %d\n",
|
||||||
WEXITSTATUS(resp->waitstatus));
|
WEXITSTATUS(resp->waitstatus));
|
||||||
|
|
||||||
/* Convert all times to milliseconds. Occasionally, one of these values
|
/* Convert all times to milliseconds. Occasionally, one of these values
|
||||||
@ -214,178 +206,194 @@ static void summarize(FILE * fp, const char *fmt, char **command,
|
|||||||
v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
|
v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
|
||||||
resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
|
resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
|
||||||
|
|
||||||
|
/* putchar() != putc(stdout) in glibc! */
|
||||||
|
|
||||||
while (*fmt) {
|
while (*fmt) {
|
||||||
|
/* Handle leading literal part */
|
||||||
|
int n = strcspn(fmt, "%\\");
|
||||||
|
if (n) {
|
||||||
|
printf("%.*s", n, fmt);
|
||||||
|
fmt += n;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (*fmt) {
|
switch (*fmt) {
|
||||||
|
#ifdef NOT_NEEDED
|
||||||
|
/* Handle literal char */
|
||||||
|
/* Usually we optimize for size, but there is a limit
|
||||||
|
* for everything. With this we do a lot of 1-byte writes */
|
||||||
|
default:
|
||||||
|
putc(*fmt, stdout);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
switch (*++fmt) {
|
switch (*++fmt) {
|
||||||
case '%': /* Literal '%'. */
|
#ifdef NOT_NEEDED_YET
|
||||||
putc('%', fp);
|
/* Our format strings do not have these */
|
||||||
|
/* and we do not take format str from user */
|
||||||
|
default:
|
||||||
|
putc('%', stdout);
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case '%':
|
||||||
|
if (!*fmt) goto ret;
|
||||||
|
putc(*fmt, stdout);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 'C': /* The command that got timed. */
|
case 'C': /* The command that got timed. */
|
||||||
fprintargv(fp, command, " ");
|
printargv(command, " ");
|
||||||
break;
|
break;
|
||||||
case 'D': /* Average unshared data size. */
|
case 'D': /* Average unshared data size. */
|
||||||
fprintf(fp, "%lu",
|
printf("%lu",
|
||||||
MSEC_TO_TICKS(v) == 0 ? 0 :
|
MSEC_TO_TICKS(v) == 0 ? 0 :
|
||||||
ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
|
ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
|
||||||
ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
|
ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
|
||||||
break;
|
break;
|
||||||
case 'E': /* Elapsed real (wall clock) time. */
|
case 'E': /* Elapsed real (wall clock) time. */
|
||||||
if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */
|
if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */
|
||||||
fprintf(fp, "%ldh %ldm %02lds",
|
printf("%ldh %ldm %02lds",
|
||||||
resp->elapsed.tv_sec / 3600,
|
resp->elapsed.tv_sec / 3600,
|
||||||
(resp->elapsed.tv_sec % 3600) / 60,
|
(resp->elapsed.tv_sec % 3600) / 60,
|
||||||
resp->elapsed.tv_sec % 60);
|
resp->elapsed.tv_sec % 60);
|
||||||
else
|
else
|
||||||
fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */
|
printf("%ldm %ld.%02lds", /* -> m:s. */
|
||||||
resp->elapsed.tv_sec / 60,
|
resp->elapsed.tv_sec / 60,
|
||||||
resp->elapsed.tv_sec % 60,
|
resp->elapsed.tv_sec % 60,
|
||||||
resp->elapsed.tv_usec / 10000);
|
resp->elapsed.tv_usec / 10000);
|
||||||
break;
|
break;
|
||||||
case 'F': /* Major page faults. */
|
case 'F': /* Major page faults. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_majflt);
|
printf("%ld", resp->ru.ru_majflt);
|
||||||
break;
|
break;
|
||||||
case 'I': /* Inputs. */
|
case 'I': /* Inputs. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_inblock);
|
printf("%ld", resp->ru.ru_inblock);
|
||||||
break;
|
break;
|
||||||
case 'K': /* Average mem usage == data+stack+text. */
|
case 'K': /* Average mem usage == data+stack+text. */
|
||||||
fprintf(fp, "%lu",
|
printf("%lu",
|
||||||
MSEC_TO_TICKS(v) == 0 ? 0 :
|
MSEC_TO_TICKS(v) == 0 ? 0 :
|
||||||
ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
|
ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
|
||||||
ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) +
|
ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) +
|
||||||
ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
|
ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
|
||||||
break;
|
break;
|
||||||
case 'M': /* Maximum resident set size. */
|
case 'M': /* Maximum resident set size. */
|
||||||
fprintf(fp, "%lu", ptok((UL) resp->ru.ru_maxrss));
|
printf("%lu", ptok((UL) resp->ru.ru_maxrss));
|
||||||
break;
|
break;
|
||||||
case 'O': /* Outputs. */
|
case 'O': /* Outputs. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_oublock);
|
printf("%ld", resp->ru.ru_oublock);
|
||||||
break;
|
break;
|
||||||
case 'P': /* Percent of CPU this job got. */
|
case 'P': /* Percent of CPU this job got. */
|
||||||
/* % cpu is (total cpu time)/(elapsed time). */
|
/* % cpu is (total cpu time)/(elapsed time). */
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
fprintf(fp, "%lu%%", (v * 100 / r));
|
printf("%lu%%", (v * 100 / r));
|
||||||
else
|
else
|
||||||
fprintf(fp, "?%%");
|
printf("?%%");
|
||||||
break;
|
break;
|
||||||
case 'R': /* Minor page faults (reclaims). */
|
case 'R': /* Minor page faults (reclaims). */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_minflt);
|
printf("%ld", resp->ru.ru_minflt);
|
||||||
break;
|
break;
|
||||||
case 'S': /* System time. */
|
case 'S': /* System time. */
|
||||||
fprintf(fp, "%ld.%02ld",
|
printf("%ld.%02ld",
|
||||||
resp->ru.ru_stime.tv_sec,
|
resp->ru.ru_stime.tv_sec,
|
||||||
resp->ru.ru_stime.TV_MSEC / 10);
|
resp->ru.ru_stime.TV_MSEC / 10);
|
||||||
break;
|
break;
|
||||||
case 'T': /* System time. */
|
case 'T': /* System time. */
|
||||||
if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */
|
if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */
|
||||||
fprintf(fp, "%ldh %ldm %02lds",
|
printf("%ldh %ldm %02lds",
|
||||||
resp->ru.ru_stime.tv_sec / 3600,
|
resp->ru.ru_stime.tv_sec / 3600,
|
||||||
(resp->ru.ru_stime.tv_sec % 3600) / 60,
|
(resp->ru.ru_stime.tv_sec % 3600) / 60,
|
||||||
resp->ru.ru_stime.tv_sec % 60);
|
resp->ru.ru_stime.tv_sec % 60);
|
||||||
else
|
else
|
||||||
fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */
|
printf("%ldm %ld.%02lds", /* -> m:s. */
|
||||||
resp->ru.ru_stime.tv_sec / 60,
|
resp->ru.ru_stime.tv_sec / 60,
|
||||||
resp->ru.ru_stime.tv_sec % 60,
|
resp->ru.ru_stime.tv_sec % 60,
|
||||||
resp->ru.ru_stime.tv_usec / 10000);
|
resp->ru.ru_stime.tv_usec / 10000);
|
||||||
break;
|
break;
|
||||||
case 'U': /* User time. */
|
case 'U': /* User time. */
|
||||||
fprintf(fp, "%ld.%02ld",
|
printf("%ld.%02ld",
|
||||||
resp->ru.ru_utime.tv_sec,
|
resp->ru.ru_utime.tv_sec,
|
||||||
resp->ru.ru_utime.TV_MSEC / 10);
|
resp->ru.ru_utime.TV_MSEC / 10);
|
||||||
break;
|
break;
|
||||||
case 'u': /* User time. */
|
case 'u': /* User time. */
|
||||||
if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */
|
if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */
|
||||||
fprintf(fp, "%ldh %ldm %02lds",
|
printf("%ldh %ldm %02lds",
|
||||||
resp->ru.ru_utime.tv_sec / 3600,
|
resp->ru.ru_utime.tv_sec / 3600,
|
||||||
(resp->ru.ru_utime.tv_sec % 3600) / 60,
|
(resp->ru.ru_utime.tv_sec % 3600) / 60,
|
||||||
resp->ru.ru_utime.tv_sec % 60);
|
resp->ru.ru_utime.tv_sec % 60);
|
||||||
else
|
else
|
||||||
fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */
|
printf("%ldm %ld.%02lds", /* -> m:s. */
|
||||||
resp->ru.ru_utime.tv_sec / 60,
|
resp->ru.ru_utime.tv_sec / 60,
|
||||||
resp->ru.ru_utime.tv_sec % 60,
|
resp->ru.ru_utime.tv_sec % 60,
|
||||||
resp->ru.ru_utime.tv_usec / 10000);
|
resp->ru.ru_utime.tv_usec / 10000);
|
||||||
break;
|
break;
|
||||||
case 'W': /* Times swapped out. */
|
case 'W': /* Times swapped out. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_nswap);
|
printf("%ld", resp->ru.ru_nswap);
|
||||||
break;
|
break;
|
||||||
case 'X': /* Average shared text size. */
|
case 'X': /* Average shared text size. */
|
||||||
fprintf(fp, "%lu",
|
printf("%lu",
|
||||||
MSEC_TO_TICKS(v) == 0 ? 0 :
|
MSEC_TO_TICKS(v) == 0 ? 0 :
|
||||||
ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
|
ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
|
||||||
break;
|
break;
|
||||||
case 'Z': /* Page size. */
|
case 'Z': /* Page size. */
|
||||||
fprintf(fp, "%d", getpagesize());
|
printf("%d", getpagesize());
|
||||||
break;
|
break;
|
||||||
case 'c': /* Involuntary context switches. */
|
case 'c': /* Involuntary context switches. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_nivcsw);
|
printf("%ld", resp->ru.ru_nivcsw);
|
||||||
break;
|
break;
|
||||||
case 'e': /* Elapsed real time in seconds. */
|
case 'e': /* Elapsed real time in seconds. */
|
||||||
fprintf(fp, "%ld.%02ld",
|
printf("%ld.%02ld",
|
||||||
resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
|
resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
|
||||||
break;
|
break;
|
||||||
case 'k': /* Signals delivered. */
|
case 'k': /* Signals delivered. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_nsignals);
|
printf("%ld", resp->ru.ru_nsignals);
|
||||||
break;
|
break;
|
||||||
case 'p': /* Average stack segment. */
|
case 'p': /* Average stack segment. */
|
||||||
fprintf(fp, "%lu",
|
printf("%lu",
|
||||||
MSEC_TO_TICKS(v) == 0 ? 0 :
|
MSEC_TO_TICKS(v) == 0 ? 0 :
|
||||||
ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
|
ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
|
||||||
break;
|
break;
|
||||||
case 'r': /* Incoming socket messages received. */
|
case 'r': /* Incoming socket messages received. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_msgrcv);
|
printf("%ld", resp->ru.ru_msgrcv);
|
||||||
break;
|
break;
|
||||||
case 's': /* Outgoing socket messages sent. */
|
case 's': /* Outgoing socket messages sent. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_msgsnd);
|
printf("%ld", resp->ru.ru_msgsnd);
|
||||||
break;
|
break;
|
||||||
case 't': /* Average resident set size. */
|
case 't': /* Average resident set size. */
|
||||||
fprintf(fp, "%lu",
|
printf("%lu",
|
||||||
MSEC_TO_TICKS(v) == 0 ? 0 :
|
MSEC_TO_TICKS(v) == 0 ? 0 :
|
||||||
ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
|
ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
|
||||||
break;
|
break;
|
||||||
case 'w': /* Voluntary context switches. */
|
case 'w': /* Voluntary context switches. */
|
||||||
fprintf(fp, "%ld", resp->ru.ru_nvcsw);
|
printf("%ld", resp->ru.ru_nvcsw);
|
||||||
break;
|
break;
|
||||||
case 'x': /* Exit status. */
|
case 'x': /* Exit status. */
|
||||||
fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus));
|
printf("%d", WEXITSTATUS(resp->waitstatus));
|
||||||
break;
|
break;
|
||||||
case '\0':
|
|
||||||
putc('?', fp);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
putc('?', fp);
|
|
||||||
putc(*fmt, fp);
|
|
||||||
}
|
}
|
||||||
++fmt;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef NOT_NEEDED_YET
|
||||||
case '\\': /* Format escape. */
|
case '\\': /* Format escape. */
|
||||||
switch (*++fmt) {
|
switch (*++fmt) {
|
||||||
|
default:
|
||||||
|
putc('\\', stdout);
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case '\\':
|
||||||
|
if (!*fmt) goto ret;
|
||||||
|
putc(*fmt, stdout);
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
putc('\t', fp);
|
putc('\t', stdout);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
putc('\n', fp);
|
putc('\n', stdout);
|
||||||
break;
|
break;
|
||||||
case '\\':
|
|
||||||
putc('\\', fp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
putc('?', fp);
|
|
||||||
putc('\\', fp);
|
|
||||||
putc(*fmt, fp);
|
|
||||||
}
|
}
|
||||||
++fmt;
|
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
|
||||||
putc(*fmt++, fp);
|
|
||||||
}
|
}
|
||||||
|
++fmt;
|
||||||
die_if_ferror(fp, "output");
|
|
||||||
}
|
}
|
||||||
putc('\n', fp);
|
/* ret: */
|
||||||
|
putc('\n', stdout);
|
||||||
die_if_ferror(fp, "output");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run command CMD and return statistics on it.
|
/* Run command CMD and return statistics on it.
|
||||||
@ -449,7 +457,11 @@ int time_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
run_command(argv, &res);
|
run_command(argv, &res);
|
||||||
summarize(stderr, output_format, argv, &res);
|
|
||||||
|
/* Cheat. printf's are shorter :) */
|
||||||
|
stdout = stderr;
|
||||||
|
dup2(2, 1); /* just in case libc does something silly :( */
|
||||||
|
summarize(output_format, argv, &res);
|
||||||
|
|
||||||
if (WIFSTOPPED(res.waitstatus))
|
if (WIFSTOPPED(res.waitstatus))
|
||||||
return WSTOPSIG(res.waitstatus);
|
return WSTOPSIG(res.waitstatus);
|
||||||
@ -457,5 +469,5 @@ int time_main(int argc, char **argv)
|
|||||||
return WTERMSIG(res.waitstatus);
|
return WTERMSIG(res.waitstatus);
|
||||||
if (WIFEXITED(res.waitstatus))
|
if (WIFEXITED(res.waitstatus))
|
||||||
return WEXITSTATUS(res.waitstatus);
|
return WEXITSTATUS(res.waitstatus);
|
||||||
return 0;
|
fflush_stdout_and_exit(0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user