/[baselayout]/trunk/src/libeinfo.c
Gentoo

Contents of /trunk/src/libeinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2973 - (show annotations) (download) (as text)
Wed Oct 3 12:55:27 2007 UTC (7 years, 1 month ago) by uberlord
File MIME type: text/x-csrc
File size: 12763 byte(s)
hide eprefix
1 /*
2 einfo.c
3 Gentoo informational functions
4 Copyright 2007 Gentoo Foundation
5 */
6
7 #include <sys/types.h>
8 #include <sys/ioctl.h>
9 #include <sys/stat.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <limits.h>
13 #include <stdarg.h>
14 #include <stdbool.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <syslog.h>
19 #include <unistd.h>
20
21 #include "einfo.h"
22 #include "rc.h"
23 #include "rc-misc.h"
24
25 #include "hidden-visibility.h"
26 hidden_proto(ecolor)
27 hidden_proto(ebegin)
28 hidden_proto(ebeginv)
29 hidden_proto(ebracket)
30 hidden_proto(eend)
31 hidden_proto(eendv)
32 hidden_proto(eerror)
33 hidden_proto(eerrorn)
34 hidden_proto(eerrorx)
35 hidden_proto(eindent)
36 hidden_proto(eindentv)
37 hidden_proto(einfo)
38 hidden_proto(einfon)
39 hidden_proto(einfov)
40 hidden_proto(einfovn)
41 hidden_proto(elog)
42 hidden_proto(eoutdent)
43 hidden_proto(eoutdentv)
44 hidden_proto(eprefix)
45 hidden_proto(ewarn)
46 hidden_proto(ewarnn)
47 hidden_proto(ewarnv)
48 hidden_proto(ewarnvn)
49 hidden_proto(ewarnx)
50 hidden_proto(ewend)
51 hidden_proto(ewendv)
52
53 /* Incase we cannot work out how many columns from ioctl, supply a default */
54 #define DEFAULT_COLS 80
55
56 #define OK "ok"
57 #define NOT_OK "!!"
58
59 #define CHECK_VERBOSE if (! is_env ("RC_VERBOSE", "yes")) return 0
60
61 /* Number of spaces for an indent */
62 #define INDENT_WIDTH 2
63
64 /* How wide can the indent go? */
65 #define INDENT_MAX 40
66
67 /* Default colours */
68 #define ECOLOR_GOOD_A "\033[32;01m"
69 #define ECOLOR_WARN_A "\033[33;01m"
70 #define ECOLOR_BAD_A "\033[31;01m"
71 #define ECOLOR_HILITE_A "\033[36;01m"
72 #define ECOLOR_BRACKET_A "\033[34;01m"
73 #define ECOLOR_NORMAL_A "\033[0m"
74 #define ECOLOR_FLUSH_A "\033[K"
75
76 /* A cheat sheet of colour capable terminals
77 This is taken from DIR_COLORS from GNU coreutils
78 We embed it here as we shouldn't depend on coreutils */
79 static const char *color_terms[] = {
80 "Eterm",
81 "ansi",
82 "color-xterm",
83 "con132x25",
84 "con132x30",
85 "con132x43",
86 "con132x60",
87 "con80x25",
88 "con80x28",
89 "con80x30",
90 "con80x43",
91 "con80x50",
92 "con80x60",
93 "cons25",
94 "console",
95 "cygwin",
96 "dtterm",
97 "gnome",
98 "konsole",
99 "kterm",
100 "linux",
101 "linux-c",
102 "mach-color",
103 "mlterm",
104 "putty",
105 "rxvt",
106 "rxvt-cygwin",
107 "rxvt-cygwin-native",
108 "rxvt-unicode",
109 "screen",
110 "screen-bce",
111 "screen-w",
112 "screen.linux",
113 "vt100",
114 "xterm",
115 "xterm-256color",
116 "xterm-color",
117 "xterm-debian",
118 NULL
119 };
120
121 static const char *term = NULL;
122 static bool term_is_cons25 = false;
123
124 /* A pointer to a string to prefix to einfo/ewarn/eerror messages */
125 static const char *_eprefix = NULL;
126
127 static bool is_env (const char *var, const char *val)
128 {
129 char *v;
130
131 if (! var)
132 return (false);
133
134 v = getenv (var);
135 if (! v)
136 return (val ? false : true);
137
138 return (strcasecmp (v, val) ? false : true);
139 }
140
141 static bool colour_terminal (FILE *f)
142 {
143 static int in_colour = -1;
144 int i = 0;
145
146 if (f && ! isatty (fileno (f)))
147 return (false);
148
149 if (is_env ("RC_NOCOLOR", "yes"))
150 return (false);
151
152 if (in_colour == 0)
153 return (false);
154 if (in_colour == 1)
155 return (true);
156
157 if (! term) {
158 term = getenv ("TERM");
159 if (! term)
160 return (false);
161 }
162
163 if (strcmp (term, "cons25") == 0)
164 term_is_cons25 = true;
165 else
166 term_is_cons25 = false;
167
168 while (color_terms[i]) {
169 if (strcmp (color_terms[i], term) == 0) {
170 in_colour = 1;
171 return (true);
172 }
173 i++;
174 }
175
176 in_colour = 0;
177 return (false);
178 }
179
180 static int get_term_columns (FILE *stream)
181 {
182 struct winsize ws;
183 char *env = getenv ("COLUMNS");
184 char *p;
185 int i;
186
187 if (env) {
188 i = strtol (env, &p, 10);
189 if (! *p)
190 return (i);
191 }
192
193 if (ioctl (fileno (stream), TIOCGWINSZ, &ws) == 0)
194 return (ws.ws_col);
195
196 return (DEFAULT_COLS);
197 }
198
199 void eprefix (const char *prefix)
200 {
201 _eprefix = prefix;
202 }
203 hidden_def(eprefix)
204
205 static void elogv (int level, const char *fmt, va_list ap)
206 {
207 char *e = getenv ("RC_ELOG");
208 va_list apc;
209
210 if (fmt && e) {
211 closelog ();
212 openlog (e, LOG_PID, LOG_DAEMON);
213 va_copy (apc, ap);
214 vsyslog (level, fmt, apc);
215 va_end (apc);
216 closelog ();
217 }
218 }
219
220 void elog (int level, const char *fmt, ...)
221 {
222 va_list ap;
223
224 va_start (ap, fmt);
225 elogv (level, fmt, ap);
226 va_end (ap);
227 }
228 hidden_def(elog)
229
230 static int _eindent (FILE *stream)
231 {
232 char *env = getenv ("RC_EINDENT");
233 int amount = 0;
234 char indent[INDENT_MAX];
235
236 if (env) {
237 errno = 0;
238 amount = strtol (env, NULL, 0);
239 if (errno != 0 || amount < 0)
240 amount = 0;
241 else if (amount > INDENT_MAX)
242 amount = INDENT_MAX;
243
244 if (amount > 0)
245 memset (indent, ' ', amount);
246 }
247
248 /* Terminate it */
249 memset (indent + amount, 0, 1);
250 return (fprintf (stream, "%s", indent));
251 }
252
253 static const char *_ecolor (FILE *f, einfo_color_t color)
254 {
255 const char *col = NULL;
256
257 if (! colour_terminal (f))
258 return ("");
259
260 switch (color) {
261 case ECOLOR_GOOD:
262 if (! (col = getenv ("ECOLOR_GOOD")))
263 col = ECOLOR_GOOD_A;
264 break;
265 case ECOLOR_WARN:
266 if (! (col = getenv ("ECOLOR_WARN")))
267 col = ECOLOR_WARN_A;
268 break;
269 case ECOLOR_BAD:
270 if (! (col = getenv ("ECOLOR_BAD")))
271 col = ECOLOR_BAD_A;
272 break;
273 case ECOLOR_HILITE:
274 if (! (col = getenv ("ECOLOR_HILITE")))
275 col = ECOLOR_HILITE_A;
276 break;
277 case ECOLOR_BRACKET:
278 if (! (col = getenv ("ECOLOR_BRACKET")))
279 col = ECOLOR_BRACKET_A;
280 break;
281 case ECOLOR_NORMAL:
282 col = ECOLOR_NORMAL_A;
283 break;
284 }
285
286 return (col);
287 }
288 hidden_def(ecolor)
289
290 const char *ecolor (einfo_color_t color)
291 {
292 return (_ecolor (NULL, color));
293 }
294
295 #define EINFOVN(_file, _color) \
296 if (_eprefix) \
297 fprintf (_file, "%s%s%s|", _ecolor (_file, _color), _eprefix, _ecolor (_file, ECOLOR_NORMAL)); \
298 fprintf (_file, " %s*%s ", _ecolor (_file, _color), _ecolor (_file, ECOLOR_NORMAL)); \
299 retval += _eindent (_file); \
300 { \
301 va_list _ap; \
302 va_copy (_ap, ap); \
303 retval += vfprintf (_file, fmt, _ap) + 3; \
304 va_end (_ap); \
305 } \
306 if (colour_terminal (_file)) \
307 fprintf (_file, ECOLOR_FLUSH_A);
308
309 static int _einfovn (const char *fmt, va_list ap)
310 {
311 int retval = 0;
312
313 EINFOVN (stdout, ECOLOR_GOOD);
314 return (retval);
315 }
316
317 static int _ewarnvn (const char *fmt, va_list ap)
318 {
319 int retval = 0;
320
321 EINFOVN (stdout, ECOLOR_WARN);
322 return (retval);
323 }
324
325 static int _eerrorvn (const char *fmt, va_list ap)
326 {
327 int retval = 0;
328
329 EINFOVN (stderr, ECOLOR_BAD);
330 return (retval);
331 }
332
333 int einfon (const char *fmt, ...)
334 {
335 int retval;
336 va_list ap;
337
338 if (! fmt || is_env ("RC_QUIET", "yes"))
339 return (0);
340
341 va_start (ap, fmt);
342 retval = _einfovn (fmt, ap);
343 va_end (ap);
344
345 return (retval);
346 }
347 hidden_def(einfon)
348
349 int ewarnn (const char *fmt, ...)
350 {
351 int retval;
352 va_list ap;
353
354 if (! fmt || is_env ("RC_QUIET", "yes"))
355 return (0);
356
357 va_start (ap, fmt);
358 retval = _ewarnvn (fmt, ap);
359 va_end (ap);
360
361 return (retval);
362 }
363 hidden_def(ewarnn)
364
365 int eerrorn (const char *fmt, ...)
366 {
367 int retval;
368 va_list ap;
369
370 va_start (ap, fmt);
371 retval = _eerrorvn (fmt, ap);
372 va_end (ap);
373
374 return (retval);
375 }
376 hidden_def(eerrorn)
377
378 int einfo (const char *fmt, ...)
379 {
380 int retval;
381 va_list ap;
382
383 if (! fmt || is_env ("RC_QUIET", "yes"))
384 return (0);
385
386 va_start (ap, fmt);
387 retval = _einfovn (fmt, ap);
388 retval += printf ("\n");
389 va_end (ap);
390
391 return (retval);
392 }
393 hidden_def(einfo)
394
395 int ewarn (const char *fmt, ...)
396 {
397 int retval;
398 va_list ap;
399
400 if (! fmt || is_env ("RC_QUIET", "yes"))
401 return (0);
402
403 va_start (ap, fmt);
404 elogv (LOG_WARNING, fmt, ap);
405 retval = _ewarnvn (fmt, ap);
406 retval += printf ("\n");
407 va_end (ap);
408
409 return (retval);
410 }
411 hidden_def(ewarn)
412
413 void ewarnx (const char *fmt, ...)
414 {
415 int retval;
416 va_list ap;
417
418 if (fmt && ! is_env ("RC_QUIET", "yes")) {
419 va_start (ap, fmt);
420 elogv (LOG_WARNING, fmt, ap);
421 retval = _ewarnvn (fmt, ap);
422 va_end (ap);
423 retval += printf ("\n");
424 }
425 exit (EXIT_FAILURE);
426 }
427 hidden_def(ewarnx)
428
429 int eerror (const char *fmt, ...)
430 {
431 int retval;
432 va_list ap;
433
434 if (! fmt)
435 return (0);
436
437 va_start (ap, fmt);
438 elogv (LOG_ERR, fmt, ap);
439 retval = _eerrorvn (fmt, ap);
440 va_end (ap);
441 retval += fprintf (stderr, "\n");
442
443 return (retval);
444 }
445 hidden_def(eerror)
446
447 void eerrorx (const char *fmt, ...)
448 {
449 va_list ap;
450
451 if (fmt) {
452 va_start (ap, fmt);
453 elogv (LOG_ERR, fmt, ap);
454 _eerrorvn (fmt, ap);
455 va_end (ap);
456 fprintf (stderr, "\n");
457 }
458
459 exit (EXIT_FAILURE);
460 }
461 hidden_def(eerrorx)
462
463 int ebegin (const char *fmt, ...)
464 {
465 int retval;
466 va_list ap;
467
468 if (! fmt || is_env ("RC_QUIET", "yes"))
469 return (0);
470
471 va_start (ap, fmt);
472 retval = _einfovn (fmt, ap);
473 va_end (ap);
474 retval += printf (" ...");
475 if (colour_terminal (stdout))
476 retval += printf ("\n");
477
478 return (retval);
479 }
480 hidden_def(ebegin)
481
482 static void _eend (FILE *fp, int col, einfo_color_t color, const char *msg)
483 {
484 int i;
485 int cols;
486
487 if (! msg)
488 return;
489
490 cols = get_term_columns (fp) - (strlen (msg) + 5);
491
492 /* cons25 is special - we need to remove one char, otherwise things
493 * do not align properly at all. */
494 if (! term) {
495 term = getenv ("TERM");
496 if (term && strcmp (term, "cons25") == 0)
497 term_is_cons25 = true;
498 else
499 term_is_cons25 = false;
500 }
501 if (term_is_cons25)
502 cols--;
503
504 if (cols > 0 && colour_terminal (fp)) {
505 fprintf (fp, "\033[A\033[%dC %s[ %s%s %s]%s\n", cols,
506 ecolor (ECOLOR_BRACKET), ecolor (color), msg,
507 ecolor (ECOLOR_BRACKET), ecolor (ECOLOR_NORMAL));
508 } else {
509 if (col > 0)
510 for (i = 0; i < cols - col; i++)
511 fprintf (fp, " ");
512 fprintf (fp, " [ %s ]\n", msg);
513 }
514 }
515
516 static int _do_eend (const char *cmd, int retval, const char *fmt, va_list ap)
517 {
518 int col = 0;
519 FILE *fp = stdout;
520 va_list apc;
521
522 if (fmt && retval != 0) {
523 va_copy (apc, ap);
524 if (strcmp (cmd, "ewend") == 0) {
525 col = _ewarnvn (fmt, apc);
526 fp = stdout;
527 } else {
528 col = _eerrorvn (fmt, apc);
529 fp = stderr;
530 }
531 col += fprintf (fp, "\n");
532 va_end (apc);
533 }
534
535 _eend (fp, col,
536 retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD,
537 retval == 0 ? OK : NOT_OK);
538 return (retval);
539 }
540
541 int eend (int retval, const char *fmt, ...)
542 {
543 va_list ap;
544
545 if (is_env ("RC_QUIET", "yes"))
546 return (retval);
547
548 va_start (ap, fmt);
549 _do_eend ("eend", retval, fmt, ap);
550 va_end (ap);
551
552 return (retval);
553 }
554 hidden_def(eend)
555
556 int ewend (int retval, const char *fmt, ...)
557 {
558 va_list ap;
559
560 if (is_env ("RC_QUIET", "yes"))
561 return (retval);
562
563 va_start (ap, fmt);
564 _do_eend ("ewend", retval, fmt, ap);
565 va_end (ap);
566
567 return (retval);
568 }
569 hidden_def(ewend)
570
571 void ebracket (int col, einfo_color_t color, const char *msg)
572 {
573 _eend (stdout, col, color, msg);
574 }
575 hidden_def(ebracket)
576
577 void eindent (void)
578 {
579 char *env = getenv ("RC_EINDENT");
580 int amount = 0;
581 char num[10];
582
583 if (env) {
584 errno = 0;
585 amount = strtol (env, NULL, 0);
586 if (errno != 0)
587 amount = 0;
588 }
589
590 amount += INDENT_WIDTH;
591 if (amount > INDENT_MAX)
592 amount = INDENT_MAX;
593
594 snprintf (num, 10, "%08d", amount);
595 setenv ("RC_EINDENT", num, 1);
596 }
597 hidden_def(eindent)
598
599 void eoutdent (void)
600 {
601 char *env = getenv ("RC_EINDENT");
602 int amount = 0;
603 char num[10];
604
605 if (! env)
606 return;
607
608 errno = 0;
609 amount = strtol (env, NULL, 0);
610 if (errno != 0)
611 amount = 0;
612 else
613 amount -= INDENT_WIDTH;
614
615 if (amount <= 0)
616 unsetenv ("RC_EINDENT");
617 else {
618 snprintf (num, 10, "%08d", amount);
619 setenv ("RC_EINDENT", num, 1);
620 }
621 }
622 hidden_def(eoutdent)
623
624 int einfovn (const char *fmt, ...)
625 {
626 int retval;
627 va_list ap;
628
629 CHECK_VERBOSE;
630
631 if (! fmt)
632 return (0);
633
634 va_start (ap, fmt);
635 retval = _einfovn (fmt, ap);
636 va_end (ap);
637
638 return (retval);
639 }
640 hidden_def(einfovn)
641
642 int ewarnvn (const char *fmt, ...)
643 {
644 int retval;
645 va_list ap;
646
647 CHECK_VERBOSE;
648
649 if (! fmt)
650 return (0);
651
652 va_start (ap, fmt);
653 retval = _ewarnvn (fmt, ap);
654 va_end (ap);
655
656 return (retval);
657 }
658 hidden_def(ewarnvn)
659
660 int einfov (const char *fmt, ...)
661 {
662 int retval;
663 va_list ap;
664
665 CHECK_VERBOSE;
666
667 if (! fmt)
668 return (0);
669
670 va_start (ap, fmt);
671 retval = _einfovn (fmt, ap);
672 retval += printf ("\n");
673 va_end (ap);
674
675 return (retval);
676 }
677 hidden_def(einfov)
678
679 int ewarnv (const char *fmt, ...)
680 {
681 int retval;
682 va_list ap;
683
684 CHECK_VERBOSE;
685
686 if (! fmt)
687 return (0);
688
689 va_start (ap, fmt);
690 retval = _ewarnvn (fmt, ap);
691 retval += printf ("\n");
692 va_end (ap);
693
694 return (retval);
695 }
696 hidden_def(ewarnv)
697
698 int ebeginv (const char *fmt, ...)
699 {
700 int retval;
701 va_list ap;
702
703 CHECK_VERBOSE;
704
705 if (! fmt)
706 return (0);
707
708 va_start (ap, fmt);
709 retval = _einfovn (fmt, ap);
710 retval += printf (" ...");
711 if (colour_terminal (stdout))
712 retval += printf ("\n");
713 va_end (ap);
714
715 return (retval);
716 }
717 hidden_def(ebeginv)
718
719 int eendv (int retval, const char *fmt, ...)
720 {
721 va_list ap;
722
723 CHECK_VERBOSE;
724
725 va_start (ap, fmt);
726 _do_eend ("eendv", retval, fmt, ap);
727 va_end (ap);
728
729 return (retval);
730 }
731 hidden_def(eendv)
732
733 int ewendv (int retval, const char *fmt, ...)
734 {
735 va_list ap;
736
737 CHECK_VERBOSE;
738
739 va_start (ap, fmt);
740 _do_eend ("ewendv", retval, fmt, ap);
741 va_end (ap);
742
743 return (retval);
744 }
745 hidden_def(ewendv)
746
747 void eindentv (void)
748 {
749 if (is_env ("RC_VERBOSE", "yes"))
750 eindent ();
751 }
752 hidden_def(eindentv)
753
754 void eoutdentv (void)
755 {
756 if (is_env ("RC_VERBOSE", "yes"))
757 eoutdent ();
758 }
759 hidden_def(eoutdentv)

  ViewVC Help
Powered by ViewVC 1.1.20