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

Contents of /trunk/src/libeinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20