這篇主要講"我的"實做方法
主要是給個程式的大略架構,不一定是最好的方法
僅供參考摟
int main() { PG_pipe Elie; PG_cmd Tio; PG_process Rixia; int seq_no = 0,pid; PG_TCP Noel; chdir(ROOT_DIC); Noel.go(); welcome_msg();
這邊我把程式切割成三大部分
pipe : 所有的pipe操作都透過該物件執行
cmd : 負責讀取資料,解析指令
process : 負責fork
TCP : 負責TCP/IP部份
while (1) { cout << "% "; Tio.seq_no = ++seq_no; Tio.read(); Tio.parse(); //Tio.show(); if (Tio.exit_flag) exit(0); int pipe_to = 0; if(Tio.delay) { pipe_to = seq_no + Tio.delay; Elie.connect(seq_no, pipe_to); }
讀入指令之後parse,parse的原則是把指令分割成一小段一小段以提供execv呼叫,標準作法上會利用strtok,不過這邊我自己用C++重刻了strtok部份,讓字串處理C++化,比較好抓Bug
if (pid = Rixia.harmonics()) { Elie.fix_main(seq_no); Rixia.Wait(); }
fork 主程序負責wait子程序結束
在wait之前,我利用fix_main把不必要的pipe關閉
else { Elie.fix_stdin(seq_no); if (Tio.pipe_err_flag) Elie.fix_stdout(seq_no,1); else Elie.fix_stdout(seq_no,0); Elie.clean_pipe();
子程序負責執行命令
先將pipe依照需求調整(dup pipe到stdin/stdout上面)
之後把沒用到的pipe關一關
if (Tio.redirect_to != "") Elie.redirect_to_file(Tio.redirect_to);
把標準輸入依照需求調整完之後,如果有偵測到重導檔案就重導
if(Tio.pipe_seg.size() > 2) { pipe_exec(Elie, Tio, 0, Tio.pipe_seg.size()-2); exit(0); cerr << "failed to exit" << endl; } else { Tio.exec(); }
看需不需要在單一指令裡面作a|b|c的動作,需要的話就另外呼叫函數處理pipe
不需要的話就直接呼叫execv系列的函數,執行目標指令
} } }
程式的大架構大致上是這樣