2014年12月9日 星期二

NTP client

要在router上自行更新時間,就必需要用到NTP service

參考資料:
NTP - 網路校時
解决ntp的错误 no server suitable for synchronization found
Linux RTC 時間對時校正
NTP协议以及ntpclinet使用
2012-09-15-NtpClient 选项用法
在linux中如何讀取並修改系統時間?
使用ntpdate更新系统时间

get ip address by DNS

目前要解析DNS去解析IP,
但是gethostbyname並不支援IPv6,
但有找到getaddrinfo可以達到同樣的功能,
而且同時有支援IPv4與IPv6

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
   struct addrinfo hints, *res, *p;
   int status;
   char ipstr[INET6_ADDRSTRLEN];

   if (argc != 2) {
       fprintf(stderr,"usage: showip hostname\n");
       return 1;
   }

   memset(&hints, 0, sizeof hints);
   hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
   hints.ai_socktype = SOCK_STREAM;

   if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
       fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
       return 2;
   }

   printf("IP addresses for %s:\n\n", argv[1]);

   for(p = res;p != NULL; p = p->ai_next) {
       void *addr;
       char *ipver;

       // get the pointer to the address itself,
       // different fields in IPv4 and IPv6:
       if (p->ai_family == AF_INET) { // IPv4
           struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
           addr = &(ipv4->sin_addr);/*error*/
           ipver = "IPv4";
       } else { // IPv6
           struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
           addr = &(ipv6->sin6_addr);/*error*/
           ipver = "IPv6";
       }

       // convert the IP to a string and print it:
       inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
       printf("  %s: %s\n", ipver, ipstr);
   }

   freeaddrinfo(res); // free the linked list

   return 0;
}

參考資料:
Sample getaddrinfo Code Compiles in Linux but not FreeBSD
getaddrinfo(3) - Linux man page
gethostbyname(), gethostbyaddr()
Porting IPv4 applications to IPv6
Porting IPv6 -- examples

2014年11月20日 星期四

linux signal相關設定

目前在寫daemon,
寫到了處理signal的程式

signal (SIGHUP, sighup_handler);
表示當這一個process收到一個SIGHUP時,
sighup_handler這一個函式會被執行。

SIGHUP
一般是用在參考檔案更新時。

可以直接透過下指令去驗証此function是否正常
kill -HUP 3077
killall -HUP a.out

SIGTERM, SIGINT


參考資料:
Sending signal to Processes
signal 小知識
Daemon函数的用法
寫 linux daemon 的注意事項

2014年11月17日 星期一

建立samba

因為compiler環境在linux,
而產生出來的image檔案必需要傳到windows上做燒錄的動作。

找了一下,有幾個方式可以完成,
FTP
WEB
網路芳鄰

目前看起來最簡單的方式應該是網路芳鄰samba

在多天的嘗試後,可以正常的使用帳號的方式連線到linux的空間,
可惜的是還沒有辦法試成功可以用匿名的方試登入(Guest)

========== 開始 ==========
0. 查詢是否有安裝samba
rpm -q samba

1. 查詢防火牆的狀態
systemctl status firewalld

2. 關掉防火牆
systemctl disable firewalld
systemctl stop firewalld

3. 新增samba使用者
smbpasswd -a caspar
若遇到以下錯誤訊息,表示系統沒有相對應的帳號。
目前的設置是linux系統有的帳號,samba才可以追加其帳號。

4. 停用samba使用者
smbpasswd -d caspar

5. 刪除samba使用者
smbpasswd -x caspar

6. 啟用samba服務
service smb start

7. 重新啟動samba服務
service smb restart

8. 查詢目前samba的狀態
service smb status

基本上新增samba使用者後,就可以由windows進入,但是,目前成功的方試,仍然要使用帳號跟密碼。

smbpasswd這一個指令可以做一些簡單的使用者帳號的操作,
但是更深入的操作方式就必需要使用pdbedit這一個指令

========== pdbedit 指令說明 ==========
pdbedit -L
列出使用者列表

pdbedit -Lv
列出詳細的使用者列表

pdbedit -Lw
列出同 smbpasswd 格式的使用者列表

pdbedit -a jerry
新增 jerry帳號

pdbedit -x jerry
刪除 jerry帳號

pdbedit -c "[D]" -u jerry
暫時停用 jerry 這個帳號

pdbedit -c "[]" -u jerry
恢復使用 jerry 這個帳號

========== 其它資訊 ==========
linux上登入window或是samba的電腦
smbclient //主機/分享的資料匣資源 -U 使用者名稱
輸入密碼就可以執行類似ftp的指令了

mount 別台機器分享的資源到本台電腦
mount -t smbfs -o username=使用者名稱 ,password=密碼 //主機名稱/分享的資源 /主機目錄

查詢使用的port
netstat -anp

查詢目前執行的程式
ps aux | grep mbd

在設定smb.conf時, 若嘗試要設定Guest登入
設定security為share
會出現以下錯誤
WARNING: Ignoring invalid value 'share' for parameter 'security'
改為以下就可以正常的
security = user
map to guest = Bad User

========== 自己安裝 samba-4.1.13 ==========
./configure
會出現以下錯誤訊息
Could not find the python development headers
安裝以下套解可以解除問題
yum install libacl-devel libblkid-devel gnutls-devel readline-devel python-devel gdb pkgconfig

參考資料:
如何檢查linux中的服務是否正常?
Samba 設定USER等級分享目錄[3]
Samba 下 Ubuntu與Win7共享資料夾設定,利用 host-only網路
Samba-4.1.13
安裝samba系統
fedora 10/11 安裝samba || windows 與 linux 的網芳設定
第十六章、檔案伺服器之二: SAMBA 伺服器

windows 網路指令

arp
可以查詢IP與MAC相對應的列表

arp -s 157.55.85.212 00-aa-00-62-c6-09 .... 新增靜態項目。
arp -a .... 顯示 ARP 表格。

2014年11月3日 星期一

daemon




參考資料:
寫 linux daemon 的注意事項

2014年10月30日 星期四

取得IPv6 address


參考資料:
get-ipv6-addr.c - Source file - www-user

sscanf使用心得


參考資料:
C 語言中的 sscanf() 函數

linux script

1. 判斷檔案是否存在

#!/bin/bash
file="/etc/hosts"
if [ -f "$file" ]
then
  echo "$file found."
else
  echo "$file not found."
fi

       -b FILE
              FILE exists and is block special
       -c FILE
              FILE exists and is character special
       -d FILE
              FILE exists and is a directory
       -e FILE
              FILE exists
       -f FILE
              FILE exists and is a regular file
       -g FILE
              FILE exists and is set-group-ID
       -G FILE
              FILE exists and is owned by the effective group ID
       -h FILE
              FILE exists and is a symbolic link (same as -L)
       -k FILE
              FILE exists and has its sticky bit set
       -L FILE
              FILE exists and is a symbolic link (same as -h)
       -O FILE
              FILE exists and is owned by the effective user ID
       -p FILE
              FILE exists and is a named pipe
       -r FILE
              FILE exists and read permission is granted
       -s FILE
              FILE exists and has a size greater than zero
       -S FILE
              FILE exists and is a socket
       -t FD  file descriptor FD is opened on a terminal
       -u FILE
              FILE exists and its set-user-ID bit is set
       -w FILE
              FILE exists and write permission is granted
       -x FILE
              FILE exists and execute (or search) permission is granted

參考資料:
Bash Shell: Check File Exists or Not

2014年10月23日 星期四

預設不啟動x window

為了節省資源,
在fedora可以預設把x window關掉。
打以下指令
# mv /etc/systemd/system/default.target /etc/systemd/system/default.target.bak
# ln -s /lib/systemd/system/runlevel2.target /etc/systemd/system/default.target

這樣下一次開機就不會啟動x window了

不過,若要啟動的話,
只要打
# startx
指令即可

參考資料:
Fedora 下设置系统不启动X window
Linux 的開機啟動流程

啟動ssh service

在fedora 20上啟動
# service sshd start

2014年10月22日 星期三

putty藍色字體看不清楚的問題

用putty連到linux server會出現藍色字體看不清楚的問題。

原本的顏色



選擇Colours的ANSI Blue,並且設定為以下數值
Red: 56
Green: 109
Blue: 199

這樣比較可以看的清楚了。



參考資料:
在putty 中设置字体的颜色和背景

2014年9月10日 星期三

Mapping of Address and Port (MAP)

最近在研究MAP這個東東,
這個東西主要是用來做什麼的呢?

眾所皆知, IPv4 address都已經發完了。
IPv6絕對是未來的方向。

可以想像的,
IPv4未來會成為IPv6網路的孤島。

可能會有總總因素,會讓使用者(client)或服務提供者(server)只能使用IPv4 network的情況,
而如何透過IPv6的網路來傳送IPv4的封包,
就是MAP要做的事情。

而要在IPv6的網路上傳輸,必需要有IPv6 address。
問題是如何把IPv4轉換成IPv6 address。

通常有兩個主要的方式,
stateful, stateless

什麼是stateful呢?
就是在每一個IPv4與IPv6轉換的設備上會有轉換的記錄,
例如:
292.11.45.1→2001:34:55:99:ac::2
292.45.11.3→2001:34:55:99:ac::3
也就是說每當要轉換時,必需由讀取這一個記錄,
才能了解要怎麼轉換。

而stateless則是會有一個演算法,
使得IPv4與IPv6可以直接透過這一個演算法來互相轉換。
一般來說都會比較推薦stateless的方式(原因是什麼我目前還不太清楚)。

而MAP主要分為
Mapping of Address and Port with Encapsulation (MAP-E)

Mapping of Address and Port with Translation (MAP-T).

這兩個主要的差別在於MAP-E是用封裝的方式,
直接在IPv4的封包外再加上IPv6的header,
這樣的好處是可以完整保存IPv4的封包。
但是,要傳送的封包是會比較大一點,因為額外加了IPv6的封包了嘛。

而MAP-T則是把IPv4的header轉換成IPv6的header,
缺點是額外做轉換的動作,
效能來說可能會比較慢一點。

先暫時寫到這裡,
最近一直在研究這個東西,
應該還會持續一段時間。

參考資料:
【自由谈】城域网IPv6过渡技术——MAP技术(1)

2014年9月1日 星期一

linux下停用IPv6

直接寫入1到
/proc/sys/net/ipv6/conf/all/disable_ipv6
就可以關掉整個IPv6的支援。

可以填到
/usr/etc/rcS裡面寫入
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6

其它方式可以參考
Linux 下關閉支援 IPv6 提升效能

2014年8月11日 星期一

顯示make編譯信息

現在在編code的時候,因為在確認一些細節,想了解實際的的編
但是,編譯的過程中,並沒有把make的實際細節顯示出來。

我知道可以透過@與-s或--silent把完整的訊息隱藏起來,
但我的Makefile並沒有這一些東西啊,為什麼還是會隱藏起來呢?

原來是在build kernel module的時候,會使用的linux kernel的makefile,而kernel的makefile有預設隱藏這一些訊息。

有兩個方式
1. 則要到kernel的makefile把這一些部分註解掉。
要俢改的檔案位置是在/usr/src/linux-2.6.38.8/Makefile
...
ifeq ($(KBUILD_VERBOSE),1)
# quiet =
# Q =
else
# quiet=quiet_
# Q = @
endif

# If the user is running make -s (silent mode), suppress echoing of
# commands

ifneq ($(findstring s,$(MAKEFLAGS)),)
# quiet=silent_
endif

#export quiet Q KBUILD_VERBOSE
...

如此一來,重新編譯的時候,就可以顯示完整的編譯過程了。

2. 使用make V=1就可以顯示完整的訊息了, 這個方式就超級方便的了。

參考資料:
顯示make編譯信息
Linux內核make命令選項

2014年6月4日 星期三

pipe的用法

使用 pipe() 可建立一組雙向的管線,
通常會使用一個陣列來建立pipe
例:
int pfd[2];
這是一條水管,
從 pfd[0] 進入的東西會從 pfd[1] 出來,
反之亦然,
除此之外,
它也是可以跨 Process,
達成兩個程式溝通的目的。

實做上必須注意以下幾個重點

1.有複製,就要有關閉,一個dup2搭一個close,保持file descriptor的單純性
(此為血淚經驗談,自己實做就知道…)

2.fork出去的程式,沒用到的file descriptor一定要記得關
舉例來說,本來shell主程式裡面有一個pipe,若是此時fork出子程序來exec指令,主程序下wait指令等待子程序執行完畢且主程序沒有關閉pipe,則主程序會卡住。因為當fork的時候,一個pipe實際上會變成兩個pipe,當指派子程序接收pipe資料的時候,如果還有其他pipe沒有關閉,則子程序會判定pipe資料流尚未結束,而繼續癡癡等待輸入,若是主程序有pipe沒關閉的話,結果就是主程序在等子程序結束,子程序又在等待主程序的pipe輸入資料,造成死結。

參考:
C/C++, Linux, Web 相關技術, 程式心得筆記, 系統研發手札
pipe @ Linux Kernel
[程設] Linux C 的file descriptor以及pipe操作相關筆記(上)
[程設] Linux C 的file descriptor以及pipe操作相關筆記(下)

2014年5月21日 星期三

Linux C - gcc 預先定義的巨集

在Linux下使用gcc編譯,
有幾個內建的變數可以非常好用,
在Debug的時候,
占非常重要的角色。

1. __BASE_FILE__
完整的原始檔案路徑

2. __cplusplus
表示該檔案由 g++ 所編譯,當成 C++ 的檔案

3. __DATE__
編譯的日期

4. __TIME__
編譯的時間

5. __FILE__
原始檔名

6. __LINE__
所在行數

7. __VERSION__
gcc 版本

8. __func__
替代 __FUNCTION__,__FUNCTION__ 已被 GNU 不推薦使用

參考資料:
LinuxC – gcc 預先定義的巨集

2014年5月9日 星期五

如何開啟windows 7的telnet與tftp

為了把image燒到測試的板子上面,
必需要用到tftp這一個指令。

而在windows 7預設是把telnet與tftp關掉。

如何把這兩個功能打開呢?

開啟控制台→程式集→開啟或關閉Windows功能



選擇「Telnet用戶端」與「TFTP用戶端」的選擇,
再按確定。



這樣就可以使用telnet與tftp了。

參考資料:
Win7 開啟 telnet and tftp

2014年5月5日 星期一

union

因為IPv6的address一共有128bit,
若要處理的話,
目前long int也只有4 bytes(32bit),
double只有8bytes(64bit)
沒有一個變數可以儲存到128bit,
這個時候就要用到union

直接寫下

/* IPv6 address */
struct in6_addr {
  union {
    uint8_t  u6_addr8[16];
    uint16_t u6_addr16[8];
    uint32_t u6_addr32[4];
  } in6_u;
#define s6_addr   in6_u.u6_addr8
#define s6_addr16  in6_u.u6_addr16
#define s6_addr32  in6_u.u6_addr32
};

這個宣告方式,可以讓128bit,
各別的使用8bit在運算。

下面是我寫的一個sub function,
也因為有了這個,
要運算IPv6才會變的比較簡單。

/*
 * Filter the IPv6 by prefix to Network ID or Interface ID
 *
 * @param IPv6_Addr_Src     the source for filtering
 * @param IPv6_Addr_Dst     the result of the filtering process
 * @param PrefixLen         the prefix of the network
 * @param MaskType          if the value is NetworkPrefix, network prefix would be reserved
 *                          if the value is InterfaceIdentifier, the interface identifier would be reserved
 */
static void
MaskIPv6 (
  struct in6_addr   IPv6_Addr_Src,
  struct in6_addr   *IPv6_Addr_Dst,
  int               PrefixLen,
  enum MaskType     Direction
  )
{
  char            *AddrPtr, *IndexAddrPtr;
  int             FullByteNumber, BitNumber;
  char            Mask;
  int             Index;
  int             CurrentPosition;

  //
  // The bytes of network id part
  //
  FullByteNumber = PrefixLen / 8;
  //
  // The bits of network id part
  //
  BitNumber = PrefixLen % 8;

  //
  // filter the bytes of Network ID part
  //
  for (CurrentPosition = 0; CurrentPosition < FullByteNumber; CurrentPosition++) {
    if (Direction == NetworkPrefix) {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0xFF;
    } else {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0x00;
    }
  }

  //
  // filter the bits of Network ID part and the bits of Interface ID part
  //
  Mask = 0;
  if (BitNumber != 0) {
    for (Index = 0; Index < BitNumber; Index++) {
      Mask = (Mask << 1) | 1;
    }

    for (Index = 0; Index < 8 - BitNumber; Index++) {
      Mask = Mask << 1;
    }

    if (Direction == InterfaceIdentifier) {
      Mask = ~Mask;
    }

    IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & Mask;

    CurrentPosition++;
  }

  //
  // filter the bytes of Interface ID part
  //
  for (; CurrentPosition < 16; CurrentPosition++) {
    if (Direction == NetworkPrefix) {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0x00;
    } else {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0xFF;
    }
  }

  //
  // Copy the modified IPv6_Addr_Src context for return
  //
  memcpy (IPv6_Addr_Dst, &IPv6_Addr_Src, sizeof (IPv6_Addr_Src));

}

2014年4月22日 星期二

IPv6的封包傳送的情境

目前正在研究,IPv6封包傳送的方式。

依IPv4的經驗,
當我要傳送出去的目的端位址,
是依目前的route table來判斷,
要送去哪一個介面。

命令提示字元輸入
route print

而要判斷是否為同一個network,則必需要使用到網路位址(IP)與網路遮罩做AND運算元的動作。
例如我要傳送一個封包到192.168.1.89,
則我route table要由下往上看。
先把網路遮罩(255.255.255.255)與192.168.1.89做AND運算元的動作,
255.255.255.255 & 192.168.1.89 = 192.168.1.89
並不與網路目的地255.255.255.255相同,
因此再往上比對上一個。

一直到比對到了倒數第7個,
先把網路遮罩(255.255.255.0)與192.168.1.89做AND運算元的動作,
255.255.255.0 & 192.168.1.89 = 192.168.1.0
與網路目的地192.168.1.0相同,因此會把這一個封包送到介面(192.168.1.100)

而當我要傳送一個封包到168.95.1.1(HiNet DNS),
一樣是由最底下開始比對,
一直到最上面那一筆做運算,
0.0.0.0 & 168.95.1.1 = 0.0.0.0
與網路目的地0.0.0.0相同,因此會把這一個封包送到介面(192.168.1.100)
並且透過把封包傳給Gateway(192.168.1.254)

以上是IPv4的情況。

在IPv6其實是差不多的。

命令提示字元輸入
route print


而要判斷要把封包傳送到哪一個介面,一樣要使用網路目的地這個東東。
而這一個組成結構是IPv6/Prefix
而運算的方式跟IPv4差不多。
若我要傳送資料到目的位址(2001:470:871c:581:bd81:7828:ca57:8888)
prefix是8的意思是說IPv6的128 bit前8bit是1,其餘的都是0。
則把目的位址PrefixAND運算元的動作。
2001:470:871c:581:bd81:7828:ca57:8888 & FF00:: = 2000::
結果並不等於ff00::
因此,再往上尋找。

一直到了到數第10個,
2001:470:871c:581:bd81:7828:ca57:8888 & FFFF:FFFF:FFFF:FFFF:: = 2001:470:871c:581::
結果與網路目的(2001:470:871c:581::)相同,
因此就把封包送到介面16。

若我想把封包送到2001:4860:4860::8888 (Google IPv6 DNS)
一樣是由最底下開始比對,
一直到最上面那一筆做運算,
:: & 2001:4860:4860::8888 = ::
與網路目的地::相同,因此會把這一個封包送到介面16,
並且透過把封包傳給Gateway(fe80::250:18ff:fe22:4491)
而這個fe80::250:18ff:fe22:4491剛好會是router的LAN port的IPv6 Link-Local Address

而若想知道介面代號指的是哪一個介面的話,可以使用下面的指令
netsh interface ipv6 show interface

2014年4月21日 星期一

tracert

在windows下要了解我的封包是如何傳送的,
可以使用tracert這一個指令。

若想知道對方的server是否還活著,
也可以使用ping這一個指令。

2014年4月18日 星期五

如何查詢目前的網路狀態

在windows下要查詢本機端的網路狀態,
最簡單的方式就到「命令提示字元」輸入ipconfig /all指令,
最完整的本機端完路設定就會出現了。

而若要透過視窗的方式表示出來的話,
則依「控制台」→「網路和網際網路」→「網路連線」
對「區域連線」按右鍵,
選擇「狀態」,再選擇「詳細資料」即可。



參考資料:
Windows 7 無法使用分享器上網時,應如何檢查設定?

2014年4月16日 星期三

RAMDisk on win7

之前的操作環境都是在XP,
一直到今年四月,
M$確定開始不支援XP了,
因此開始把操作環境改成Windows 7,
用到今天,突然我用的VSuite Ramdisk突然沒有辦法使用了。
看了一下,原來在Windows 7只能使用30天,
本來想支持一下正版的,
看了一下價錢,
3千多元,
因為我不是重度使用者,
若1千多元我就可以接受。

找到一個可以在windows 7下面使用的RamDisk軟體。
看起來不錯。
先用一陣子再說。

[2014.06.24 補充]
用了一陣子之後,
覺得跟之前的沒有什麼不一樣,
重點是免費的!!!
官方網頁

參考資料:
RAM Disk for Windows XP, Vista, 7 and 8
[更新]Ramdisk Windows 7 筆電加速與優化(使用SoftPerfect RAM Disk)
RamDisk on XP

PackEth

這個東西看起來可以自訂測試封包,
或許之後會用的到!



參考資料:
PackEth for Windows!

2014年4月9日 星期三

如何自定bool type

現在的code竟然沒有bool type,
上網找了一下,
有以下幾個方式可以自己定義。

Option 1

typedef int bool;
#define true 1
#define false 0

Option 2
typedef int bool;
enum { false, true };

Option 3
typedef enum { false, true } bool;

Option 4 (C99)
#include <stdbool.h>

Explanation
Options 1, 2 and 3 will have in practice the same identical behavior. #2 and #3 don't use #defines though, which in my opinion is better.
Option 4 will work only if you use C99 and it's the "standard way" to do it. Choose this if possible.
If you are undecided, go with #3!

參考資料:
C doesn't have any built in boolean types. What's the best way to use them in C?

typedef 與 link list的配合使用

今天要建立一個link list,
必定要使用到struct,
例如:

struct node_tag {
  int data;
  struct node_tag *link;
};
就是建立一個struct,而這一個struct裡面也有一個成員,
剛好就是這一個建立的struct。

而在使用這一個struct時,
直接宣告
struct node_tag Object;
Object.data = 2;
Object.link = NULL;

就可以了。

但是為了讓可讀性更好,
我嘗試修改為
typedef struct node_tag {
  int data;
  struct node_tag *link;
} node;
如此一來,在使用這一個struct時,
直接宣告
node Object;
Object.data = 2;
Object.link = NULL;


雖然這樣已經很不錯了,
但是,我希望可以更簡化。

修改如下
typedef struct node_tag {
  int data;
  node *link;
} node;

但是,這樣會有錯誤,
error: expected specifier-qualifier-list before 'node'
因為在宣告link的時候,
typedef struct node_tag node;
還沒有被建立完成。

此時,我天馬行空的想了一下,
typedef應該是標記某兩個label是同一個東西,
這個東西應該在compiler的時候不會被檢查,而是在link的時候,被指到同一個地方。
因此,我把內容改成如下:
typedef struct node_tag node;
struct node_tag {
  int data;
  node *link;
};
這樣就可以過了,
而且還蠻簡化的。

而我另外還看到另一個寫法
typedef struct node {
  int data;
  struct node *link;
} node;
這樣雖然完成typedef前跟完成type後,都是使用node為名稱,
但是,在定義node的內容仍出現struct node *link;
因此,這一個方式我個人不會採用。

========== 外記 ==========
另外有額外遇到一個情況,我宣告完typedef在h檔之後,
自定的函式的第一個參數Compiler仍出現錯誤。
error: expected ')' before '*' token
這一個錯誤就是沒有認到這一個typedef,
不過,我覺得很奇怪,
我定義typedef在a.h
而b.h宣告這一個function,
同時,b.h也有include a.h,
為什麼會認不到呢?

最後找到原因是,
我在b.h也有include a.h
因此在這一次的Compiler事實上是a.h去include b.h,
然後拿去Compiler,
因此,此宣告的函式是在typdef位置的上面,所以才會出現Compiler ERROR。

解法是在a.h拿掉b.h,
而直接把b.h加在a.c裡面。

之前我的習慣是把要加的.h檔都加在.h裡面,
原來還會遇到這個問題啊~

參考資料:
typedef
Linked list: function with a struct ptr parameter in header file error
LinkedList Struct Typedef in C

2014年4月3日 星期四

C/C++ 字串分析函式

========== 檔案相關 ==========
開啟檔案
FILE * fopen ( const char * filename, const char * mode );
fopen - C++ Reference
C 語言標準函數庫分類導覽 - stdio.h fopen()

關閉檔案
int fclose ( FILE * stream );
fclose - C++ Reference
C 語言標準函數庫分類導覽 - stdio.h fclose()

讀取資料
char * fgets ( char * str, int num, FILE * stream );
stdio.h 中的 fgets() 從檔案一行一行的讀取資料,共需三個參數,第一個參數為儲存輸入資料的陣列,第二個參數為該行最多幾個字元,第三個參數為指向結構 FILE 的指標。
fgets - C++ Reference
C 語言標準函數庫分類導覽 - stdio.h fgets()

========== 字串相關 ==========
搜尋函式:
const char * strchr ( const char * str, int character );
string.h 的函數 strchr() ,需要一個字串及一個字元當作參數,然後搜尋字元在字串中第一次出現的位置,回傳該位置的指標。
strchr - C++ Reference
C 語言標準函數庫分類導覽 - string.h strchr()

const char * strstr ( const char * str1, const char * str2 );
Parameters 1 是輸入字串,Parameters 2 是找尋字串,strstr 會先將頭一次比對成功的 pointer 回傳,也就是如果要找尋 appleboyappleboy 字串中的 boy,函式會回傳第一次比對成功的 boy pointer,而並非回傳最後一個比對到的。
strstr - C++ Reference
[C/C++] cstring (string.h) 搜尋函式:strstr, strchr


size_t strspn ( const char * str1, const char * str2 );
這有兩個解釋
1. 由字串開始,str1哪一個位置開始不包含str2裡面的字元,若第一個字元就不包含在str2裡面,當然就是回傳0(0 base)
2. strspn()會傳回兩個字串開始不匹配的第一個字元索引位置,否則傳回0
我覺得應該是1的這一個解釋比較正確,若有空可以來做一個實驗。
strspn - C++ Reference
C 語言標準函數庫分類導覽 - string.h strspn()
strspn()—返回从字符串开头连续包含特定字符的字符数目

切割函式
char * strtok ( char * str, const char * delimiters );
string.h 的函數 strtok() ,需要兩個字串參數,以第二個參數字串的內容切割第一個參數字串。
strtok - C++ Reference
C 語言標準函數庫分類導覽 - string.h strtok()
[C&C++] strtok
若一開始字串為
char buffer[] = "a string,of ,,tokens";
char *token = NULL;
char *line = NULL;
char *final = NULL;
原本記憶體內容為
a string,of ,,tokens
當執行完一次
token = strtok (buffer, " ,");
則記憶體內容為
a'\0'string,of ,,tokens
因此,若列印token的話,結果為a

再執行一次
line = strtok (NULL, " ,")
則記憶體內容為
a'\0'string'\0'of ,,tokens
因此,若列印line的話,結果為string

若這個時候,執行
final = strtok (NULL, "");
則記憶體內容不變,但,
列印final的話,結果為of ,,tokens

複製函數
char * strcpy ( char * destination, const char * source );
string.h 的函數strcpy() ,需要兩個字串當作參數,然後把第二個參數的字串複製到第一個參數的字串中,然後回傳第一個參數。
strcpy - C++ Reference
C 語言標準函數庫分類導覽 - string.h strcpy()

長度計算
size_t strlen ( const char * str );
strlen - C++ Reference
C 語言標準函數庫分類導覽 - string.h strlen()

字串比對
int strcmp (const char * str1, const char * str2 );
string.h 的函數strcmp() ,需要兩個字串當作參數,比較兩個字串是否相等,相等就回傳0,第一個字串大於第二個字串回傳正值,反之回傳負值。
strcmp - C++ Reference
C 語言標準函數庫分類導覽 - string.h strcmp()

int strcasecmp (const char * str1, const char * str2 ); // 非標準函式
strcasecmp()—判断字符串是否相等(忽略大小写)

判斷字元
int isspace (int c );
判斷此字元是否為空白
For the "C" locale, white-space characters are any of:

' ' (0x20) space (SPC)
'\t' (0x09) horizontal tab (TAB)
'\n' (0x0a) newline (LF)
'\v' (0x0b) vertical tab (VT)
'\f' (0x0c) feed (FF)
'\r' (0x0d) carriage return (CR)

isspace - C++ Reference
C 語言標準函數庫分類導覽 - ctype.h isspace()

int isalpha (int c );
Check if character is alphabetic (function )

int isdigit (int c );
Check if character is decimal digit (function )

2014年4月2日 星期三

vim - 複製

想要把第5行到第10行的內容貼到第12行之後,
要使用下面的指令
:5,10 co 12

參考資料:
[保留] 请问如何用vi 复制第5行到第10行并粘贴到第12行之后?

2014年4月1日 星期二

xshell軟體

之前遠端連到linux server都是使用putty或pietty(中文支援比較好)

最近又開始在玩linux了,
發現xshell這個新東西實在非常好用。

其中最好用的就是tab視窗,
尤其是我們常常一次就連很多個連線的人非常的需要。

參考資料如下: [網路工具] Xshell 4 超好用的 SSH 連線工具 - 強力推薦 xshell & xftp

2014年3月27日 星期四

strtok

這一篇文章寫的還蠻清楚的。

記錄一下~~

[C&C++] strtok

2014年3月20日 星期四

dump hex

在debug的時候,
有時候有一連串的資料需要看,
這個時候若一個變數一個變數處理,
會變的非常麻煩,
現在需要用到dump hex的指令,
而這個東西應該已經一堆人寫好了,
為了不要浪費時間,
直接去網路上找就可以了。

triple-column hex dump with ASCII representation

非常之好,
直接套用上去就可以啦~~

static in C code

這裡看到一個for static的解釋,
看起來還蠻清楚的,記錄一下。

Keyword Static (Function) [C++ 求生筆記]

不過,在C++中,static好像有特別的功能,
就是不需要宣告物件,
就可以直接透過類別來使用其static的函式。

設定TortoiseSVN比對時使用Beyond compare

在使用TortoiseSVN來看程式碼的差異時,
TortoiseSVN有內建的TortoiseMerge,
但因為實在太過陽春了,
還是建議使用外部程式來看檔案差異。

如下設定:


這裡要注意的是,若目前已經有存在的Beyond Compare的視窗,則會在這個視窗加一個tab顯示。

若不想要在目前已有的視窗顯示的話,
則加入/solo指令即可。
圖上圖中,灰階的部分。

2014年3月19日 星期三

Wireshark filter出DHCP封包

透過Wireshark抓DHCP封包。
觀察DHCP packet.

因DHCP是基於bootp協定,所以設定filter為bootp即可。

而若只要單純的抓options是53的話,可以設定
bootp.option.type==53
這樣會把options file有53的濾出來。

參考資料:
How to filter DHCP Traffic with Wireshark
wireshark 只過濾出DHCP封包

2014年3月14日 星期五

開啟多個skype

因為到了新的公司,
公司要求要有特定帳號名稱的skype,
因此,
又必需要另外申請skype帳號。

好啦,現在有兩個skype帳號,
只有一台電腦,
何解?

上網找了一下,
發現原來skype原本就有提供了可以啟動多個skype的功能了。

Skype.exe /secondary

用secondary就可以啟動另一個skype,
不過,能不能用同一個方式再啟動第三個skype呢?

確實是可以的!!

意外發現,
這個文章竟然是官方網站,
看來這個功能應該不會不見才對!!!

參考資料:
How can I run multiple Skype accounts on Windows desktop?

2014年3月13日 星期四

在linux下,使用ssh來操作vim同時trace code

這一次換到新的公司,
雖然工作環境看似windows,
但是,source code都必需要連到linux server操作,
因此必需要開始重新復習怎麼使用vim了。

要藉著使用ssh的方式來使用vim去trace code,
這個之前沒有完整用過,
以前至少是在本機端的QT IDE上操作,
現在要在遠端上使用,
必然會遇到很多問題,
不過,遇到問題是成長的過程,
這個是好的。

首先,如何在vim的編輯下,
跳出來shell,
並且在完成shell下的動作之後,
再回到vim哩?

:sh
暫時退出vim進入shell命令行,執行完後,ctrl+d退出重新進入vim編輯繼續

2014年2月3日 星期一

在醫院當志工的感想

1. 不是因為快樂令人變的感恩,而是因為懂得感恩令人變得更加快樂
2. 見苦知福
3. 知福、惜福、再造福
4. 因知足而懂得幫助別人
5. 幫助別人、得到最多的其實是自己
6. 什麼是需要?什麼是想要?
7. 平衡點

最近去醫院當志工,
到目前為止,
一共做了三次的醫院志工,
二次是「急診」,一次是「內科檢查室」外加支援「內科加護病房的外面」。

這三次下來,
真的體會到「人生最苦莫過於病痛」。
這一些病人因為身體的病痛,
必需要待在醫院,
而不能自由的在外面活動,
情況更差的,
就只能待在病床上等所有的治療流程。

我是在「急診室」與「內科加護病房」支援過,
這兩個定點一看就知道情況是比較差的情況。
在第一次擔任「急診室」的志工的時候,
有一位去其它診間看病的病人,
突然因心肌梗塞被送來急診,
這個時候警衛把病人放在輪椅,
很緊急的推過來,
一堆醫生和護理師就直接衝到急救區,
一段時間過後,
急救失敗,
病人往生了,
往急救室一看,
地上一堆沾滿血的紗布,
一個生命在無常間就失去了。

真的很令人震驚,
這一位病人並不是因為心肌梗塞來醫院的耶,
而是要去其它診間的,
但是,
確因為心肌梗塞而離開人世間。

接著家屬得到通知後,
來到急診室,
一整個不敢相信,
一直哭。

「有誰知道是無常先來,還是明天先來呢?」

其實來醫院當志工,
可以幫到什麼忙呢?
事實上幫不到什麼專業的東西,
但是,
可以幫忙打打雜,
推病床、幫護理師拿藥、跟病人聊天、幫忙注意病人的情況,
這一些東西一點都不專業,
但是,確可以讓護理師更可以專心在他們的工作上,
而不會因為要處理這一些雜事而分心。
我想對於醫院、醫生、護理師和病人應該多少有幫助的吧。

但是,事實上「幫助別人,得到最多的其實是自己。
為什麼呢?
我開始去思考,
大部分的人當然希望生活可以快樂,
但是,什麼樣的生活才快樂?

過去,
大家都往上看,
都會覺得自己想要的東西很多,
一直在追,
然後都會一直不滿足,
卻一直忽略身邊已經擁有的東西,
像是還健在的父母,
還算健康的身體,
而一直去追求現在沒有的東西。

等到追求到的東西的時候,
又有其它東西要追求,
而這一些東西追求到了之後,
還是有其它東西要追求,
因為,人的欲望是沒有止盡的~

那怎麼辦?
前一陣子看到一句話:
不是因為快樂令人變得感恩,而是因為懂得感恩令人變得更加快樂
很有道理的一句話,
但是,若是之前的我(三年前吧),
我會不知道為何而感恩,
說錢沒有錢,說車沒有車,說房沒房,
別人有的東西我都沒有,
我也想感恩啊,
但是,這太牽強了吧。

直到我看到「見苦知福」這一句話後,
我就懂了,
其實我們一直「生在福中而不知福!」
怎麼說呢?
當我們要喝水時,
飲水機打開,水就出來了,
這是很平常的事情,
也不會特別去注意,
但是,
當看到非洲連喝個水都很困難,
這麼看起來,
我們有水可以喝,
這不就是直得感恩的事嗎?

當父母在旁邊碎碎唸時,
我會覺得好煩,
但是,看到別人想要好好的孝順父母時,
父母卻已經不在了。
而我們回家,
父母會擔心我們吃的不夠飽、穿的不夠暖,
這不就是直得感恩的事嗎?
(當然有時候父母的觀念錯誤,也要給他正確的資訊,而不是逆來順受,要跟父母一起成長,要用父母可以理解的方式跟他們溝通)

看到一些人一生下來,
身體就有殘疾,
而我們四肢健全,
這不就是直得感恩的事嗎?

當在醫院看到這一群病人因為生病而必需待在病房,
而我們卻可以在外面自由行動,
甚至可以服務他人,
這不就是直得感恩的事嗎?

在這裡,
我被教導「要感恩那一些受到我們幫助的人」,
我之前不懂,
我幫助你,
我還要謝謝你?!
這是什麼道理?

深入了解之後,
才知道確實是有道理。

「這一些人(病人、戰爭災民、天災災民)不論是自願還是非自願,
他用自身表現出病、苦讓我們知道,
讓我知道怎我們擁有真的很多,
只是我們已經習慣了,
習慣擁有健康的身體,
習慣擁有便利的商店,
習慣擁有沒有血淋淋戰事的生活環境…
習慣了一堆我們擁有但是別人確沒有的東西」

這一些平常我們是不會注意到,
而這一些病人或是災民用自身來提醒我們,
我們擁有的真的很多,
所以,
我們要感恩這一些受到我們幫助的人的理由就在這裡。

而當我們透過「見苦知福」知道我們擁有很多,
而知道我們是有福的人之後,
就比較會樂於付出,
知福、惜福、再造福」。
如此才會有善的循環,
不是嗎?

另外,
要感恩這一些病人的另一個原因是,
當我親眼看到他們病痛的身體後,
我的心裡會想,
我一定不要把身體搞得跟他一樣,
如此一來,
我會去思考如何保持身體健康。

以我之前的經驗,
我在聽到別人熬夜到爆肝,
我會想說我應該沒有那麼剛好吧。
別人爆飲爆食到身體出了狀況,
也會想,我應該不會那麼倒楣吧。

但是,當親眼看到他們痛苦的畫面,
這真的跟聽別人說到不一樣,
比較震撼(就好像看到「十二夜」、「看見台灣」、「生命的吶喊」一樣)、
真的會讓自己提早去思考,
什麼東西是自己想要的?
而什麼東西是需要的?

聽過一句話:「人在年輕的時候,用健康去換錢;年紀大的時候,用錢去換健康」,
我一直在思考這個「平衡點」,
會失去平衡,通常是想要的太多,
而這一些想要的真的是必要的嗎?
真的不要等到失去健康才開始想怎麼挽回健康。

有人會說,
若太容易知足,
則會滿於現狀,
而不知進步。
人就是因為不知足,
才會進步,
所以,
人應該要懂得不知足!!

事實上,
追求更美好的事物是人之常情,
但是,我想的是,
也必需要了解自己擁有的東西,
與我接下來要追求的東西,
我必需要在這兩個東西裡面尋找一個平衡點。
而不是完全忽略我所擁有的東西,
而全力去追求自己目前沒有擁有的東西。
因為有時候追求目標時,
會要犧牲現在有的部份東西(像是過度追求財富,需要犧牲部份家庭時間,甚至健康...)。

等到有一天,
發現我本來擁有的東西不見時,
這個時候才回過頭來去追求我原本有的,
而現在失去的東西。

但一些東西失去了就回不來了,
像是小孩的成長過程, 身體健康, 或是父母健在...

平衡點」是我想要傳達的精神。

而透過去醫院當志工,
去發掘哪一些東西是我們現在擁有的東西,
但是,我們已經習以為常的東西,
把這一些東西跟我們現在要追求的東西在重新檢視,
尋找新的「平衡點」。

當發現別人現在沒有的東西(健康),
而我們現在竟然是擁有,
這個時候,
我們就會覺得很幸福並且滿足,
這個時候就會試著由「手心向上」改為「手心向下」。

這裡有一個問題,
當發現自己擁有很多,並且滿足後,
就會裹足不前嗎?

我也分析過,
當我們知道「手心向下」後,
必然會嘗試去做很多付出,
而在做這一些事情的過程中,
必定會遇到挫折,
而當我們遇到挫的時候,
會想要嘗試去提升自己的能力來解決這一個問題。

因此,懂得知足,並且學會「手心向下」,
並不會讓自己裹足不前,
反而會讓自己在知足感恩中提升自己的能力。

而當這一些受到幫助的人,
開心的一笑,
這不就是最好的回報嗎?

這不是雙贏嗎?

很高興有去當醫院志工,
讓我更懂得知足,
因知足而感恩,
因感恩而快樂,
因快樂而懂得付出,
因付出而遇到挫折,
因挫折而要提升自己的能力,
因提升自己的能力而進步。

感恩~~

下面的圖片是志工替病患辦的茶會,
醫院不只要醫病,
同時也要照顧病人的心,
很有趣的還有舞獅,
替病患帶來過年的氣氛XD