Changeset 5632
Restore the coloured CLI prompt functionality
Comitted by:
mjagdis
Date:
Feb 14 2010 * 23:33 (about 1 year ago)
Affected files:
callweaver/trunk/corelib/console.c (diff)
callweaver/trunk/corelib/terminal.c (diff)
callweaver/trunk/corelib/terminal.h (diff)
callweaver/trunk/corelib/console.c (unified diff)
| r5630 | r5632 | |
|---|---|---|
| 36 | 36 | |
| 37 | 37 | CALLWEAVER_FILE_VERSION("$HeadURL$", "$Revision$") |
| 38 | 38 | |
| 39 | #include <callweaver/dynstr.h> | |
| 39 | 40 | #include <callweaver/app.h> |
| 40 | 41 | #include <callweaver/cli.h> |
| 41 | 42 | #include <callweaver/time.h> |
| --- | --- | |
| 56 | 57 | #endif |
| 57 | 58 | |
| 58 | 59 | |
| 59 | #define CALLWEAVER_PROMPT "%s*CLI> " | |
| 60 | #define CALLWEAVER_PROMPT "%H*CLI%# " | |
| 60 | 61 | |
| 61 | 62 | |
| 62 | 63 | static struct { |
| --- | --- | |
| 84 | 85 | static unsigned int remotepid; |
| 85 | 86 | static char remoteversion[256]; |
| 86 | 87 | |
| 88 | static struct cw_dynstr prompt = CW_DYNSTR_INIT; | |
| 89 | ||
| 87 | 90 | static char *clr_eol; |
| 88 | 91 | |
| 89 | 92 | static int prompting; |
| --- | --- | |
| 146 | 149 | } |
| 147 | 150 | |
| 148 | 151 | |
| 149 | static char *cli_prompt(void) | |
| 152 | static int promptput(int c) | |
| 150 | 153 | { |
| 151 | static char prompt[200]; | |
| 152 | char *pfmt; | |
| 153 | int color_used = 0; | |
| 154 | #if 0 | |
| 155 | char term_code[20]; | |
| 156 | #endif | |
| 154 | cw_dynstr_printf(&prompt, "%c", c); | |
| 155 | return c; | |
| 156 | } | |
| 157 | 157 | |
| 158 | if ((pfmt = getenv("CALLWEAVER_PROMPT"))) { | |
| 159 | char *t = pfmt, *p = prompt; | |
| 160 | memset(prompt, 0, sizeof(prompt)); | |
| 161 | while (*t != '\0' && *p < sizeof(prompt)) { | |
| 162 | if (*t == '%') { | |
| 163 | #if 0 | |
| 164 | int i; | |
| 165 | #endif | |
| 166 | struct timeval tv; | |
| 167 | struct tm tm; | |
| 158 | static void promptattr(const char **attr) | |
| 159 | { | |
| 160 | cw_dynstr_printf(&prompt, "%c", RL_PROMPT_START_IGNORE); | |
| 161 | terminal_write_attr(*attr, promptput); | |
| 162 | cw_dynstr_printf(&prompt, "%c", RL_PROMPT_END_IGNORE); | |
| 163 | free((void *)(*attr)); | |
| 164 | *attr = NULL; | |
| 165 | } | |
| 166 | ||
| 167 | static void set_prompt(const char *pfmt) | |
| 168 | { | |
| 169 | struct tm tm; | |
| 170 | struct timeval tv; | |
| 171 | const char *t, *p; | |
| 172 | const char *astart = NULL, *aend = NULL; | |
| 173 | ||
| 174 | cw_dynstr_reset(&prompt); | |
| 175 | ||
| 176 | if (!pfmt) | |
| 177 | pfmt = CALLWEAVER_PROMPT; | |
| 178 | ||
| 179 | t = pfmt; | |
| 180 | while ((p = strchr(t, '%'))) { | |
| 181 | cw_dynstr_printf(&prompt, "%.*s", (int)(p - t), t); | |
| 182 | t = p + 1; | |
| 168 | 183 | #ifdef linux |
| 169 | FILE *LOADAVG; | |
| 184 | FILE *LOADAVG; | |
| 170 | 185 | #endif |
| 171 | 186 | |
| 187 | switch (*t) { | |
| 188 | case 'C': { /* colour */ | |
| 189 | char *q = NULL; | |
| 190 | int fg, bg, i; | |
| 191 | ||
| 192 | if (aend) | |
| 193 | promptattr(&aend); | |
| 194 | if (t[1] == '{' && (p = strchr(&t[2], '}'))) { | |
| 195 | q = alloca(p - &t[2] + 1); | |
| 196 | memcpy(q, &t[2], p - &t[2]); | |
| 197 | q[p - &t[2]] = '\0'; | |
| 198 | t = p; | |
| 199 | } else if (t[1] == '*') { | |
| 200 | t++; | |
| 201 | } else if (sscanf(&t[1], "%d;%d%n", &fg, &bg, &i) >= 2 && fg >= 0 && fg <= 16 && bg >= 0 && bg <= 16) { | |
| 202 | q = alloca(sizeof("fg=XX,bg=XX")); | |
| 203 | sprintf(q, "fg=%d,bg=%d", fg, bg); | |
| 204 | t += i; | |
| 205 | } else if (sscanf(&t[1], "%d%n", &fg, &i) >= 1 && fg >= 0 && fg <= 16) { | |
| 206 | q = alloca(sizeof("fg=XX")); | |
| 207 | sprintf(q, "fg=%d", fg); | |
| 208 | t += i; | |
| 209 | } | |
| 210 | if (q) { | |
| 211 | terminal_highlight(&astart, &aend, q); | |
| 212 | if (astart) | |
| 213 | promptattr(&astart); | |
| 214 | } | |
| 215 | break; | |
| 216 | } | |
| 217 | case 'd': /* date */ | |
| 218 | cw_dynstr_need(&prompt, sizeof("YYYY-MM-DD")); | |
| 219 | tv = cw_tvnow(); | |
| 220 | if (localtime_r(&(tv.tv_sec), &tm)) | |
| 221 | strftime(&prompt.data[prompt.used], prompt.size - prompt.used, "%Y-%m-%d", &tm); | |
| 222 | break; | |
| 223 | case 'H': /* short remote hostname */ | |
| 224 | if ((p = strchr(remotehostname, '.'))) { | |
| 225 | cw_dynstr_printf(&prompt, "%.*s", (int)(p - remotehostname), remotehostname); | |
| 226 | break; | |
| 227 | } | |
| 228 | /* fall through */ | |
| 229 | case 'h': /* remote hostname */ | |
| 230 | cw_dynstr_printf(&prompt, "%s", remotehostname); | |
| 231 | break; | |
| 232 | #ifdef linux | |
| 233 | case 'l': /* load avg */ | |
| 172 | 234 | t++; |
| 173 | switch (*t) { | |
| 174 | case 'C': /* color */ | |
| 175 | t++; | |
| 176 | #if 0 | |
| 177 | if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) { | |
| 178 | strncat(p, cw_term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1); | |
| 179 | t += i - 1; | |
| 180 | } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) { | |
| 181 | strncat(p, cw_term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1); | |
| 182 | t += i - 1; | |
| 235 | if ((LOADAVG = fopen("/proc/loadavg", "r"))) { | |
| 236 | float avg1, avg2, avg3; | |
| 237 | int actproc, totproc, npid, which; | |
| 238 | fscanf(LOADAVG, "%f %f %f %d/%d %d", &avg1, &avg2, &avg3, &actproc, &totproc, &npid); | |
| 239 | if (sscanf(t, "%d", &which) == 1) { | |
| 240 | switch (which) { | |
| 241 | case 1: | |
| 242 | cw_dynstr_printf(&prompt, "%.2f", avg1); | |
| 243 | break; | |
| 244 | case 2: | |
| 245 | cw_dynstr_printf(&prompt, "%.2f", avg2); | |
| 246 | break; | |
| 247 | case 3: | |
| 248 | cw_dynstr_printf(&prompt, "%.2f", avg3); | |
| 249 | break; | |
| 250 | case 4: | |
| 251 | cw_dynstr_printf(&prompt, "%d/%d", actproc, totproc); | |
| 252 | break; | |
| 253 | case 5: | |
| 254 | cw_dynstr_printf(&prompt, "%d", npid); | |
| 255 | break; | |
| 183 | 256 | } |
| 184 | ||
| 185 | /* If the color has been reset correctly, then there's no need to reset it later */ | |
| 186 | if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) { | |
| 187 | color_used = 0; | |
| 188 | } else { | |
| 189 | color_used = 1; | |
| 190 | } | |
| 191 | #endif | |
| 192 | break; | |
| 193 | case 'd': /* date */ | |
| 194 | memset(&tm, 0, sizeof(struct tm)); | |
| 195 | tv = cw_tvnow(); | |
| 196 | if (localtime_r(&(tv.tv_sec), &tm)) { | |
| 197 | strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm); | |
| 198 | } | |
| 199 | break; | |
| 200 | case 'h': /* remote hostname */ | |
| 201 | strncat(p, remotehostname, sizeof(prompt) - strlen(prompt) - 1); | |
| 202 | break; | |
| 203 | case 'H': { /* short remote hostname */ | |
| 204 | char *q = strchr(remotehostname, '.'); | |
| 205 | int n = (q ? q - remotehostname : strlen(remotehostname)); | |
| 206 | int l = sizeof(prompt) - strlen(prompt) - 1; | |
| 207 | strncat(p, remotehostname, n > l ? l : n); | |
| 208 | break; | |
| 209 | 257 | } |
| 210 | #ifdef linux | |
| 211 | case 'l': /* load avg */ | |
| 212 | t++; | |
| 213 | if ((LOADAVG = fopen("/proc/loadavg", "r"))) { | |
| 214 | float avg1, avg2, avg3; | |
| 215 | int actproc, totproc, npid, which; | |
| 216 | fscanf(LOADAVG, "%f %f %f %d/%d %d", | |
| 217 | &avg1, &avg2, &avg3, &actproc, &totproc, &npid); | |
| 218 | if (sscanf(t, "%d", &which) == 1) { | |
| 219 | switch (which) { | |
| 220 | case 1: | |
| 221 | snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1); | |
| 222 | break; | |
| 223 | case 2: | |
| 224 | snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2); | |
| 225 | break; | |
| 226 | case 3: | |
| 227 | snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3); | |
| 228 | break; | |
| 229 | case 4: | |
| 230 | snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc); | |
| 231 | break; | |
| 232 | case 5: | |
| 233 | snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid); | |
| 234 | break; | |
| 235 | } | |
| 236 | } | |
| 237 | } | |
| 238 | break; | |
| 239 | #endif | |
| 240 | case 't': /* time */ | |
| 241 | memset(&tm, 0, sizeof(struct tm)); | |
| 242 | tv = cw_tvnow(); | |
| 243 | if (localtime_r(&(tv.tv_sec), &tm)) { | |
| 244 | strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm); | |
| 245 | } | |
| 246 | break; | |
| 247 | case '#': /* process console or remote? */ | |
| 248 | if (! option_remote) { | |
| 249 | strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1); | |
| 250 | } else { | |
| 251 | strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1); | |
| 252 | } | |
| 253 | break; | |
| 254 | case '%': /* literal % */ | |
| 255 | strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1); | |
| 256 | break; | |
| 257 | case '\0': /* % is last character - prevent bug */ | |
| 258 | t--; | |
| 259 | break; | |
| 260 | 258 | } |
| 261 | while (*p != '\0') { | |
| 262 | p++; | |
| 263 | } | |
| 264 | t++; | |
| 265 | } else { | |
| 266 | *p = *t; | |
| 267 | p++; | |
| 268 | t++; | |
| 269 | } | |
| 270 | } | |
| 271 | if (color_used) { | |
| 272 | /* Force colors back to normal at end */ | |
| 273 | #if 0 | |
| 274 | cw_term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code)); | |
| 275 | if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) { | |
| 276 | strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code)); | |
| 277 | } else { | |
| 278 | strncat(p, term_code, sizeof(term_code)); | |
| 279 | } | |
| 259 | break; | |
| 280 | 260 | #endif |
| 261 | case 't': /* time */ | |
| 262 | cw_dynstr_need(&prompt, sizeof("HH:MM:SS")); | |
| 263 | tv = cw_tvnow(); | |
| 264 | if (localtime_r(&(tv.tv_sec), &tm)) | |
| 265 | strftime(&prompt.data[prompt.used], prompt.size - prompt.used, "%H:%M:%S", &tm); | |
| 266 | break; | |
| 267 | case '#': /* process console or remote? */ | |
| 268 | cw_dynstr_printf(&prompt, "%c", (option_remote ? '>' : '#')); | |
| 269 | break; | |
| 270 | case '%': /* literal % */ | |
| 271 | cw_dynstr_printf(&prompt, "%c", '%'); | |
| 272 | break; | |
| 273 | case '\0': /* % is last character - prevent bug */ | |
| 274 | t--; | |
| 275 | break; | |
| 281 | 276 | } |
| 282 | } else | |
| 283 | snprintf(prompt, sizeof(prompt), CALLWEAVER_PROMPT, remotehostname); | |
| 277 | t++; | |
| 278 | } | |
| 279 | cw_dynstr_printf(&prompt, "%s", t); | |
| 284 | 280 | |
| 285 | return (prompt); | |
| 281 | if (aend) | |
| 282 | promptattr(&aend); | |
| 286 | 283 | } |
| 287 | 284 | |
| 288 | 285 | |
| 286 | static char *cli_prompt(void) | |
| 287 | { | |
| 288 | return prompt.data; | |
| 289 | } | |
| 290 | ||
| 291 | ||
| 289 | 292 | static int read_message(int s, int nresp) |
| 290 | 293 | { |
| 291 | 294 | static char buf_level[16]; |
| --- | --- | |
| 486 | 489 | if (level != CW_EVENT_NUM_VERBOSE) { |
| 487 | 490 | fwrite(field[F_DATE].buf, 1, field_len[F_DATE], stdout); |
| 488 | 491 | if (level >= 0 && level < arraysize(level_attr) && level_attr[level].on) |
| 489 | terminal_write_attr(level_attr[level].on); | |
| 492 | terminal_write_attr(level_attr[level].on, putchar); | |
| 490 | 493 | fwrite(field[F_LEVEL].buf, 1, field_len[F_LEVEL], stdout); |
| 491 | 494 | if (level >= 0 && level < arraysize(level_attr) && level_attr[level].off) |
| 492 | terminal_write_attr(level_attr[level].off); | |
| 495 | terminal_write_attr(level_attr[level].off, putchar); | |
| 493 | 496 | putchar('['); |
| 494 | 497 | fwrite(field[F_THREADID].buf, 1, field_len[F_THREADID], stdout); |
| 495 | 498 | fwrite("]: ", 1, 3, stdout); |
| --- | --- | |
| 498 | 501 | fwrite(field[F_LINE].buf, 1, field_len[F_LINE], stdout); |
| 499 | 502 | putchar(' '); |
| 500 | 503 | if (bold_on) |
| 501 | terminal_write_attr(bold_on); | |
| 504 | terminal_write_attr(bold_on, putchar); | |
| 502 | 505 | fwrite(field[F_FUNCTION].buf, 1, field_len[F_FUNCTION], stdout); |
| 503 | 506 | if (bold_off) |
| 504 | terminal_write_attr(bold_off); | |
| 507 | terminal_write_attr(bold_off, putchar); | |
| 505 | 508 | fwrite(": ", 1, 2, stdout); |
| 506 | 509 | } |
| 507 | 510 | fwrite(key, 1, lval, stdout); |
| --- | --- | |
| 642 | 645 | cw_safe_system(s+1); |
| 643 | 646 | else |
| 644 | 647 | cw_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh"); |
| 648 | } else if (s[0] == '@') { | |
| 649 | if (!strncmp(&s[1], "set prompt ", sizeof("set prompt ") - 1)) { | |
| 650 | set_prompt(&s[sizeof("set prompt ") - 1]); | |
| 651 | rl_set_prompt(prompt.data); | |
| 652 | } else | |
| 653 | fprintf(stderr, "unknown command: %s\n", s); | |
| 645 | 654 | } else if (option_remote && (!strcasecmp(s, "quit") || !strcasecmp(s, "exit"))) { |
| 646 | 655 | console_cleanup(NULL); |
| 647 | 656 | exit(0); |
| --- | --- | |
| 832 | 841 | if (option_console && !fully_booted) |
| 833 | 842 | kill(cw_mainpid, SIGHUP); |
| 834 | 843 | |
| 844 | set_prompt(getenv("CALLWEAVER_PROMPT")); | |
| 845 | ||
| 835 | 846 | progress = 0; |
| 836 | 847 | prompting = 1; |
| 837 | 848 | rl_callback_handler_install(cli_prompt(), console_handler); |
callweaver/trunk/corelib/terminal.c (unified diff)
| r5619 | r5632 | |
|---|---|---|
| 96 | 96 | known = 0; |
| 97 | 97 | |
| 98 | 98 | col = &fg; |
| 99 | if (l > 3) { | |
| 99 | if (l >= 3) { | |
| 100 | 100 | if (!strncmp(spec, "bg=", 3)) { |
| 101 | 101 | col = &bg; |
| 102 | 102 | spec += 3; |
| --- | --- | |
| 107 | 107 | } |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | for (i = 0; i < sizeof(colours) / sizeof(colours[0]); i++) { | |
| 111 | if (l == colours[i].len && !strncmp(spec, colours[i].name, l)) { | |
| 112 | *col = i; | |
| 113 | known = 1; | |
| 114 | break; | |
| 110 | i = strtol(spec, &tmp, 10); | |
| 111 | if (tmp != spec && i < sizeof(colours) / sizeof(colours[0])) { | |
| 112 | *col = i; | |
| 113 | known = 1; | |
| 114 | } | |
| 115 | ||
| 116 | if (!known) { | |
| 117 | for (i = 0; i < sizeof(colours) / sizeof(colours[0]); i++) { | |
| 118 | if (l == colours[i].len && !strncmp(spec, colours[i].name, l)) { | |
| 119 | *col = i; | |
| 120 | known = 1; | |
| 121 | break; | |
| 122 | } | |
| 115 | 123 | } |
| 116 | 124 | } |
| 117 | 125 | |
| --- | --- | |
| 165 | 173 | } |
| 166 | 174 | |
| 167 | 175 | if (setab && bg != -1) { |
| 168 | p = tparm(setaf, bg); | |
| 176 | p = tparm(setab, bg); | |
| 169 | 177 | i = strlen(p); |
| 170 | 178 | bg_p = strcpy(alloca(i + 1), p); |
| 171 | 179 | l += i; |
| --- | --- | |
| 181 | 189 | } |
| 182 | 190 | |
| 183 | 191 | |
| 184 | int terminal_write_attr(const char *str) | |
| 192 | int terminal_write_attr(const char *str, int (*func)(int)) | |
| 185 | 193 | { |
| 186 | return putp(str); | |
| 194 | return tputs(str, 1, func); | |
| 187 | 195 | } |
| 188 | 196 | |
| 189 | 197 |
callweaver/trunk/corelib/terminal.h (unified diff)
| r5619 | r5632 | |
|---|---|---|
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | 19 | extern void terminal_highlight(const char **start, const char **end, const char *spec); |
| 20 | extern int terminal_write_attr(const char *str); | |
| 20 | extern int terminal_write_attr(const char *str, int (*putc)(int)); | |
| 21 | 21 | extern void terminal_init(void); |
| 22 | 22 | extern void terminal_set_icon(const char *s); |
![Home changeset 5632 [home]](/images/logo.png?1180520111)

RSS Feeds