| 447 | {{{ |
| 448 | #!C |
| 449 | #include <unistd.h> |
| 450 | #include <stdio.h> |
| 451 | #include <fcntl.h> |
| 452 | #include <linux/fb.h> // include frame buffer header files |
| 453 | #include <sys/ioctl.h> |
| 454 | |
| 455 | int main(void) |
| 456 | { |
| 457 | int fbfd = 0 ; // frame buffer file description |
| 458 | |
| 459 | /* Get device independent unchangeable information about a frame buffer |
| 460 | * device and a specific video mode by FBIOGET_FSCREENINFO ioctl. */ |
| 461 | struct fb_fix_screeninfo finfo; |
| 462 | |
| 463 | fbfd = open( "/dev/fb0" , O_RDWR ); |
| 464 | if ( !fbfd ) |
| 465 | { |
| 466 | printf( "Error: cannot open framebuffer device.\n" ); |
| 467 | exit(1); |
| 468 | } |
| 469 | printf("The framebuffer device was opened successfully.\n"); |
| 470 | |
| 471 | /* Get fixed screen information */ |
| 472 | if ( ioctl ( fbfd , FBIOGET_FSCREENINFO , &finfo ) ) |
| 473 | { |
| 474 | printf("Error reading fixed screen information.\n"); |
| 475 | exit(2); |
| 476 | } else { |
| 477 | printf("Succesfully Read the Fixed Screen Information\n"); |
| 478 | } |
| 479 | |
| 480 | printf("fb_fix_screeninfo.smem_len = %d\n", finfo.smem_len); |
| 481 | printf("fb_fix_screeninfo.mmio_len = %d\n", finfo.mmio_len); |
| 482 | } |
| 483 | }}} |
| 484 | |
| 485 | * 在 Ubuntu Intrepid 上執行結果 |
| 486 | {{{ |
| 487 | root@intrepid:~# uname -a |
| 488 | Linux intrepid 2.6.27-7-server #1 SMP Tue Nov 4 20:16:57 UTC 2008 x86_64 GNU/Linux |
| 489 | root@intrepid:~# ./fbinfo |
| 490 | The framebuffer device was opened successfully. |
| 491 | Succesfully Read the Fixed Screen Information |
| 492 | fb_fix_screeninfo.smem_len = 16777216 |
| 493 | fb_fix_screeninfo.mmio_len = 0 |
| 494 | }}} |
| 495 | * 以下是在 Debian Sarge 上執行結果,值得一提的是 jfbterm 在 2.6.8 核心上可以正常執行。(不過還有字型問題需要調整) |
| 496 | {{{ |
| 497 | root@wsu-admin:~# uname -a |
| 498 | Linux wsu-admin 2.6.8-2-386 #1 Tue Aug 16 12:46:35 UTC 2005 i686 GNU/Linux |
| 499 | root@wsu-admin:~# ./fbinfo |
| 500 | The framebuffer device was opened successfully. |
| 501 | Succesfully Read the Fixed Screen Information |
| 502 | fb_fix_screeninfo.smem_len = 65536 |
| 503 | fb_fix_screeninfo.mmio_len = 0 |
| 504 | }}} |
| 505 | {{{ |
| 506 | root@wsu-admin:~# jfbterm |
| 507 | jfbterm - Kanji on framebuffer console Version 0.4.7 |
| 508 | Copyright (C) 2003 Fumitoshi UKAI |
| 509 | Copyright (C) 1999-2000 Noritoshi Masuichi |
| 510 | This program is based on KON2 |
| 511 | Copyright (C) 1992-1996 Takashi MANABE |
| 512 | |
| 513 | (**) : Configuration file `/etc/jfbterm.conf' |
| 514 | .... 略 .... |
| 515 | exec : /bin/bash ioctl FBIOGET_CON2FBMAP: Invalid argument |
| 516 | color 0 : 0, 0 |
| 517 | color 1 : 2a, 2a |
| 518 | color 2 : 2a, 2a |
| 519 | color 3 : 2a, 2a |
| 520 | color 4 : 2a, 2a |
| 521 | color 5 : 2a, 2a |
| 522 | color 6 : 2a, 2a |
| 523 | color 7 : 2a, 2a |
| 524 | color 8 : 15, 15 |
| 525 | color 9 : 3f, 3f |
| 526 | color 10 : 3f, 3f |
| 527 | color 11 : 3f, 3f |
| 528 | color 12 : 3f, 3f |
| 529 | color 13 : 3f, 3f |
| 530 | color 14 : 3f, 3f |
| 531 | color 15 : 3f, 3f |
| 532 | }}} |
| 533 | * 以下是在 Debian Etch 上執行結果,有趣的是 jfbterm 0.4.7-7 在 2.6.18-4 上執行,縱使有 cannot mmap(mmio) : Invalid argument 的錯誤訊息,但仍舊可以正常進入 jfbterm 的環境。 |
| 534 | {{{ |
| 535 | root@etch:~# uname -a |
| 536 | Linux etch 2.6.18-4-686 #1 SMP Wed May 9 23:03:12 UTC 2007 i686 GNU/Linux |
| 537 | root@etch:~# ./fbinfo |
| 538 | The framebuffer device was opened successfully. |
| 539 | Succesfully Read the Fixed Screen Information |
| 540 | fb_fix_screeninfo.smem_len = 1920000 |
| 541 | fb_fix_screeninfo.mmio_len = 0 |
| 542 | }}} |
| 543 | {{{ |
| 544 | root@etch:~# jfbterm |
| 545 | jfbterm - Kanji on framebuffer console Version 0.4.7 |
| 546 | Copyright (C) 2003 Fumitoshi UKAI |
| 547 | Copyright (C) 1999-2000 Noritoshi Masuichi |
| 548 | This program is based on KON2 |
| 549 | Copyright (C) 1992-1996 Takashi MANABE |
| 550 | |
| 551 | (**) : Configuration file `/etc/jfbterm.conf' |
| 552 | ... 略 ... |
| 553 | exec : /bin/bash color 0 : 0, 0 |
| 554 | color 1 : 15, 15 |
| 555 | color 2 : 540, 540 |
| 556 | color 3 : 555, 555 |
| 557 | color 4 : a800, a800 |
| 558 | color 5 : a815, a815 |
| 559 | color 6 : ad40, ad40 |
| 560 | color 7 : ad55, ad55 |
| 561 | color 8 : 52aa, 52aa |
| 562 | color 9 : 52bf, 52bf |
| 563 | color 10 : 57ea, 57ea |
| 564 | color 11 : 57ff, 57ff |
| 565 | color 12 : faaa, faaa |
| 566 | color 13 : fabf, fabf |
| 567 | color 14 : ffea, ffea |
| 568 | color 15 : ffff, ffff |
| 569 | cannot mmap(mmio) : Invalid argument |
| 570 | }}} |
| 571 | * 為了測試 jfbterm 的中文相容性,我們寫了一隻簡單的 script |
| 572 | {{{ |
| 573 | #!sh |
| 574 | #!/bin/bash |
| 575 | echo " TEST 中文測試 " |
| 576 | echo "Press Any Key to continue!" |
| 577 | read |
| 578 | }}} |
| 579 | * 在 Ubutnu intriped 的 tty1 上執行 jfbterm -f /etc/jfbterm.conf -e /root/test.sh 可以正常看到" TEST 中文測試 "字樣,但卻無法正常跳出,因此我們再來 DEBUG 一下。 |
| 580 | {{{ |
| 581 | file jfbterm |
| 582 | set args -f /etc/jfbterm.conf -e /root/test.sh |
| 583 | show args |
| 584 | break fbcommon.c:500 |
| 585 | break fbcommon.c:557 |
| 586 | break fbcommon.c:566 |
| 587 | break term.c:103 |
| 588 | break term.c:284 |
| 589 | r |
| 590 | c |
| 591 | c |
| 592 | c |
| 593 | bt |
| 594 | c |
| 595 | bt |
| 596 | p utp->ut_time |
| 597 | p utp->ut_tv |
| 598 | }}} |
| 599 | {{{ |
| 600 | Breakpoint 4, tterm_final (p=0x6147c0) at term.c:103 |
| 601 | (gdb) bt |
| 602 | #0 tterm_final (p=0x6147c0) at term.c:103 |
| 603 | #1 0x0000000000408adf in sigchld (sig=<value optimized out>) at term.c:82 |
| 604 | #2 <signal handler called> |
| 605 | #3 0x00007f5dfc00f433 in select () from /lib/libc.so.6 |
| 606 | #4 0x0000000000408873 in tterm_start (p=0x6147c0, tn=<value optimized out>, en=<value optimized out>) at term.c:192 |
| 607 | #5 0x0000000000402cf2 in main (argc=<value optimized out>, argv=0x7fff049477f8) at main.c:438 |
| 608 | (gdb) c |
| 609 | Continuing. |
| 610 | |
| 611 | Breakpoint 5, tterm_reset_utmp (p=<value optimized out>) at term.c:284 |
| 612 | (gdb) bt |
| 613 | #0 tterm_reset_utmp (p=<value optimized out>) at term.c:284 |
| 614 | #1 0x0000000000408a50 in tterm_final (p=0xe) at term.c:103 |
| 615 | #2 0x0000000000408adf in sigchld (sig=<value optimized out>) at term.c:82 |
| 616 | #3 <signal handler called> |
| 617 | #4 0x00007fa268131433 in select () from /lib/libc.so.6 |
| 618 | #5 0x0000000000408873 in tterm_start (p=0x6147c0, tn=<value optimized out>, en=<value optimized out>) at term.c:192 |
| 619 | #6 0x0000000000402cf2 in main (argc=<value optimized out>, argv=0x7fff70a69328) at main.c:438 |
| 620 | (gdb) p utp->ut_time |
| 621 | There is no member named ut_time. |
| 622 | }}} |
| 623 | * [註] utp->ut_time = utp->ut_tv.tv_sec |
| 624 | {{{ |
| 625 | #!C |
| 626 | |
| 627 | < /usr/include/bits/utmp.h > |
| 628 | |
| 629 | 59 /* The structure describing an entry in the user accounting database. */ |
| 630 | 60 struct utmp |
| 631 | 61 { |
| 632 | 62 short int ut_type; /* Type of login. */ |
| 633 | 63 pid_t ut_pid; /* Process ID of login process. */ |
| 634 | 64 char ut_line[UT_LINESIZE]; /* Devicename. */ |
| 635 | 65 char ut_id[4]; /* Inittab ID. */ |
| 636 | 66 char ut_user[UT_NAMESIZE]; /* Username. */ |
| 637 | 67 char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ |
| 638 | 68 struct exit_status ut_exit; /* Exit status of a process marked |
| 639 | 69 as DEAD_PROCESS. */ |
| 640 | 70 /* The ut_session and ut_tv fields must be the same size when compiled |
| 641 | 71 32- and 64-bit. This allows data files and shared memory to be |
| 642 | 72 shared between 32- and 64-bit applications. */ |
| 643 | 73 #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 |
| 644 | 74 int32_t ut_session; /* Session ID, used for windowing. */ |
| 645 | 75 struct |
| 646 | 76 { |
| 647 | 77 int32_t tv_sec; /* Seconds. */ |
| 648 | 78 int32_t tv_usec; /* Microseconds. */ |
| 649 | 79 } ut_tv; /* Time entry was made. */ |
| 650 | 80 #else |
| 651 | 81 long int ut_session; /* Session ID, used for windowing. */ |
| 652 | 82 struct timeval ut_tv; /* Time entry was made. */ |
| 653 | 83 #endif |
| 654 | 84 |
| 655 | 85 int32_t ut_addr_v6[4]; /* Internet address of remote host. */ |
| 656 | 86 char __unused[20]; /* Reserved for future use. */ |
| 657 | 87 }; |
| 658 | |
| 659 | 94 # define ut_time ut_tv.tv_sec |
| 660 | }}} |
| 661 | * GDB 線上除錯練習 |
| 662 | {{{ |
| 663 | [tty1] |
| 664 | |
| 665 | root@etch:~# apt-get build-dep jfbterm |
| 666 | root@etch:~# apt-get source jfbterm |
| 667 | root@etch:~# apt-get install jfbterm |
| 668 | root@etch:~# cd jfbterm-0.4.7 |
| 669 | root@etch:~/jfbterm-0.4.7# ./configure --enable-debug |
| 670 | root@etch:~/jfbterm-0.4.7# make |
| 671 | root@etch:~/jfbterm-0.4.7# ./jfbterm -f /etc/jfbterm.conf -e /root/test.sh |
| 672 | |
| 673 | [tty2] |
| 674 | |
| 675 | root@etch:~# gdb /root/jfbterm-0.4.7/jfbterm `pidof jfbterm` |
| 676 | GNU gdb 6.4.90-debian |
| 677 | Copyright (C) 2006 Free Software Foundation, Inc. |
| 678 | GDB is free software, covered by the GNU General Public License, and you are |
| 679 | welcome to change it and/or distribute copies of it under certain conditions. |
| 680 | Type "show copying" to see the conditions. |
| 681 | There is absolutely no warranty for GDB. Type "show warranty" for details. |
| 682 | This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". |
| 683 | |
| 684 | Attaching to program: /root/jfbterm-0.4.7/jfbterm, process 7480 |
| 685 | Reading symbols from /lib/tls/i686/cmov/libutil.so.1...done. |
| 686 | Loaded symbols for /lib/tls/i686/cmov/libutil.so.1 |
| 687 | Reading symbols from /lib/tls/i686/cmov/libm.so.6...done. |
| 688 | Loaded symbols for /lib/tls/i686/cmov/libm.so.6 |
| 689 | Reading symbols from /lib/tls/i686/cmov/libc.so.6...done. |
| 690 | Loaded symbols for /lib/tls/i686/cmov/libc.so.6 |
| 691 | Reading symbols from /lib/ld-linux.so.2...done. |
| 692 | Loaded symbols for /lib/ld-linux.so.2 |
| 693 | Reading symbols from /lib/tls/i686/cmov/libnss_compat.so.2...done. |
| 694 | Loaded symbols for /lib/tls/i686/cmov/libnss_compat.so.2 |
| 695 | Reading symbols from /lib/tls/i686/cmov/libnsl.so.1...done. |
| 696 | Loaded symbols for /lib/tls/i686/cmov/libnsl.so.1 |
| 697 | Reading symbols from /lib/tls/i686/cmov/libnss_nis.so.2...done. |
| 698 | Loaded symbols for /lib/tls/i686/cmov/libnss_nis.so.2 |
| 699 | Reading symbols from /lib/tls/i686/cmov/libnss_files.so.2...done. |
| 700 | Loaded symbols for /lib/tls/i686/cmov/libnss_files.so.2 |
| 701 | Failed to read a valid object file image from memory. |
| 702 | 0xb7fea410 in ?? () |
| 703 | (gdb) break term.c:284 |
| 704 | Breakpoint 1 at 0x804f552: file term.c, line 284. |
| 705 | (gdb) c |
| 706 | Continuing. |
| 707 | |
| 708 | Breakpoint 1, tterm_final (p=0x8058be0) at term.c:284 |
| 709 | 284 time(&(utp->ut_time)); |
| 710 | (gdb) c |
| 711 | Continuing. |
| 712 | |
| 713 | Breakpoint 1, tterm_final (p=0x8058be0) at term.c:284 |
| 714 | 284 time(&(utp->ut_time)); |
| 715 | (gdb) c |
| 716 | Continuing. |
| 717 | |
| 718 | Program exited normally. |
| 719 | }}} |
| 720 | * GDB 遠端除錯練習 |
| 721 | {{{ |
| 722 | [tty1] |
| 723 | gdbserver 127.0.0.1:1234 /root/jfbterm-0.4.7/jfbterm |
| 724 | [pts1] |
| 725 | (gdb) target remote 127.0.0.1:1234 |
| 726 | }}} |
| 727 | * 在 DEBUG 的時候偶爾會看到 <value optimized out>,但是該怎麼去掉呢?? |
| 728 | * [參考] http://www.cs.utk.edu/~vose/c-stuff/onlinedocs/gdb_7.html |
| 729 | {{{ |
| 730 | The values of arguments that were not saved in their stack frames are shown as `<value optimized out>'. |
| 731 | |
| 732 | If you need to display the values of such optimized-out arguments, either deduce that from other variables whose values depend on the one you are interested in, or recompile without optimizations. |
| 733 | }}} |
| 734 | * [作法] 在 configure 的時候加上 CFLAGS |
| 735 | * 註: 因為如果有設定 CFLAGS 的話,在 configure 裡是會直接採用我們提供的 CFLAGS。因此縱使加上 --enable-debug 也沒有用,configure 不會幫你加 -g 進去。 |
| 736 | {{{ |
| 737 | root@intrepid:~/jfbterm-0.4.7-dev# CFLAGS="-g -O0" ./configure |
| 738 | }}} |
| 739 | * 繼續追為何結束時會收到 SIGSEGV 的主因 |
| 740 | {{{ |
| 741 | < 直接在 tty1 或在 screen 中執行 > |
| 742 | root@intrepid:~/jfbterm-0.4.7-dev# ./jfbterm -f /etc/jfbterm.conf -e /root/test.sh |
| 743 | }}} |
| 744 | {{{ |
| 745 | root@intrepid:~/jfbterm-0.4.7-dev# gdb ./jfbterm `pidof jfbterm` |
| 746 | break term.c:103 |
| 747 | break term.c:284 |
| 748 | c |
| 749 | #### 直接在 tty1 不透過 screen 執行 的結果 ##### |
| 750 | Breakpoint 1, tterm_final (p=0x617a00) at term.c:103 |
| 751 | 103 tterm_reset_utmp(p); |
| 752 | (gdb) s |
| 753 | tterm_reset_utmp (p=0x617a00) at term.c:271 |
| 754 | 271 { |
| 755 | (gdb) s |
| 756 | 275 tn = rindex(p->name, '/') + 4; |
| 757 | (gdb) p p->name |
| 758 | $1 = "/dev/pts/0", '\0' <repeats 53 times> |
| 759 | #### 直接在 tty1 有透過 screen 執行 的結果 ##### |
| 760 | |
| 761 | Breakpoint 1, tterm_final (p=0x617a00) at term.c:103 |
| 762 | 103 tterm_reset_utmp(p); |
| 763 | (gdb) s |
| 764 | tterm_reset_utmp (p=0x617a00) at term.c:271 |
| 765 | 271 { |
| 766 | (gdb) s |
| 767 | 275 tn = rindex(p->name, '/') + 4; |
| 768 | (gdb) p p->name |
| 769 | $1 = "/dev/pts/1", '\0' <repeats 53 times> |
| 770 | }}} |
| 771 | * manpage of getutid(3) |
| 772 | {{{ |
| 773 | SYNOPSIS |
| 774 | |
| 775 | struct utmp *getutid(struct utmp *ut); |
| 776 | |
| 777 | DESCRIPTION |
| 778 | |
| 779 | getutid() searches forward from the current file position in the utmp |
| 780 | file based upon ut. If ut->ut_type is one of RUN_LVL, BOOT_TIME, |
| 781 | NEW_TIME, or OLD_TIME, getutid() will find the first entry whose |
| 782 | ut_type field matches ut->ut_type. If ut->ut_type is one of INIT_PRO- |
| 783 | CESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS, getutid() will find |
| 784 | the first entry whose ut_id field matches ut->ut_id. |
| 785 | |
| 786 | RETURN VALUE |
| 787 | getutent(), getutid(), getutline() and pututline() return a pointer to |
| 788 | a struct utmp on success, and NULL on failure. This struct utmp is |
| 789 | allocated in static storage, and may be overwritten by subsequent |
| 790 | calls. |
| 791 | |
| 792 | FILES |
| 793 | /var/run/utmp database of currently logged-in users |
| 794 | /var/log/wtmp database of past user logins |
| 795 | |
| 796 | NOTES |
| 797 | Glibc Notes |
| 798 | The above functions are not thread-safe. Glibc adds reentrant versions |
| 799 | |
| 800 | #define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE */ |
| 801 | #include <utmp.h> |
| 802 | |
| 803 | int getutent_r(struct utmp *ubuf, struct utmp **ubufp); |
| 804 | |
| 805 | int getutid_r(struct utmp *ut, |
| 806 | struct utmp *ubuf, struct utmp **ubufp); |
| 807 | |
| 808 | int getutline_r(struct utmp *ut, |
| 809 | struct utmp *ubuf, struct utmp **ubufp); |
| 810 | |
| 811 | These functions are GNU extensions, analogs of the functions of the |
| 812 | same name without the _r suffix. The ubuf parameter gives these func- |
| 813 | tions a place to store their result. On success they return 0, and a |
| 814 | pointer to the result is written in *ubufp. On error these functions |
| 815 | return -1. |
| 816 | |
| 817 | }}} |
| 818 | {{{ |
| 819 | root@intrepid:~# w |
| 820 | 02:01:29 up 5 min, 5 users, load average: 0.75, 0.91, 0.41 |
| 821 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT |
| 822 | root@intrepid:~# w |
| 823 | 02:02:14 up 6 min, 5 users, load average: 0.35, 0.78, 0.39 |
| 824 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT |
| 825 | root pts/0 :tty1:S.0 01:58 1:46m 0.24s 0.21s ./jfbterm -f /etc/jfbterm.conf -e /root/test.sh ### screen 0 |
| 826 | root pts/1 :tty1:S.1 01:58 3:55m 0.01s 0.01s /bin/bash ### screen 1 |
| 827 | root pts/3 172.21.253.1 01:59 1:19m 0.12s 0.10s gdb ./jfbterm 3833 ### from ssh for gdb |
| 828 | root pts/2 - 01:59 1:46m 0.00s 0.21s ./jfbterm -f /etc/jfbterm.conf -e /root/test.sh ### fb created by jfbterm |
| 829 | root pts/4 172.21.253.1 02:01 0.00s 0.02s 0.00s w ### from ssh for this command `w' |
| 830 | }}} |