Compare commits
6 commits
1384f90765
...
36dbe8dcb7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36dbe8dcb7 | ||
|
|
c67d1f0455 | ||
|
|
e6958c31d0 | ||
|
|
8ea5fe76a3 | ||
|
|
bee3380a95 | ||
|
|
7fc84c0996 |
3 changed files with 117 additions and 78 deletions
3
d3d.rc
3
d3d.rc
|
|
@ -2,7 +2,6 @@
|
||||||
path reset_gpio /run/gpio/Reset/value
|
path reset_gpio /run/gpio/Reset/value
|
||||||
path eint1_gpio /run/gpio/EINT1/value
|
path eint1_gpio /run/gpio/EINT1/value
|
||||||
uart /dev/ttyS1 gpio
|
uart /dev/ttyS1 gpio
|
||||||
clock_sync 3600
|
|
||||||
fct_min_data 16
|
fct_min_data 16
|
||||||
fct_max_cadence 2
|
fct_max_cadence 2
|
||||||
fct 32
|
fct 32
|
||||||
|
|
@ -10,4 +9,4 @@ statusfile d3d/irena-status
|
||||||
datafile d3d/irena-%Y-%m-%dT%H:%M:%SZ.dat
|
datafile d3d/irena-%Y-%m-%dT%H:%M:%SZ.dat
|
||||||
counterfile d3d/irena-%Y-%m-%dT%H:%M:%SZ.hst
|
counterfile d3d/irena-%Y-%m-%dT%H:%M:%SZ.hst
|
||||||
socket unix irena-control interactive force
|
socket unix irena-control interactive force
|
||||||
cron next init 60 irena pres/inj
|
cron next init 60 script d3dinit.rc
|
||||||
|
|
|
||||||
4
d3dinit.rc
Normal file
4
d3dinit.rc
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
irena pres/inj
|
||||||
|
irena v rtc_drift[3] = 0x10700
|
||||||
|
clock_sync 3600
|
||||||
|
set_clock drift config
|
||||||
178
irena.c
178
irena.c
|
|
@ -29,12 +29,21 @@ const char version[] = "$Id$";
|
||||||
FILE *mout;
|
FILE *mout;
|
||||||
|
|
||||||
int maintainance = 0;
|
int maintainance = 0;
|
||||||
|
|
||||||
int verbosity[2] = {1,1};
|
int verbosity[2] = {1,1};
|
||||||
|
int in_prompt;
|
||||||
|
|
||||||
|
void check_prompt()
|
||||||
|
{
|
||||||
|
if (in_prompt==1) {
|
||||||
|
fprintf(mout, "\n");
|
||||||
|
in_prompt = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void silent(int v) { if (verbosity[0] < v) verbosity[1] = 0; }
|
static inline void silent(int v) { if (verbosity[0] < v) verbosity[1] = 0; }
|
||||||
static inline void unsilent() { verbosity[1] = verbosity[0]; }
|
static inline void unsilent() { verbosity[1] = verbosity[0]; }
|
||||||
static inline void loud(int v) { if (v > verbosity[0]) verbosity[1] = v; }
|
static inline void loud(int v) { if (v > verbosity[0]) verbosity[1] = v; }
|
||||||
static inline int verbose(int v) { v = verbosity[1] >= v; unsilent(); return v; }
|
static inline int verbose(int v) { v = verbosity[1] >= v; unsilent(); if (v) check_prompt(); return v; }
|
||||||
|
|
||||||
// replacement for perror()
|
// replacement for perror()
|
||||||
void merror(const char *s)
|
void merror(const char *s)
|
||||||
|
|
@ -941,10 +950,10 @@ int config_status(int na, char **av)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(mout, "%s %s[%u] %g %g %g %g %s tau %d flags 0x%04x reset %d\n",
|
fprintf(mout, "%s %s[%u] %g %g %g %g %s tau %d reset %d flags 0x%04x\n",
|
||||||
av[0], st->name, index,
|
av[0], st->name, index,
|
||||||
st->limits[0], st->limits[1], st->limits[2], st->limits[3],
|
st->limits[0], st->limits[1], st->limits[2], st->limits[3],
|
||||||
st->units, st->tau, st->flags, st->reset_delay);
|
st->units, st->tau, st->reset_delay, st->flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -977,6 +986,16 @@ struct line_buffer {
|
||||||
static inline
|
static inline
|
||||||
void buffer_reset(struct line_buffer *b) { b->size = b->read = 0; }
|
void buffer_reset(struct line_buffer *b) { b->size = b->read = 0; }
|
||||||
|
|
||||||
|
void reprint_line(struct line_buffer *b)
|
||||||
|
{
|
||||||
|
// in case the prompt was garbled
|
||||||
|
int n = read(b->fd, b->buf + b->size, 4095 - b->size);
|
||||||
|
if (n>0)
|
||||||
|
b->size += n;
|
||||||
|
b->buf[b->size] = 0;
|
||||||
|
fprintf(mout, "%.*s", b->size - b->read, b->buf + b->read);
|
||||||
|
}
|
||||||
|
|
||||||
char *get_line(struct line_buffer *b, unsigned int ev)
|
char *get_line(struct line_buffer *b, unsigned int ev)
|
||||||
{
|
{
|
||||||
if (b->fd < 0)
|
if (b->fd < 0)
|
||||||
|
|
@ -1092,6 +1111,7 @@ int arm_reset()
|
||||||
arm_reset_uart(i_buf.fd, reset_flags);
|
arm_reset_uart(i_buf.fd, reset_flags);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
if (verbose(0))
|
||||||
fprintf(mout, "Sent hardware RESET, mode %d\n", reset_flags);
|
fprintf(mout, "Sent hardware RESET, mode %d\n", reset_flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1162,10 +1182,9 @@ int split(char *l, int n, char *sp[])
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsplit(char *l, int n)
|
void unsplit(char *s, int n)
|
||||||
{
|
{
|
||||||
int i = 1;
|
int i = 1;
|
||||||
char *s = l;
|
|
||||||
while (i<n) {
|
while (i<n) {
|
||||||
s = index(s, 0);
|
s = index(s, 0);
|
||||||
*s = ' ';
|
*s = ' ';
|
||||||
|
|
@ -1223,6 +1242,7 @@ int base64_decode(const char *l, unsigned char *b, size_t n)
|
||||||
else if (!i && (!c || c=='\n'))
|
else if (!i && (!c || c=='\n'))
|
||||||
return m;
|
return m;
|
||||||
else if (c&0x80 || !bb[i] && c!='A') {
|
else if (c&0x80 || !bb[i] && c!='A') {
|
||||||
|
if (verbose(0))
|
||||||
fprintf(mout, "Base64 format error: %s\n", l);
|
fprintf(mout, "Base64 format error: %s\n", l);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1288,7 +1308,7 @@ int base85_decode(const char *l, unsigned char *b, size_t n)
|
||||||
l++;
|
l++;
|
||||||
int ll = base85_decode1(l, (unsigned int*)(b+m));
|
int ll = base85_decode1(l, (unsigned int*)(b+m));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
if (*l && verbose(2))
|
if (*l && verbose(0))
|
||||||
fprintf(mout, "invalid base85: «%s»\n", l);
|
fprintf(mout, "invalid base85: «%s»\n", l);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
@ -2168,64 +2188,34 @@ static inline unsigned char b64_chr(unsigned int c)
|
||||||
return e[c&0x3f];
|
return e[c&0x3f];
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_file_64(const char *fn)
|
int process_cmd(char *l);
|
||||||
|
|
||||||
|
int send_file(const char *fn, const char *cfmt, unsigned int drop)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(fn, "r");
|
// cfmt must have at most two %i formats.
|
||||||
if (!f) {
|
const char *s = cfmt;
|
||||||
merror(fn);
|
int i= 0;
|
||||||
return -2;
|
while (s) {
|
||||||
|
s = index(s, '%');
|
||||||
|
s++;
|
||||||
|
if (*s=='%') {
|
||||||
|
s++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
unsigned char buf[512];
|
if (i >= 2) {
|
||||||
int n;
|
if (verbose(-1))
|
||||||
while ((n = fread(buf, 1, sizeof(buf), f))) {
|
fprintf(mout, "more than two in parameters «%s»\n", cfmt);
|
||||||
if (n<sizeof(buf))
|
return -3;
|
||||||
memset(buf+n, 0, sizeof(buf)-n);
|
|
||||||
n = sizeof(buf);
|
|
||||||
n = (n+3) & ~3; // NOP
|
|
||||||
for (int i=0; i < n; ) {
|
|
||||||
char cmd[64];
|
|
||||||
int retry = 0;
|
|
||||||
int c = snprintf(cmd, 64, "v f[%d]=:=", i>>2);
|
|
||||||
while (c<58) {
|
|
||||||
int nn = -i & 3;
|
|
||||||
if (c < 54 || nn > n-i)
|
|
||||||
nn = n-i;
|
|
||||||
if (!nn)
|
|
||||||
break;
|
|
||||||
unsigned char a1, a2=0, a3=0;
|
|
||||||
a1 = buf[i++];
|
|
||||||
if (nn>1) a2 = buf[i++];
|
|
||||||
if (nn>2) a3 = buf[i++];
|
|
||||||
cmd[c++] = b64_chr(a1>>2);
|
|
||||||
cmd[c++] = b64_chr((a1<<4) | (a2>>4));
|
|
||||||
cmd[c++] = nn>1 ? b64_chr((a2<<2) | (a3>>6)) : '=';
|
|
||||||
cmd[c++] = nn>2 ? b64_chr(a3) : '=';
|
|
||||||
}
|
}
|
||||||
cmd[c++] = 0;
|
while (index(".-+#0123456789", *s)) s++;
|
||||||
while (retry<3) {
|
if (!*s || !index("diuoOxX", *s)) {
|
||||||
loud(2);
|
if (verbose(-1))
|
||||||
while (-2==send_irena_command(cmd))
|
fprintf(mout, "invalid format «%s»\n", cfmt);
|
||||||
poll_uart(1);
|
return -3;
|
||||||
char *res = poll_response(2);
|
|
||||||
if (!res)
|
|
||||||
fprintf(mout, "timeout for cmd «%s»\n", cmd);
|
|
||||||
else if (strncmp(res+1, "303", 3))
|
|
||||||
fprintf(mout, "invalid response to «%s» → «%s»\n", cmd, res);
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
poll_uart(0);
|
|
||||||
retry ++;
|
|
||||||
}
|
}
|
||||||
if (retry >= 3)
|
i++;
|
||||||
break;
|
|
||||||
}
|
|
||||||
do_cron(0, CR_BUFFER, 1);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_file_85(const char *fn)
|
|
||||||
{
|
|
||||||
FILE *f = fopen(fn, "r");
|
FILE *f = fopen(fn, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
merror(fn);
|
merror(fn);
|
||||||
|
|
@ -2233,10 +2223,19 @@ int send_file_85(const char *fn)
|
||||||
}
|
}
|
||||||
unsigned int buf[128];
|
unsigned int buf[128];
|
||||||
int n;
|
int n;
|
||||||
|
int a = 0;
|
||||||
while ((n = fread(buf, 1, sizeof(buf), f))) {
|
while ((n = fread(buf, 1, sizeof(buf), f))) {
|
||||||
if (n<sizeof(buf))
|
if (n<sizeof(buf))
|
||||||
memset(buf+n, 0, sizeof(buf)-n);
|
memset(buf+n, 0, sizeof(buf)-n);
|
||||||
n = sizeof(buf);
|
// Drop blocks that are only 0xff, those
|
||||||
|
// are unused blocks in the flash filesystem.
|
||||||
|
int d = 1;
|
||||||
|
if (drop) while (d<128 && buf[d]==buf[0]) d++;
|
||||||
|
if (d>=128 && buf[0]==0xffffffff) {
|
||||||
|
if (verbose(2))
|
||||||
|
fprintf(mout, "dropping block %d\n", a/128);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (int i=0; i<128; ) {
|
for (int i=0; i<128; ) {
|
||||||
char cmd[64];
|
char cmd[64];
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
|
|
@ -2258,9 +2257,18 @@ int send_file_85(const char *fn)
|
||||||
retry ++;
|
retry ++;
|
||||||
}
|
}
|
||||||
if (retry >= 3)
|
if (retry >= 3)
|
||||||
break;
|
return -1;
|
||||||
|
}
|
||||||
|
if (cfmt) {
|
||||||
|
char cmd[128];
|
||||||
|
int cs = snprintf(cmd, 128, cfmt, a, n);
|
||||||
|
if (cs <= 127)
|
||||||
|
process_cmd(cmd);
|
||||||
|
else if (verbose(-1))
|
||||||
|
fprintf(mout, "sendfile format too long «%s»\n", cmd);
|
||||||
}
|
}
|
||||||
do_cron(0, CR_BUFFER, 1);
|
do_cron(0, CR_BUFFER, 1);
|
||||||
|
a += n;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -2274,7 +2282,16 @@ int set_clock(int do_sleep)
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
if (do_sleep) {
|
if (do_sleep) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
poll_uart(1);
|
||||||
if (!clock_gettime(CLOCK_REALTIME, &ts)) {
|
if (!clock_gettime(CLOCK_REALTIME, &ts)) {
|
||||||
|
while (ts.tv_nsec < 750000000) {
|
||||||
|
ts.tv_nsec += 100000000;
|
||||||
|
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, 0);
|
||||||
|
if (verbose(2))
|
||||||
|
fprintf(mout, "slept 100ms ns=%lu\n", ts.tv_nsec);
|
||||||
|
poll_uart(1);
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
}
|
||||||
ts.tv_sec++;
|
ts.tv_sec++;
|
||||||
t = ts.tv_sec;
|
t = ts.tv_sec;
|
||||||
ts.tv_nsec=0;
|
ts.tv_nsec=0;
|
||||||
|
|
@ -2344,6 +2361,7 @@ const char *cmd_socket_name() {
|
||||||
int close_cmd_socket()
|
int close_cmd_socket()
|
||||||
{
|
{
|
||||||
if (cmd_socket_fd >= 0) {
|
if (cmd_socket_fd >= 0) {
|
||||||
|
if (verbose(1))
|
||||||
fprintf(mout, "closing cmd socket: «%s»\n", cmd_socket_name());
|
fprintf(mout, "closing cmd socket: «%s»\n", cmd_socket_name());
|
||||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, cmd_socket_fd, 0);
|
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, cmd_socket_fd, 0);
|
||||||
close(cmd_socket_fd);
|
close(cmd_socket_fd);
|
||||||
|
|
@ -2604,7 +2622,7 @@ struct numbers {
|
||||||
{.name="fct_packets", .doc="packets", .i=&fct_packets, .flags=NU_INT},
|
{.name="fct_packets", .doc="packets", .i=&fct_packets, .flags=NU_INT},
|
||||||
{.name="clock_sync", .doc="seconds", .u=&clock_cadence, .flags=NU_INT},
|
{.name="clock_sync", .doc="seconds", .u=&clock_cadence, .flags=NU_INT},
|
||||||
{.name="clock_mod", .doc="seconds", .u=&clock_modulus, .flags=NU_INT},
|
{.name="clock_mod", .doc="seconds", .u=&clock_modulus, .flags=NU_INT},
|
||||||
{.name="clock_sleep", .doc="bool", .i=&clock_sleep, .flags=NU_INT},
|
{.name="clock_sleep", .doc="(1=sleep,2=drift)", .i=&clock_sleep, .flags=NU_INT},
|
||||||
{.name="reset_cadence", .doc="seconds", .i=&status_reset_cadence, .flags=NU_INT},
|
{.name="reset_cadence", .doc="seconds", .i=&status_reset_cadence, .flags=NU_INT},
|
||||||
{.name="last_reset", .doc="time", .t=&last_status_reset, .flags=NU_TIME},
|
{.name="last_reset", .doc="time", .t=&last_status_reset, .flags=NU_TIME},
|
||||||
{.name="init_time", .doc="time", .t=&init_time, .flags=NU_TIME},
|
{.name="init_time", .doc="time", .t=&init_time, .flags=NU_TIME},
|
||||||
|
|
@ -2659,7 +2677,6 @@ void print_numbers(FILE *f)
|
||||||
print_number(f, nu);
|
print_number(f, nu);
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_cmd(char *l);
|
|
||||||
int process_script(const char *fn)
|
int process_script(const char *fn)
|
||||||
{
|
{
|
||||||
static int recursion = 0;
|
static int recursion = 0;
|
||||||
|
|
@ -2699,6 +2716,7 @@ int process_cmd(char *l)
|
||||||
int na = split(l, 10, av);
|
int na = split(l, 10, av);
|
||||||
if (!na)
|
if (!na)
|
||||||
return 0;
|
return 0;
|
||||||
|
check_prompt();
|
||||||
if (verbose(2) || !strcmp(av[0], "echo")) {
|
if (verbose(2) || !strcmp(av[0], "echo")) {
|
||||||
fprintf(mout, "CMD:");
|
fprintf(mout, "CMD:");
|
||||||
for (int i=0; i<na; i++)
|
for (int i=0; i<na; i++)
|
||||||
|
|
@ -2731,6 +2749,7 @@ int process_cmd(char *l)
|
||||||
"\tcron [«index» [«flags»… [«delay» «cmd»]]]\n"
|
"\tcron [«index» [«flags»… [«delay» «cmd»]]]\n"
|
||||||
"\tcron force «flags»… [«times»]\n"
|
"\tcron force «flags»… [«times»]\n"
|
||||||
"\tcron «index» delete\n"
|
"\tcron «index» delete\n"
|
||||||
|
"\tsendfile «filename» [drop] [«command»]\n"
|
||||||
"\t«number» [[«index»]] [«value» …]\n"
|
"\t«number» [[«index»]] [«value» …]\n"
|
||||||
"\n"
|
"\n"
|
||||||
);
|
);
|
||||||
|
|
@ -2816,11 +2835,18 @@ int process_cmd(char *l)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(av[0], "sendfile")) {
|
if (!strcmp(av[0], "sendfile")) {
|
||||||
if (na!=2) {
|
char *cmd = 0;
|
||||||
fprintf(mout, "usage: sendfile «filename»\n");
|
int drop = 0;
|
||||||
return -1;
|
int i = 2;
|
||||||
|
if (na>2 && !strcmp(av[2], "drop")) {
|
||||||
|
drop = 1;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
return send_file_85(av[1]);
|
if (na>i) {
|
||||||
|
unsplit(av[i], na-i);
|
||||||
|
cmd = av[i];
|
||||||
|
}
|
||||||
|
return send_file(av[1], cmd, drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(av[0], "uart")) {
|
if (!strcmp(av[0], "uart")) {
|
||||||
|
|
@ -2877,7 +2903,7 @@ int process_cmd(char *l)
|
||||||
else if (!strcmp(av[1], "drift")) do_sleep = 2;
|
else if (!strcmp(av[1], "drift")) do_sleep = 2;
|
||||||
else if (!strcmp(av[1], "config")) config = 1;
|
else if (!strcmp(av[1], "config")) config = 1;
|
||||||
else do_sleep = -1;
|
else do_sleep = -1;
|
||||||
if (na>3 || na>2 && (!do_sleep || strcmp(av[1], "config")))
|
if (na>3 || na>2 && (!do_sleep || strcmp(av[2], "config")))
|
||||||
do_sleep = -1;
|
do_sleep = -1;
|
||||||
if (do_sleep < 0) {
|
if (do_sleep < 0) {
|
||||||
fprintf(mout, "usage: set_clock [sleep|drift] [config]\n");
|
fprintf(mout, "usage: set_clock [sleep|drift] [config]\n");
|
||||||
|
|
@ -3145,6 +3171,7 @@ int main(int argc, char **argv)
|
||||||
if (isatty(0) && isatty(2)) {
|
if (isatty(0) && isatty(2)) {
|
||||||
prompt = "IRENA> ";
|
prompt = "IRENA> ";
|
||||||
fprintf(mout, prompt);
|
fprintf(mout, prompt);
|
||||||
|
in_prompt = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_priorities();
|
reset_priorities();
|
||||||
|
|
@ -3160,8 +3187,8 @@ int main(int argc, char **argv)
|
||||||
int n = epoll_wait(epoll_fd, eev, 2, 1000);
|
int n = epoll_wait(epoll_fd, eev, 2, 1000);
|
||||||
time_t t = time(0);
|
time_t t = time(0);
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i<n; i++) {
|
||||||
if (eev[i].events != EPOLLIN)
|
if (eev[i].events != EPOLLIN && verbose(2))
|
||||||
debug("epoll: fd=%d events=0x%x\n", eev[i].data.fd, eev[i].events);
|
fprintf(mout, "epoll: fd=%d events=0x%x\n", eev[i].data.fd, eev[i].events);
|
||||||
if (eev[i].data.fd == cmd_socket_fd)
|
if (eev[i].data.fd == cmd_socket_fd)
|
||||||
accept_cmd_socket(&s_buf, cmd_socket_fd);
|
accept_cmd_socket(&s_buf, cmd_socket_fd);
|
||||||
else if (eev[i].data.fd == s_buf.fd) {
|
else if (eev[i].data.fd == s_buf.fd) {
|
||||||
|
|
@ -3177,14 +3204,23 @@ int main(int argc, char **argv)
|
||||||
poll_uart(eev[i].events);
|
poll_uart(eev[i].events);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *l = get_line(&c_buf, eev[i].events);
|
int do_read = eev[i].events;
|
||||||
|
if (prompt && in_prompt==2 && do_read) {
|
||||||
|
fprintf(mout, prompt);
|
||||||
|
reprint_line(&c_buf);
|
||||||
|
in_prompt = 1;
|
||||||
|
do_read = 0;
|
||||||
|
}
|
||||||
|
char *l = get_line(&c_buf, do_read);
|
||||||
while (l) {
|
while (l) {
|
||||||
|
in_prompt = 0;
|
||||||
process_cmd(l);
|
process_cmd(l);
|
||||||
if (prompt) {
|
if (prompt) {
|
||||||
if (maintainance)
|
if (maintainance)
|
||||||
fprintf(stderr, "M:%s", prompt);
|
fprintf(stderr, "M:%s", prompt);
|
||||||
else
|
else
|
||||||
fprintf(stderr, prompt);
|
fprintf(stderr, prompt);
|
||||||
|
in_prompt = 1;
|
||||||
}
|
}
|
||||||
l = get_line(&c_buf, 0);
|
l = get_line(&c_buf, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue