2009년 10월 6일 화요일
2008년 11월 23일 일요일
[Linux] Thread Server 포트 2개 열기
more..
/*
** selectserver.c -- a cheezy multiperson chat server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT1 9034 // port1 we're listening on
#define PORT2 9035 // port2 we're listening on
void *do_serv(void *argv)
{
int port_no = (int)argv;
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
struct sockaddr_in myaddr; // server address
struct sockaddr_in remoteaddr; // client address
int fdmax; // maximum file descriptor number
int listener; // listening socket descriptor
int newfd; // newly accept()ed socket descriptor
char buf[256]; // buffer for client data
int nbytes;
int yes=1; // for setsockopt() SO_REUSEADDR, below
socklen_t addrlen;
int i, j;
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
// get the listener
if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
// lose the pesky "address already in use" error message
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
// bind
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(port_no);
memset(myaddr.sin_zero, '\0', sizeof myaddr.sin_zero);
if (bind(listener, (struct sockaddr *)&myaddr, sizeof myaddr) == -1) {
perror("bind");
exit(1);
}
// listen
if (listen(listener, 10) == -1) {
perror("listen");
exit(1);
}
// add the listener to the master set
FD_SET(listener, &master);
// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(1);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == listener) {
// handle new connections
addrlen = sizeof remoteaddr;
if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr,
&addrlen)) == -1) {
perror("accept");
} else {
FD_SET(newfd, &master); // add to master set
if (newfd > fdmax) { // keep track of the maximum
fdmax = newfd;
}
printf("selectserver: new connection from %s on "
"socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd);
}
} else {
// handle data from a client
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf("selectserver: socket %d hung up\n", i);
} else {
perror("recv");
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
} else {
// we got some data from a client
for(j = 0; j <= fdmax; j++) {
// send to everyone!
if (FD_ISSET(j, &master)) {
// except the listener and ourselves
if (j != listener && j != i) {
if (send(j, buf, nbytes, 0) == -1) {
perror("send");
}
}
}
}
}
} // it's SO UGLY!
}
}
}
pthread_exit(NULL);
}
int main(void) {
pthread_t threads[2];
int rc;
rc = pthread_create(&threads[0], NULL, do_serv, (void *)PORT1);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
rc = pthread_create(&threads[1], NULL, do_serv, (void *)PORT2);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
pthread_exit(NULL);
};
출처 : http://kldp.org/node/94310 TCP Server [Thread]
more..
// by Softcream.kr/tc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#define MAXLINE 511
#define MAX_SOCK 1024 // 솔라리스의 경우 64
char *EXIT_STRING = "exit"; // 클라이언트의 종료요청 문자열
char *START_STRING = "Connected to chat_server \n";
// 클라이언트 환영 메시지
int maxfdp1, nbyte; // 최대 소켓번호 +1
int num_chat = 0; // 채팅 참가자 수
int clisock_list[MAX_SOCK]; // 채팅에 참가자 소켓번호 목록
int listen_sock; // 서버의 리슨 소켓
int clinum = 0, num = 0;
fd_set read_fds; // 읽기를 감지할 fd_set 구조체
pthread_t tid[MAX_SOCK]; // 각 클라이언트와 상대할 스레드 변수
pthread_mutex_t num_lock; // 뮤텍스 초기화
pthread_mutexattr_t mutex_attr; // 뮤텍스 속성 초기화
// 새로운 채팅 참가자 처리
void addClient(int s, struct sockaddr_in *newcliaddr);
int getmax(); // 최대 소켓 번호 찾기
void removeClient(int s, int t_tid); // 채팅 탈퇴 처리 함수
int tcp_listen(int host, int port, int backlog); // 소켓 생성 및 listen
void errquit(char *mesg) { perror(mesg); exit(1); }
void *thrfunc(void *arg);
int main(int argc, char *argv[]) {
struct sockaddr_in cliaddr;
int accp_sock, addrlen = sizeof(struct sockaddr_in);
int i, status;
pthread_mutexattr_init(&mutex_attr); // 뮤텍스
pthread_mutex_init(&num_lock, &mutex_attr); // 뮤텍스 속성 변수
if(argc != 2) {
printf("사용법 :%s port\n", argv[0]);
exit(0);
}
// tcp_listen(host, port, backlog) 함수 호출
listen_sock = tcp_listen(INADDR_ANY, atoi(argv[1]), 5);
while(1) {
FD_ZERO(&read_fds);
FD_SET(listen_sock, &read_fds);
for(i=0; i< num_chat; i++)
FD_SET(clisock_list[i], &read_fds);
maxfdp1 = getmax() + 1; // maxfdp1 재 계산
puts("wait for client");
if(FD_ISSET(listen_sock, &read_fds)) {
accp_sock=accept(listen_sock, (struct sockaddr
*)&cliaddr, &addrlen);
if(accp_sock == -1)
errquit("accept fail");
pthread_mutex_lock(&num_lock); // 뮤텍스 잠금
addClient(accp_sock,&cliaddr);
pthread_mutex_unlock(&num_lock); //뮤텍스 해제
send(accp_sock, START_STRING, strlen(START_STRING), 0);
printf("%d번째 사용자 추가.\n", num_chat);
// 각 클라이언트를 담당할 스레드 생성
if((status=pthread_create(&tid[num], NULL, &thrfunc, NULL))!=0)
errquit("pthread error");
num++;
continue;
}
} // end of while
return 0;
}
// 새로운 채팅 참가자 처리
void addClient(int s, struct sockaddr_in *newcliaddr) {
char buf[20];
inet_ntop(AF_INET,&newcliaddr->sin_addr,buf,sizeof(buf));
printf("new client: %s\n",buf);
// 채팅 클라이언트 목록에 추가
clisock_list[num_chat] = s;
num_chat++;
}
// 채팅 탈퇴 처리
void removeClient(int s, int ptid) {
close(clisock_list[s]);
if(s != num_chat-1)
clisock_list[s] = clisock_list[num_chat-1];
num_chat--;
printf("채팅 참가자 1명 탈퇴. 현재 참가자 수 = %d\n", num_chat);
pthread_cancel(ptid); // 해당 스레드 삭제
}
// 최대 소켓번호 찾기
int getmax() {
// Minimum 소켓번호는 가정 먼저 생성된 listen_sock
int max = listen_sock;
int i;
for (i=0; i < num_chat; i++)
if (clisock_list[i] > max )
max = clisock_list[i];
return max;
}
// listen 소켓 생성 및 listen
// listen 소켓 생성 및 listen
int tcp_listen(int host, int port, int backlog) {
int sd;
struct sockaddr_in servaddr;
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1) {
perror("socket fail");
exit(1);
}
// servaddr 구조체의 내용 세팅
bzero((char *)&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(host);
servaddr.sin_port = htons(port);
if (bind(sd , (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind fail"); exit(1);
}
// 클라이언트로부터 연결요청을 기다림
listen(sd, backlog);
return sd;
}
void *thrfunc(void *arg) // 스레드 함수 부분. 스레드 하나가 하나의 클라이언트를 담당
{
int i, j, cnt, status;
pthread_t ptid;
char buf[MAXLINE+1];
ptid = (pthread_t*) &tid[num]; // 스레드의 tid
if( (status=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))!=0) {
printf("pthread_setcancelstate fail: %s\n",strerror(status));
exit(0); // 취소 요청 허용
}
if( (status=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))!=0) {
printf("pthread_setcanceltype fail: %s\n",strerror(status));
exit(0); // 취소 요청시 즉시 종료
}
cnt = clinum;
clinum++;
while(1){
FD_ZERO(&read_fds);
FD_SET(listen_sock, &read_fds);
for(i=0; i < num_chat; i++)
FD_SET(clisock_list[i], &read_fds);
if(FD_ISSET(clisock_list[cnt], &read_fds)) {
nbyte = recv(clisock_list[cnt], buf, MAXLINE, 0);
if(nbyte<=0) {
pthread_mutex_lock(&num_lock); // 뮤텍스 잠금
removeClient(i,ptid); // 클라이언트의 종료
pthread_mutex_unlock(&num_lock); // 뮤텍스 해제
continue;
}
buf[nbyte] = 0;
// 종료문자 처리
if(strstr(buf, EXIT_STRING) != NULL) {
pthread_mutex_lock(&num_lock); // 뮤텍스 잠금
removeClient(i,ptid); // 클라이언트의 종료
pthread_mutex_unlock(&num_lock); // 뮤텍스 해제
continue;
}
// 모든 채팅 참가자에게 메시지 방송
for (j = 0; j < num_chat; j++)
send(clisock_list[j], buf, nbyte, 0);
printf("%s\n", buf);
}
}
}
2008년 11월 18일 화요일
JAVA 와 C 간의 TCP 통신시 Endian 처리
두 다른 언어를 TCP 로 연결할때 플랫폼이 다르다면 시스템이 little-Endian / Big-Endian 인지 확인하여야한다.
일반적으로 Linux 은 little-Endian Windows 는 Big-Endian 을 사용한다. ( 시스템 마다 차이 있을수 있음 )
Server ( Linux C )
Client (windows JAVA) 일경우에는 ..
C 에서 받은 버퍼를 받아 Endian 처리를 다음과 같이 변환하여야한다. (int 자료형 등을 받을때)
* Java는 모든 플렛폼에서 정수를 표현할 때 Big-Endian 방식을 사용한다.
* Little-Endian을 사용하는 플렛폼에서 보낸 이진데이터를 받을 경우
Big-Endian으로 변환하여 사용해야한다.
* 다음은 자바에서 Big Little Endian변환을 수행하는 로직이다.
*/
public class Endian{
/**
* 자바에서 사용하는 Big-Endian 정수값을 Little-Endian 바이트 배열로 변환한다.
*/
public static byte[] getLittleEndian(int v){
byte[] buf = new byte[4];
buf[3] = (byte)((v >>> 24) & 0xFF);
buf[2] = (byte)((v >>> 16) & 0xFF);
buf[1] = (byte)((v >>> 8) & 0xFF);
buf[0] = (byte)((v >>> 0) & 0xFF);
return buf;
}
/**
* Little-Endian 바이트 배열을 자바에서 사용하는 Big-Endian정수로 변환한다.
*/
public static int getBigEndian(byte[] v)throws Exception{
int[] arr = new int[4];
for(int i=0;i<4;i++){
arr[i] = (int)(v[3-i] & 0xFF);
}
return ((arr[0] << 24) + (arr[1] << 16) + (arr[2] << 8) + (arr[3] << 0));
}
}
C <--> JAVA 통신 설정시 잘못된 값이 나올수 있기 때문에, 이유 정도는 알아둘 필요가 있다.
이것이 구찮다면 전부 byte 로 보내자 ..;;
소스출처: http://blog.naver.com/joodong1027?Redirect=Log&logNo=130023035042
2008년 11월 16일 일요일
[Linux] TCP Binary File 전송
바이너리 파일 전송은 전송하는 파일의 사이즈가 동일하여야 하는것은 당연한 것이다.
JAVA 라면 알아서 쉽게 해결되겠지만 C의 경우는 가끔 버퍼를 먹어버리거나 손실되는 경우가 발생되기때문에
사이즈를 정확하게 맞추기가 생각보다 까다롭다.( 절대 어렵다는 예기가 아님 ;;)
해당 방식은 서버로부터 파일사이즈를 먼저 받고 그 파일사이즈만큼 받는 방식이다.
상호 지정된 버퍼만큼 들어온다고 가정하고 파일의사이즈 를 루프를 돌면서 들어오는 버퍼의 양만큼 감산한다.
파일의 사이즈가 지정된 버퍼사이즈 보다 적을때는 남은 파일의사이즈 만큼만 받는다.
( 이렇게 하는 이유는 약간씩 오버헤드 또는 쓰레기 값이 들어올수 있게 되기때문에 파일사이즈가 불일치 할 확률이 매우 높아진다. )
server.c 소스
fsize = 0, nsize = 0, fpsize = 0;
file = fopen("test.jpg","rb");
fseek(file,0,SEEK_END);
fsize = ftell(file);
fseek(file,0,SEEK_SET);
send(sd,&fsize,sizeof(fsize),0); // 파일의 사이즈를 보냄
while(nsize != fsize){ // 파일을 보냄
fpsize = fread(buf,1,MAXLINE,file);
nsize = nsize + fpsize;
send(sd,buf,fpsize,0);
} // end of while
fclose(file);
client.c 소스
filesize = 0;
file = fopen("test.jpg","wb");
recv(sd,&filesize,sizeof(filesize),0); // 파일의 사이즈를 받음
bufsize = MAXLINE; // 기본 버퍼 설정
while(filesize != 0){ // 받은 버퍼의 총사이즈가 파일의 사이즈와 같을때 까지 loop
if(filesize < MAXLINE) // 남은 파일 사이즈가 버퍼보다 적을때
bufsize = filesize;
nbyte = recv(sd,buf,bufsize,0);
filesize = filesize - nbyte;
fwrite(buf,sizeof(char),nbyte,file);
nbyte=0;
} // end of while
fclose(file);
2008년 11월 5일 수요일
TCP Server/Client (Fork)
Server.c
more..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
char *EXIT_STRING = "exit"; // 종료문자
int recv_and_print(int sd); // 상대로부터 메시지 수신후 화면출력
int input_and_send(int sd); // 키보드입력받고 상대에게 메시지전달
int sendtime(int sd);
#define MAXLINE 511
int main(int argc, char *argv[]) {
struct sockaddr_in cliaddr, servaddr;
int listen_sock, accp_sock, // 소켓번호
addrlen = sizeof(cliaddr);
pid_t pid;
if (argc != 2) {
printf("사용법: %s port\n", argv[0]);
exit(0);
}
// 소켓 생성
if((listen_sock=socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket fail");
exit(0);
}
// 서버의 소켓주소 구조체 servaddr을 '0'으로 초기화
bzero((char *)&servaddr, sizeof(servaddr));
// servaddr을 세팅
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(atoi(argv[1]));
// bind() 호출
if(bind(listen_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind fail");
exit(0);
}
puts("서버가 클라이언트를 기다리고 있습니다");
listen(listen_sock, 1);
// 클라이언트 연결요청 수락
if((accp_sock = accept(listen_sock,(struct sockaddr *)&cliaddr, &addrlen)) < 0) {
perror("accept fail");
exit(0);
}
puts("클라이언트가 연결되었습니다.");
if( (pid = fork()) > 0) {
if((pid=fork())>0){
input_and_send(accp_sock); // 키보드입력받고 상대에게 메시지전달
}else if(pid==0){
sendtime(accp_sock);
}else{
perror("fork 에러");
close(listen_sock);
close(accp_sock);
}
}else if (pid == 0){
recv_and_print(accp_sock); // 상대로부터 메시지 수신후 화면출력
}
close(listen_sock);
close(accp_sock);
return 0;
}
// 키보드입력받고 상대에게 메시지전달
int input_and_send(int sd) {
char buf[MAXLINE+1];
int nbyte;
while(fgets(buf, sizeof(buf), stdin) != NULL) {
nbyte = strlen(buf);
write(sd, buf, strlen(buf));
// 종료문자열 입력 처리
if (strstr(buf, EXIT_STRING) != NULL ) {
puts("Good bye.");
close(sd);
exit(0);
}
}
return 0;
}
// 상대로부터 메시지 수신후 화면출력
int recv_and_print(int sd) {
char buf[MAXLINE+1];
int nbyte;
while(1) {
if( (nbyte=read(sd, buf, MAXLINE))<0){
perror("read fail");
close(sd);
exit(0);
}
buf[nbyte] = 0;
// 종료문자열 수신시 종료
if (strstr(buf, EXIT_STRING) != NULL )
break;
printf("%s", buf); // 화면 출력
}
return 0;
}
int sendtime(int sd)
{
char *buf;
time_t tim;
while(1){
sleep(10);
tim=time(NULL);
buf=ctime(&tim);
write(sd, buf, strlen(buf));
}
return 0;
}
Client.c
more..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXLINE 511
char *EXIT_STRING = "exit"; // 종료문자 정의
int recv_and_print(int sd); // 상대로부터 메시지 수신후 화면출력
int input_and_send(int sd); // 키보드입력받고 상대에게 메시지전달
int main(int argc, char *argv[]) {
pid_t pid;
static int s;
static struct sockaddr_in servaddr;
// 명령문 입력 인자 처리
if (argc != 3) {
printf("사용법: %s server_ip port \n", argv[0]);
exit(0);
}
// 소켓 생성
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
printf("Client: Can't open stream socket.\n");
exit(0);
}
// servaddr을 '0'으로 초기화
bzero((char *)&servaddr, sizeof(servaddr));
// servaddr 세팅
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
servaddr.sin_port = htons(atoi(argv[2]));
// 서버에 연결요청
if(connect(s,(struct sockaddr *)&servaddr,sizeof(servaddr)) <
0) {
printf("Client: can't connect to server.\n");
exit(0);
}
if( (pid=fork())>0) // 부모 프로세스
input_and_send(s);
else if(pid==0) // 자식 프로세스
recv_and_print(s);
close(s);
return 0;
}
// 키보드입력받고 상대에게 메시지전달
int input_and_send(int sd) {
char buf[MAXLINE+1];
int nbyte;
while(fgets(buf, sizeof(buf), stdin) != NULL) {
nbyte = strlen(buf);
write(sd, buf, strlen(buf));
// 종료문자열 입력 처리
if (strstr(buf, EXIT_STRING) != NULL ) {
puts("Good bye.");
close(sd);
exit(0);
}
}
return 0;
}
// 상대로부터 메시지 수신후 화면출력
int recv_and_print(int sd) {
char buf[MAXLINE+1];
int nbyte;
while(1) {
if( (nbyte=read(sd, buf, MAXLINE))<0) {
perror("read fail");
close(sd);
exit(0);
}
buf[nbyte] = 0;
// 종료문자열 수신시 종료
if (strstr(buf, EXIT_STRING) != NULL )
break;
printf("%s", buf); // 화면 출력
}
return 0;
}
Small Shell Version #1
ex) 200500001$ ./a.out &
2. redirect(>), more(|)를 추가 구현하라.
ex) 200500001$ ./a.out >output
200500001$ ./a.out | more
shell.c
more..
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#define MAX 256
int main()
{
char *i;
char buf[MAX], buf1[MAX], buf2[MAX];
int fd[2],fp ,n ,status;
pid_t pid;
printf("$ 200103937 >> "); // prompt
while(fgets(buf, MAX, stdin) != NULL) // 키보드로부터 입력을기다린다.
{
// '\n' 문자만입력돠었을때, 즉only Enter press.
if(strlen(buf) == 1 || (buf[0] == NULL)){
printf("$ 200203937 >> ");
continue // 다시 키보드로부터 입력을 기다린다.
}
buf[strlen(buf)-1] = NULL;
if(!strcmp(buf,"exit")) exit(0);
// buf에 해당문자열이 있는지 검사한다.
if((i = index(buf,'|')) != NULL || (i = index(buf,'>')) != NULL || (i = index(buf,'&')) != NULL)
{
if( *i == '|') // a.out | more
{
// buf 문자열중에 exec할 파일경로를 buf1에 복사..
strncpy(buf1, buf, i - buf - 1);
pipe(fd); // 파이프생성.
pid = fork();
if(pid < 0)
{
perror(" Fork Error!! \n");
exit(1);
}
else if(pid == 0) // ./a.out
{
/* ./a.out 하여 얻은 데이터를 stdout 대신에pipe를 연결하여
pipe의 write 채널로 연결시킨다. */
close(1); // stdout close.
close(fd[0]); // pipe fd[0] close.
dup(fd[1]); // stdout 자리에pipe fd[1] 복사.
close(fd[1]); // pipe fd[1] close.
execlp(buf1,buf1,0); // 다른프로그램으로exec.
perror("execlp error!!"); // exec 실패시에러출력.
exit(1);
}
if(fork() == 0) // more exec.
{
/* stdin 채널을닫고 그 자리에 pipe의read 채널을 복사하여
pipe로부터 데이터를 read 한다. */
close(0); // stdin close.
close(fd[1]); // pipe fd[1] close.
dup(fd[0]); // stdin 자리에pipe fd[0] 복사.
close(fd[0]); // pipe fd[0] close.
// 다른프로그램으로exec.
execl("/bin/more","more", NULL, NULL);
perror(" execl error!! "); // exec 실패시에러출력.
exit(1);
}
close(fd[0]);
close(fd[1]);
wait(0); // wait child process.
wait(0); // wait child process.
}
else if( *i == '>') // ./a.out > output.
{
// buf 문자열중에 exec할 파일경로를 buf1 에복사.
strncpy(buf1, buf, i - buf - 1);
// buf 문자열중에 파일로 출력할 파일경로를 buf2 에복사.
strncpy(buf2, i + 2, buf + strlen(buf) - i - 2);
fp = creat(buf2, 0666); // 출력할 파일을 새로만든다.
pipe(fd); // 파이프생성.
pid = fork(); // process 생성
if(pid < 0){
perror(" Fork Error!! \n");
exit(0);
}
else if(pid == 0) // child process.
{
close(0); // stdin close
dup(fd[0]); // stdin 자리에pipe의write 채널을 복사한다.
close(1); // stdout close.
dup(fp); // stdin 자리에fp 복사.
close(fd[0]);
close(fd[1]);
execlp(buf1, buf1, (char*)0); // 다른 프로그램으로 exec.
perror("execlp error!!"); // exec 실패시 에러출력.
exit(1);
}
wait(0); // wait child process.
close(fp);
printf("$ 200103937 >> ");
}
else // ./a.out&
{
if(*i == '&') // buf 에background 표시가 있을때.
{
buf[strlen(buf)-1] = NULL; // exec 을위해'&' 문자제거.
}
if((pid = fork()) == 0) // child process
{
execlp(buf, buf, (char*)0); // 다른 프로그램으로 exec.
perror(" execlp error!! "); // exec 실패시 에러출력.
exit(1);
}
printf("$ 200103937 >> ");
continue
}
}
else // foreground
{
if((pid = fork()) == 0) // child process
{
execlp(buf, buf, (char*)0); // 다른 프로그램으로 exec.
perror("execlp error!!"); // exec 실패시 에러출력.
exit(1);
}
// foreground 일경우. 즉, child process 의종료를 기다린다.
// 사용자쉘은 뜨지않고 수행이 끝날때까지 block 된다.
while(wait(&status)!= pid);
printf("$ 200103937 >> ");
}
} // end of while
return 0 ;
}