2016年8月9日 星期二

C語言巨集、單井號(#)和雙井號(##)

C(和C++)中的巨集(Macro)屬於編譯器預處理的範疇。
下面對常遇到的巨集的使用問題做了簡單總結。

單井號(#)和雙井號(##)

(#)的功能是將其後面的巨集引數進行字串化操作(Stringfication):

#define WARN_IF(EXP) /
do{ if (EXP) /
fprintf(stderr, "Warning: " #EXP "/n"); } /
while(0)

實際使用會出現下面的替換過程:

WARN_IF (divider == 0);

被替換為

do {
if (divider == 0)
fprintf(stderr, "Warning" "divider == 0" "/n");
} while(0);

定義單行巨集:主要有以下三種用法。

1) 前加##或後加##,將標記作為一個合法的識別字的一部分,例如:

#define A(x) T_##x // int A(1) = 10; 等效於 int T_1 = 10;
#define A(x) Tx##__ // int A(1) = 10; 等效於 int T1__ = 10;

2) 前加#@,將標記轉換為相應的字元,注意:僅對單一標記轉換有效:

#define B(x) #@x // B(a) 等效 'a',B(1) 等效 '1',但B(abc)卻不甚有效。

3) 前加#,將標記轉換為字串。

#define C(x) #x // C(1+1) 等效於 "1+1"


(##)連接子(concatenator),
            其功能是在帶參數的巨集定義中將兩個Token聯接起來,從而形成一個新的Token。
    但它不可以是第一個或者最後一個子串。

譬如做一個功能表項目命令名稱和函數指標組成的結構陣列,並在函數名和功能表項目命令名之間有直接名字上的關係:

struct command
{
  char * name;
  void (*function) (void);
};

#define COMMAND(NAME) { NAME, NAME ## _command }

struct command commands[] = {
  COMMAND(quit),
  COMMAND(help),
  ...
}

COMMAND在這裡充當一個代碼生成器的作用,這樣可以在一定程度上減少代碼密度,
間接地也可以減少不留心所造成的錯誤。
我們還可以n個##符號連接 n+1個Token,這個特性也是#符號所不具備的。譬如:

#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d

typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);

// 這裡這個語句將展開為:
// typedef struct _record_type name_company_position_salary;

MSDN上的一個例子:

#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;

// Main中調用 paster( 9 ); 這個語句將展開為:
// printf( "token" "9" " = %d", token9 );

注意到在這個例子中,paster(9); 中的這個”9”被原封不動的當成了一個字串,
與”token”連接在了一起,從而成為了token9。
而 #n 也被”9”所替代。可想而知,上面程式運行的結果就是在螢幕上列印出token9=9

2016年7月12日 星期二

Ubuntu mount folder automatically

Create your username/password file for access server

# sudo -s
# nano /root/.smbcredentials

Add the following to it

username=deray.xu
password=userpassword


Edit /etc/fstab

#nano /etc/fstab

Add the following to it
//file.server.com/folder /home/deray/mount cifs credentials=/root/.smbcredentials,iocharset=utf8,file_mode=0777,dir_mode=0777,domain=deray.com,sec=ntlm 0 0


直接寫上帳號密碼的方式:
//file.server.com/folder /home/deray/mount smbfs defaults,username=deray.xu,password=userpassword,_netdev,file_mode=0777,dir_mode=0777 0 1


安裝cifs支援
# sudo apt-get install cifs-utils

利用 rsync + ssh + crontab 做主機自動同步備份

1. 安裝rsync

# sudo apt-get install rsync

檢查
# dpkg -l | grep rsync


2. 製作不需密碼就可以登入的ssh用戶

在client端製作公鑰和私鑰

# ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/home/deray/.ssh/id_rsa):
Created directory '/home/deray/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/deray/.ssh/id_rsa.
Your public key has been saved in /home/deray/.ssh/id_rsa.pub.

最後鑰匙會產生在家目錄的.ssh目錄下,id_rsa.pub是公鑰,id_rsa就是私鑰,
把公鑰傳到server上,然後到server上,將公鑰加入authorized_keys,
authorised_keys放在家目錄的.ssh目錄下,如果還沒有這個目錄,手動把它建立起來

# mkdir .ssh

第一次還沒有authorized_keys,直接用cat把id_rsa.pub的內容加進去
# cat id_rsa.pub >> authorized_keys

以後要加其他的公鑰,也是用cat附加到該檔案後面就可以

回到client端,試試看是否不需要詢問密碼就能登入

# ssh xxx@xxx.xxx.xxx


3. rsync同步備份

在client端輸入以下指令
# rsync -av --delete -e ssh xxx@xxx.xxx.xxx:/var/www /home/backup

把server上的/var/www同步備份到client的/home/backup,
之後server端有任何異動,只會同步備份異動的部份。


4. 設定crontab讓備份自動執行

在client端把rsync指令寫到crontab裡

# crontab -e
3 5 * * * rsync -av --delete -e ssh xxx@xxx.xxx.xxx:/var/www /home/backup
這樣就是在每天凌晨03:05自動同步備份

Ubuntu sudo 不用輸入密碼

修改/etc/sudoers

# visudo

( # sudo vi /etc/sudoers )

把
%admin ALL=(ALL)
改成
%admin ALL=(ALL) ALL NOPASSWD: ALL

或把單一使用者改為不用輸入密碼:
在檔案最後加入
deray ALL=(ALL) NOPASSWD: ALL


sudoers內容意義


root ALL=(ALL) ALL

這行意思是,使用者root能從所有的終端機,
以任何所有使用者的身分,
來執行所有任何的指令。

所以第一部分是什麼使用者,
第二部分是使用者從哪個終端機能執行sudo,
第三部分是哪個使用者能執行,
最後部分是他能跑什麼指令。

Ubuntu中文資料夾改成英文

1. 打開console視窗,先使用以下指令確認目前語系:
# echo $LANG

2. 然後輸入export LANG=en_US,將語系變更為「英文」:
# export LANG=en_US

3. 接著輸入xdg-user-dirs-gtk-update,此時就會出現GUI的資料夾更名程式,
    然後選擇「更名」,就可以將預設資料夾改為英文:
# xdg-user-dirs-gtk-update

4. 在console視窗中輸入export LANG=[步驟1記下的語系設定],
    然後再做一次步驟3,此時要選擇「保留舊名稱」

* 前提是這些使用者系統預設的資料夾內必須是空的,
   如果有某個中文檔名資料夾內有其他檔案 ,
   雖然新的英文檔案夾仍會產生,
   但舊的中文檔案夾仍存在 檔案仍在舊的中文資料夾內。

---

指令修改方式:

# cd ~
# rm Desktop
# mv 桌面 Desktop
# mv 模板 Template
# mv 公共 Public
# mv 文件 Document
# mv 音樂 Music
# mv 圖片 Picture
# mv 影片 Video
# ln -s Desktop 桌面
# ln -s Template 模板
# ln -s Public 公共
# ln -s Document 文件
# ln -s Music 音樂
# ln -s Picture 圖片
# ln -s Video 影片

# nano ~/.config/user-dirs.dirs

XDG_DESKTOP_DIR="$HOME/Desktop"
XDG_DOWNLOAD_DIR="$HOME/Desktop"
XDG_TEMPLATES_DIR="$HOME/Template"
XDG_PUBLICSHARE_DIR="$HOME/Public"
XDG_DOCUMENTS_DIR="$HOME/Document"
XDG_MUSIC_DIR="$HOME/Music"
XDG_PICTURES_DIR="$HOME/Picture"
XDG_VIDEOS_DIR="$HOME/Video"

# sudo /etc/init.d/gdm restart

Linux install Git

Install Git

# sudo apt-get -y install git-core git-doc git-gui gitk gitg


其他開發可能需要的套件

# sudo apt-get install openjdk-7-jre

# sudo apt-get install build-essential gawk pkg-config gettext automake autoconf libtool bison flex zlib1g-dev libgmp3-dev libmpfr-dev libmpc-dev texinfo mc
sudo apt-get install libglib2.0-dev


設定 GCC PATH

# sudo nano /etc/profile
PATH="$PATH:/opt/buildroot-gcc???/bin/"
export PATH

Ubuntu Install tftp

安裝

# sudo apt-get install tftpd-hpa


無法正常安裝時可嘗試以下指令

# sudo apt-get install tftp-hpa tftpd-hpa openbsd-inetd
# sudo apt-get install xinetd


建立目錄tftpboot,用於傳輸文件

# sudo mkdir /tftpboot
# sudo chmod -R 777 /tftpboot
# sudo chown -R nobody /tftpboot


修改設定檔

# sudo nano /etc/default/tftpd-hpa

TFTP_USERNAME="root"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-s -c -l"

Note: -l for listening all time this avoided the timeout issue, -c to create files in tftfp folder.


tftp服務控制

# sudo service tftpd-hpa restart
# sudo service tftpd-hpa start
# sudo service tftpd-hpa stop


確認tftp服務是否開啟

# netstat -a | grep tftp

出現以下訊息,表示成功開啟
udp    0   0 *:tftp     *:*



Uninstalling HEVC Video Extensions from Windows

Microsoft store packages are usually APPX format installations (HEVC Video Extensions is installed as APPX package) You will need to use Pow...