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

Diff of /trunk/src/libeinfo.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2649 Revision 2650
6 6
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/ioctl.h> 8#include <sys/ioctl.h>
9#include <sys/stat.h> 9#include <sys/stat.h>
10#include <errno.h> 10#include <errno.h>
11#include <fcntl.h>
11#include <limits.h> 12#include <limits.h>
12#include <stdarg.h> 13#include <stdarg.h>
13#include <stdbool.h> 14#include <stdbool.h>
14#include <stdio.h> 15#include <stdio.h>
15#include <stdlib.h> 16#include <stdlib.h>
30hidden_proto(eendv) 31hidden_proto(eendv)
31hidden_proto(eerror) 32hidden_proto(eerror)
32hidden_proto(eerrorn) 33hidden_proto(eerrorn)
33hidden_proto(eerrorx) 34hidden_proto(eerrorx)
34hidden_proto(eflush) 35hidden_proto(eflush)
36hidden_proto(eclose)
35hidden_proto(eindent) 37hidden_proto(eindent)
36hidden_proto(eindentv) 38hidden_proto(eindentv)
37hidden_proto(einfo) 39hidden_proto(einfo)
38hidden_proto(einfon) 40hidden_proto(einfon)
39hidden_proto(einfov) 41hidden_proto(einfov)
116 "xterm-color", 118 "xterm-color",
117 "xterm-debian", 119 "xterm-debian",
118 NULL 120 NULL
119}; 121};
120 122
123/* We use this array to save the stdout/stderr fd's for buffering */
124static int stdfd[2] = {-1, -1};
125static FILE *ebfp = NULL;
126static char ebfile[PATH_MAX] = { '\0' };
127
121static bool is_env (const char *var, const char *val) 128static bool is_env (const char *var, const char *val)
122{ 129{
123 char *v; 130 char *v;
124 131
125 if (! var) 132 if (! var)
175#endif 182#endif
176 183
177 return (DEFAULT_COLS); 184 return (DEFAULT_COLS);
178} 185}
179 186
180static int ebuffer (const char *cmd, int retval, const char *fmt, va_list ap) 187void ebuffer (const char *file)
181{ 188{
182 char *file = getenv ("RC_EBUFFER"); 189 /* Don't ebuffer if we don't have a file or we already are */
183 FILE *fp; 190 if (! file || stdfd[0] >= 0 || ! isatty (fileno (stdout)))
191 return;
192
193 /* Save the current fd's */
194 stdfd[0] = dup (fileno (stdout));
195 stdfd[1] = dup (fileno (stderr));
196
197 if (! (ebfp = fopen (file, "w+"))) {
198 fprintf (stderr, "fopen `%s': %s\n", file, strerror (errno));
199 return;
200 }
201
202 snprintf (ebfile, sizeof (ebfile), "%s", file);
203
204 fflush (stdout);
205 fflush (stderr);
206
207 /* Now redirect stdout and stderr */
208 if ((dup2 (fileno (ebfp), fileno (stdout))) < 0)
209 fprintf (stderr, "dup2: %s", strerror (errno));
210 if ((dup2 (fileno (ebfp), fileno (stderr))) < 0)
211 fprintf (stderr, "dup2: %s", strerror (errno));
212
213 /* Store the filename in our environment so scripts can tell if we're
214 * buffering or not */
215 unsetenv ("RC_EBUFFER");
216 setenv ("RC_EBUFFER", file, 1);
217
218 return;
219}
220
221static void _eflush (bool reopen)
222{
184 char buffer[RC_LINEBUFFER]; 223 char buffer[RC_LINEBUFFER];
185 int l = 1; 224 int serrno = errno;
186 225
187 if (! file || ! cmd || strlen (cmd) < 4) 226 /* eflush called from an init script? */
188 return (0); 227 if (! ebfp) {
189
190 if (! (fp = fopen (file, "a"))) {
191 fprintf (stderr, "fopen `%s': %s\n", file, strerror (errno));
192 return (0);
193 }
194
195 fprintf (fp, "%s %d ", cmd, retval);
196
197 if (fmt) {
198 va_list apc;
199 va_copy (apc, ap);
200 l = vsnprintf (buffer, sizeof (buffer), fmt, apc);
201 fprintf (fp, "%d %s\n", l, buffer);
202 va_end (apc);
203 } else
204 fprintf (fp, "0\n");
205
206 fclose (fp);
207 return (l);
208}
209
210typedef struct func
211{
212 const char *name;
213 int (*efunc) (const char *fmt, ...);
214 int (*eefunc) (int retval, const char *fmt, ...);
215 void (*eind) (void);
216} func_t;
217
218static const func_t funcmap[] = {
219 { "einfon", &einfon, NULL, NULL },
220 { "ewarnn", &ewarnn, NULL, NULL},
221 { "eerrorn", &eerrorn, NULL, NULL},
222 { "einfo", &einfo, NULL, NULL },
223 { "ewarn", &ewarn, NULL, NULL },
224 { "eerror", &eerror, NULL, NULL },
225 { "ebegin", &ebegin, NULL, NULL },
226 { "eend", NULL, &eend, NULL },
227 { "ewend", NULL, &ewend, NULL },
228 { "eindent", NULL, NULL, &eindent },
229 { "eoutdent", NULL, NULL, &eoutdent },
230 { "einfovn", &einfovn, NULL, NULL },
231 { "ewarnvn", &ewarnvn, NULL, NULL },
232 { "einfov", &einfov, NULL, NULL },
233 { "ewarnv", &ewarnv, NULL, NULL },
234 { "ebeginv", &ebeginv, NULL, NULL },
235 { "eendv", NULL, &eendv, NULL },
236 { "ewendv", NULL, &ewendv, NULL },
237 { "eindentv" ,NULL, NULL, &eindentv },
238 { "eoutdentv", NULL, NULL, &eoutdentv },
239 { NULL, NULL, NULL, NULL },
240};
241
242void eflush (void)
243{
244 FILE *fp;
245 char *file = getenv ("RC_EBUFFER"); 228 char *file = getenv ("RC_EBUFFER");
246 char buffer[RC_LINEBUFFER]; 229 if (file)
247 char *cmd; 230 ebfp = fopen (file, "a+");
248 int retval = 0; 231 }
249 int length = 0;
250 char *token;
251 char *p;
252 struct stat buf;
253 pid_t pid;
254 char newfile[PATH_MAX];
255 int i = 1;
256 232
257 if (! file|| (stat (file, &buf) != 0)) { 233 if (! ebfp)
258 errno = 0;
259 return; 234 return;
260 }
261 235
262 /* Find a unique name for our file */ 236 fflush (stdout);
263 while (true) { 237 fflush (stderr);
264 snprintf (newfile, sizeof (newfile), "%s.%d", file, i); 238
265 if (stat (newfile, &buf) != 0) { 239 /* Restore stdout and stderr now */
266 if (rename (file, newfile)) 240 if (stdfd[0] >= 0) {
267 fprintf (stderr, "rename `%s' `%s': %s\n", file, newfile, 241 dup2 (stdfd[0], fileno (stdout));
268 strerror (errno)); 242 dup2 (stdfd[1], fileno (stderr));
269 break; 243 } else {
244 char *tty = getenv ("RC_TTY");
245 if (tty) {
246 freopen (tty, "w+", stdout);
247 dup2 (fileno (stdout), fileno (stderr));
270 } 248 }
271 i++;
272 } 249 }
273
274 /* We fork a child process here so we don't hold anything up */
275 if ((pid = fork ()) == -1) {
276 fprintf (stderr, "fork: %s", strerror (errno));
277 return;
278 }
279
280 if (pid != 0)
281 return;
282 250
283 /* Spin until we can lock the ebuffer */ 251 /* Spin until we can lock the ebuffer */
284 while (true) { 252 while (true) {
285 struct timeval tv; 253 struct timeval tv;
254 errno = 0;
255 if (mkfifo (EBUFFER_LOCK, 0700) == 0)
256 break;
257 if (errno != EEXIST)
258 eerror ("mkfifo `%s': %s\n", EBUFFER_LOCK, strerror (errno));
286 tv.tv_sec = 0; 259 tv.tv_sec = 0;
287 tv.tv_usec = 20000; 260 tv.tv_usec = 20000;
288 select (0, NULL, NULL, NULL, &tv); 261 select (0, NULL, NULL, NULL, &tv);
289 errno = 0;
290 if (link (newfile, EBUFFER_LOCK) == 0)
291 break;
292 if (errno != EEXIST)
293 fprintf (stderr, "link `%s' `%s': %s\n", newfile, EBUFFER_LOCK,
294 strerror (errno));
295 } 262 }
263 errno = serrno;
296 264
297 if (! (fp = fopen (newfile, "r"))) { 265 /* Dump the file to stdout */
298 fprintf (stderr, "fopen `%s': %s\n", newfile, strerror (errno));
299 return;
300 }
301
302 unsetenv ("RC_EBUFFER");
303
304 memset (buffer, 0, RC_LINEBUFFER); 266 memset (buffer, 0, RC_LINEBUFFER);
267 if (fseek (ebfp, (off_t) 0, SEEK_SET) < 0)
268 eerror ("fseek: %s", strerror (errno));
269 else {
305 while (fgets (buffer, RC_LINEBUFFER, fp)) { 270 while (fgets (buffer, RC_LINEBUFFER, ebfp))
306 i = strlen (buffer) - 1; 271 printf ("%s", buffer);
307 if (i < 1)
308 continue;
309
310 if (buffer[i] == '\n')
311 buffer[i] = 0;
312
313 p = buffer;
314 cmd = strsep (&p, " ");
315 token = strsep (&p, " ");
316 if (sscanf (token, "%d", &retval) != 1) {
317 fprintf (stderr, "eflush `%s': not a number", token);
318 continue;
319 } 272 }
320 token = strsep (&p, " "); 273 fflush (stdout);
321 if (sscanf (token, "%d", &length) != 1) { 274 fflush (stderr);
322 fprintf (stderr, "eflush `%s': not a number", token); 275
323 continue;
324 }
325
326 i = 0;
327 while (funcmap[i].name) {
328 if (strcmp (funcmap[i].name, cmd) == 0) {
329 if (funcmap[i].efunc) {
330 if (p)
331 funcmap[i].efunc ("%s", p);
332 else
333 funcmap[i].efunc (NULL, NULL);
334 } else if (funcmap[i].eefunc) {
335 if (p)
336 funcmap[i].eefunc (retval, "%s", p);
337 else
338 funcmap[i].eefunc (retval, NULL, NULL);
339 } else if (funcmap[i].eind)
340 funcmap[i].eind ();
341 else
342 fprintf (stderr, "eflush `%s': no function defined\n", cmd);
343 break;
344 }
345 i++;
346 }
347
348 if (! funcmap[i].name)
349 fprintf (stderr, "eflush `%s': invalid function\n", cmd);
350 }
351 fclose (fp);
352
353 if (unlink (EBUFFER_LOCK)) 276 if (unlink (EBUFFER_LOCK))
354 fprintf (stderr, "unlink `%s': %s", EBUFFER_LOCK, strerror (errno)); 277 eerror ("unlink `%s': %s", EBUFFER_LOCK, strerror (errno));
355 278
279 if (reopen) {
280 ftruncate (fileno (ebfp), (off_t) 0);
281 fseek (ebfp, (off_t) 0, SEEK_SET);
282 dup2 (fileno (ebfp), fileno (stdout));
283 dup2 (fileno (ebfp), fileno (stderr));
284 } else {
285 stdfd[0] = -1;
286 stdfd[1] = -1;
287 fclose (ebfp);
288 ebfp = NULL;
356 if (unlink (newfile)) 289 unlink (ebfile);
357 fprintf (stderr, "unlink `%s': %s", newfile, strerror (errno)); 290 ebfile[0] = '\0';
291 unsetenv ("RC_EBUFFER");
292 }
358 293
359 _exit (EXIT_SUCCESS); 294 return;
295}
296
297void eflush () {
298 _eflush (true);
360} 299}
361hidden_def(eflush) 300hidden_def(eflush)
362 301
363#define EBUFFER(_cmd, _retval, _fmt, _ap) { \ 302void eclose () {
364 int _i = ebuffer (_cmd, _retval, _fmt, _ap); \ 303 _eflush (false);
365 if (_i) \
366 return (_i); \
367} 304}
305hidden_def(eclose)
368 306
369static void elog (int level, const char *fmt, va_list ap) 307static void elog (int level, const char *fmt, va_list ap)
370{ 308{
371 char *e = getenv ("RC_ELOG"); 309 char *e = getenv ("RC_ELOG");
372 va_list apc; 310 va_list apc;
399 memset (indent, ' ', amount); 337 memset (indent, ' ', amount);
400 } 338 }
401 339
402 /* Terminate it */ 340 /* Terminate it */
403 memset (indent + amount, 0, 1); 341 memset (indent + amount, 0, 1);
404
405 return (fprintf (stream, "%s", indent)); 342 return (fprintf (stream, "%s", indent));
406} 343}
407 344
408const char *ecolor (einfo_color_t color) { 345const char *ecolor (einfo_color_t color) {
409 const char *col = NULL; 346 const char *col = NULL;
484 421
485 if (! fmt || is_env ("RC_QUIET", "yes")) 422 if (! fmt || is_env ("RC_QUIET", "yes"))
486 return (0); 423 return (0);
487 424
488 va_start (ap, fmt); 425 va_start (ap, fmt);
489 if (! (retval = ebuffer ("einfon", 0, fmt, ap)))
490 retval = _einfovn (fmt, ap); 426 retval = _einfovn (fmt, ap);
491 va_end (ap); 427 va_end (ap);
492 428
493 return (retval); 429 return (retval);
494} 430}
495hidden_def(einfon) 431hidden_def(einfon)
501 437
502 if (! fmt || is_env ("RC_QUIET", "yes")) 438 if (! fmt || is_env ("RC_QUIET", "yes"))
503 return (0); 439 return (0);
504 440
505 va_start (ap, fmt); 441 va_start (ap, fmt);
506 if (! (retval = ebuffer ("ewarnn", 0, fmt, ap)))
507 retval = _ewarnvn (fmt, ap); 442 retval = _ewarnvn (fmt, ap);
508 va_end (ap); 443 va_end (ap);
509 444
510 return (retval); 445 return (retval);
511} 446}
512hidden_def(ewarnn) 447hidden_def(ewarnn)
515{ 450{
516 int retval; 451 int retval;
517 va_list ap; 452 va_list ap;
518 453
519 va_start (ap, fmt); 454 va_start (ap, fmt);
520 if (! (retval = ebuffer ("eerrorn", 0, fmt, ap)))
521 retval = _eerrorvn (fmt, ap); 455 retval = _eerrorvn (fmt, ap);
522 va_end (ap); 456 va_end (ap);
523 457
524 return (retval); 458 return (retval);
525} 459}
526hidden_def(eerrorn) 460hidden_def(eerrorn)
532 466
533 if (! fmt || is_env ("RC_QUIET", "yes")) 467 if (! fmt || is_env ("RC_QUIET", "yes"))
534 return (0); 468 return (0);
535 469
536 va_start (ap, fmt); 470 va_start (ap, fmt);
537 if (! (retval = ebuffer ("einfo", 0, fmt, ap))) {
538 retval = _einfovn (fmt, ap); 471 retval = _einfovn (fmt, ap);
539 retval += printf ("\n"); 472 retval += printf ("\n");
540 }
541 va_end (ap); 473 va_end (ap);
542 474
543 return (retval); 475 return (retval);
544} 476}
545hidden_def(einfo) 477hidden_def(einfo)
552 if (! fmt || is_env ("RC_QUIET", "yes")) 484 if (! fmt || is_env ("RC_QUIET", "yes"))
553 return (0); 485 return (0);
554 486
555 va_start (ap, fmt); 487 va_start (ap, fmt);
556 elog (LOG_WARNING, fmt, ap); 488 elog (LOG_WARNING, fmt, ap);
557 if (! (retval = ebuffer ("ewarn", 0, fmt, ap))) {
558 retval = _ewarnvn (fmt, ap); 489 retval = _ewarnvn (fmt, ap);
559 retval += printf ("\n"); 490 retval += printf ("\n");
560 }
561 va_end (ap); 491 va_end (ap);
562 492
563 return (retval); 493 return (retval);
564} 494}
565hidden_def(ewarn) 495hidden_def(ewarn)
567void ewarnx (const char *fmt, ...) 497void ewarnx (const char *fmt, ...)
568{ 498{
569 int retval; 499 int retval;
570 va_list ap; 500 va_list ap;
571 501
502 eclose ();
572 if (fmt && ! is_env ("RC_QUIET", "yes")) { 503 if (fmt && ! is_env ("RC_QUIET", "yes")) {
573 va_start (ap, fmt); 504 va_start (ap, fmt);
574 elog (LOG_WARNING, fmt, ap); 505 elog (LOG_WARNING, fmt, ap);
575 retval = _ewarnvn (fmt, ap); 506 retval = _ewarnvn (fmt, ap);
576 va_end (ap); 507 va_end (ap);
592 elog (LOG_ERR, fmt, ap); 523 elog (LOG_ERR, fmt, ap);
593 retval = _eerrorvn (fmt, ap); 524 retval = _eerrorvn (fmt, ap);
594 va_end (ap); 525 va_end (ap);
595 retval += fprintf (stderr, "\n"); 526 retval += fprintf (stderr, "\n");
596 527
528 eflush ();
597 return (retval); 529 return (retval);
598} 530}
599hidden_def(eerror) 531hidden_def(eerror)
600 532
601void eerrorx (const char *fmt, ...) 533void eerrorx (const char *fmt, ...)
602{ 534{
603 va_list ap; 535 va_list ap;
604 536
537 eclose ();
605 if (fmt) { 538 if (fmt) {
606 va_start (ap, fmt); 539 va_start (ap, fmt);
607 elog (LOG_ERR, fmt, ap); 540 elog (LOG_ERR, fmt, ap);
608 _eerrorvn (fmt, ap); 541 _eerrorvn (fmt, ap);
609 va_end (ap); 542 va_end (ap);
610 printf ("\n"); 543 printf ("\n");
611 } 544 }
545
612 exit (EXIT_FAILURE); 546 exit (EXIT_FAILURE);
613} 547}
614hidden_def(eerrorx) 548hidden_def(eerrorx)
615 549
616int ebegin (const char *fmt, ...) 550int ebegin (const char *fmt, ...)
620 554
621 if (! fmt || is_env ("RC_QUIET", "yes")) 555 if (! fmt || is_env ("RC_QUIET", "yes"))
622 return (0); 556 return (0);
623 557
624 va_start (ap, fmt); 558 va_start (ap, fmt);
625 if ((retval = ebuffer ("ebegin", 0, fmt, ap))) {
626 va_end (ap);
627 return (retval);
628 }
629
630 retval = _einfovn (fmt, ap); 559 retval = _einfovn (fmt, ap);
631 va_end (ap); 560 va_end (ap);
632 retval += printf (" ..."); 561 retval += printf (" ...");
633 if (colour_terminal ()) 562 if (colour_terminal ())
634 retval += printf ("\n"); 563 retval += printf ("\n");
665static int _do_eend (const char *cmd, int retval, const char *fmt, va_list ap) 594static int _do_eend (const char *cmd, int retval, const char *fmt, va_list ap)
666{ 595{
667 int col = 0; 596 int col = 0;
668 FILE *fp; 597 FILE *fp;
669 va_list apc; 598 va_list apc;
670 int eb;
671
672 if (fmt) {
673 va_copy (apc, ap);
674 eb = ebuffer (cmd, retval, fmt, apc);
675 va_end (apc);
676 if (eb)
677 return (retval);
678 }
679 599
680 if (fmt && retval != 0) { 600 if (fmt && retval != 0) {
681 va_copy (apc, ap); 601 va_copy (apc, ap);
682 if (strcmp (cmd, "ewend") == 0) { 602 if (strcmp (cmd, "ewend") == 0) {
683 col = _ewarnvn (fmt, apc); 603 col = _ewarnvn (fmt, apc);
737{ 657{
738 char *env = getenv ("RC_EINDENT"); 658 char *env = getenv ("RC_EINDENT");
739 int amount = 0; 659 int amount = 0;
740 char num[10]; 660 char num[10];
741 661
742 if (ebuffer ("eindent", 0, NULL, NULL))
743 return;
744
745 if (env) { 662 if (env) {
746 errno = 0; 663 errno = 0;
747 amount = strtol (env, NULL, 0); 664 amount = strtol (env, NULL, 0);
748 if (errno != 0) 665 if (errno != 0)
749 amount = 0; 666 amount = 0;
761void eoutdent (void) 678void eoutdent (void)
762{ 679{
763 char *env = getenv ("RC_EINDENT"); 680 char *env = getenv ("RC_EINDENT");
764 int amount = 0; 681 int amount = 0;
765 char num[10]; 682 char num[10];
766
767 if (ebuffer ("eoutdent", 0, NULL, NULL))
768 return;
769 683
770 if (! env) 684 if (! env)
771 return; 685 return;
772 686
773 errno = 0; 687 errno = 0;
795 709
796 if (! fmt) 710 if (! fmt)
797 return (0); 711 return (0);
798 712
799 va_start (ap, fmt); 713 va_start (ap, fmt);
800 if (! (retval = ebuffer ("einfovn", 0, fmt, ap)))
801 retval = _einfovn (fmt, ap); 714 retval = _einfovn (fmt, ap);
802 va_end (ap); 715 va_end (ap);
803 716
804 return (retval); 717 return (retval);
805} 718}
806hidden_def(einfovn) 719hidden_def(einfovn)
814 727
815 if (! fmt) 728 if (! fmt)
816 return (0); 729 return (0);
817 730
818 va_start (ap, fmt); 731 va_start (ap, fmt);
819 if (! (retval = ebuffer ("ewarnvn", 0, fmt, ap)))
820 retval = _ewarnvn (fmt, ap); 732 retval = _ewarnvn (fmt, ap);
821 va_end (ap); 733 va_end (ap);
822 734
823 return (retval); 735 return (retval);
824} 736}
825hidden_def(ewarnvn) 737hidden_def(ewarnvn)
833 745
834 if (! fmt) 746 if (! fmt)
835 return (0); 747 return (0);
836 748
837 va_start (ap, fmt); 749 va_start (ap, fmt);
838 if (! (retval = ebuffer ("einfov", 0, fmt, ap))) {
839 retval = _einfovn (fmt, ap); 750 retval = _einfovn (fmt, ap);
751 retval += printf ("\n");
752 va_end (ap);
753
754 return (retval);
755}
756hidden_def(einfov)
757
758int ewarnv (const char *fmt, ...)
759{
760 int retval;
761 va_list ap;
762
763 CHECK_VERBOSE;
764
765 if (! fmt)
766 return (0);
767
768 va_start (ap, fmt);
769 retval = _ewarnvn (fmt, ap);
770 retval += printf ("\n");
771 va_end (ap);
772
773 return (retval);
774}
775hidden_def(ewarnv)
776
777int ebeginv (const char *fmt, ...)
778{
779 int retval;
780 va_list ap;
781
782 CHECK_VERBOSE;
783
784 if (! fmt)
785 return (0);
786
787 va_start (ap, fmt);
788 retval = _einfovn (fmt, ap);
789 retval += printf (" ...");
790 if (colour_terminal ())
840 retval += printf ("\n"); 791 retval += printf ("\n");
841 }
842 va_end (ap);
843
844 return (retval);
845}
846hidden_def(einfov)
847
848int ewarnv (const char *fmt, ...)
849{
850 int retval;
851 va_list ap;
852
853 CHECK_VERBOSE;
854
855 if (! fmt)
856 return (0);
857
858 va_start (ap, fmt);
859 if (! (retval = ebuffer ("ewarnv", 0, fmt, ap))) {
860 retval = _ewarnvn (fmt, ap);
861 retval += printf ("\n");
862 }
863 va_end (ap);
864
865 return (retval);
866}
867hidden_def(ewarnv)
868
869int ebeginv (const char *fmt, ...)
870{
871 int retval;
872 va_list ap;
873
874 CHECK_VERBOSE;
875
876 if (! fmt)
877 return (0);
878
879 va_start (ap, fmt);
880 if (! (retval = ebuffer ("ebeginv", 0, fmt, ap))) {
881 retval = _einfovn (fmt, ap);
882 retval += printf (" ...");
883 if (colour_terminal ())
884 retval += printf ("\n");
885 }
886 va_end (ap); 792 va_end (ap);
887 793
888 return (retval); 794 return (retval);
889} 795}
890hidden_def(ebeginv) 796hidden_def(ebeginv)

Legend:
Removed from v.2649  
changed lines
  Added in v.2650

  ViewVC Help
Powered by ViewVC 1.1.20