이 코드에서 링크드 리스트가 제대로 구현된건가요..
글쓴이: superkkt / 작성시간: 목, 2005/10/13 - 6:15오후
안녕하세요. 아이디와 패스워드가 똑같은 계정을 찾아내는 프로그램을 짜봤는데요.. shadow파일의 처음부터 끝까지 읽는걸 반복하는 부분이 엔트리가 많은 시스템에서는 성능이 떨어지는것 같아서 링크드 리스트를 이용해 봤습니다.
그런데 제대로 구현이 된건지 모르겠네요.. 특히 노드마다 할당된 메모리를 해제하는 부분이 제대로 작동하는건지 궁금합니다.
/* * chk_shadow v0.1 2005/10/12 * * 아이디와 패스워드가 동일한 계정을 찾아서 보여준다. * */ #include <stdio.h> #include <pwd.h> #include <limits.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void chk_shadow(struct passwd *p); void create_list(); void add_list(char *data); void print_list(); void remove_list(); void err_print(char *err_string); struct pw { char shadow[LINE_MAX]; struct pw *next; }; struct pw *cur; /* 리스트 검색시 임시로 사용할 포인터 */ struct pw *end; /* 새로운 노드 추가시 사용할 포인터 */ struct pw *start; /* 리스트의 시작 노드를 가르키는 포인터 */ struct pw *next; /* 할당된 메모리를 해제할때 사용하는 포인터 */ int main(void) { FILE *fp; struct passwd *p; char data[LINE_MAX]; create_list(); if((fp = fopen("/etc/shadow", "r")) == NULL) err_print("/etc/shadow open failed "); while(fgets(data, LINE_MAX, fp) != NULL) add_list(data); //print_list(); while((p = getpwent()) != NULL) { chk_shadow(p); } endpwent(); fclose(fp); remove_list(); return 0; } void chk_shadow(struct passwd *p) { char *id; char *pw; char salt[13]; char entry[LINE_MAX]; cur = start->next; while(cur->next != NULL) { strcpy(entry, cur->shadow); /* strtok에서 cur->shadow를 그대로 쓰면 작동안함 */ if((id = strtok(entry, ":")) == NULL) err_print("shadow file ID entry parsing error "); if((pw = strtok(NULL, ":")) == NULL) err_print("shadow file PW entry parsing error "); if(strcmp(id, p->pw_name) != 0) { /* 찾는 아이디가 아니면 다음줄로 이동 */ cur = cur->next; continue; } else { /* md5 구현 (리눅스) */ if(pw[0] == '$') { /* !!인 경우는 pw[2], pw[11]이 잘못된 포인터라서 */ if(pw[2] == '$' && pw[11] == '$') { /* 1, 3, 12번째가 $로 나오면 MD5를 사용한 암호화 */ strncpy(salt, pw, 12); /* MD5의 경우에는 앞 12글자가 salt 값이다 */ salt[12] = '\0'; } } /* 일반 crypt 구현 (솔라리스) */ else { strncpy(salt, pw, 2); /* 일반 crypt의 경우에는 앞 2글자만 salt 값이다 */ salt[2] = '\0'; } if(strcmp(pw, crypt(p->pw_name, salt)) == 0) printf("%s (%s) account detected\n", p->pw_name, p->pw_dir); break; } } } void create_list() { start = malloc(sizeof(struct pw)); start->next = NULL; } void add_list(char *data) { end = malloc(sizeof(struct pw)); if(start->next == NULL) { strcpy(end->shadow, data); start->next = end; end->next = NULL; } else { cur = start; while(cur->next != NULL) cur = cur->next; strcpy(end->shadow, data); cur->next = end; end->next = NULL; } } void print_list() { cur = start; for(;;) { printf("%s", cur->shadow); if(cur->next == NULL) break; else cur = cur->next; } } void remove_list() { cur = start; while(cur->next != NULL) { next = cur->next; free(cur); cur = next; } } void err_print(char *err_string) { perror(err_string); exit(EXIT_FAILURE); }
그리고 컴파일시 아래와 같이 경고가 나오는데요..
a.c: In function `chk_shadow':
a.c:99: warning: implicit declaration of function `crypt'
a.c:99: warning: passing arg 2 of `strcmp' makes pointer from integer without a cast
분명히 unistd.h도 선언을 했고 crypt 함수 원형을 보면 pointer to char를 반환하는데도 불구하고 저런 경고가 뜨는게 정말 이해가 안됩니다. 뭐가 문제인지...
고수님들의 많은 조언 부탁드립니다. 감사합니다~
Forums:
crypt()에 대한 warning에 대해선,man page를 보니까
crypt()에 대한 warning에 대해선,
man page를 보니까 unistd.h include 하기 전에 뭔가 define을 해줘야 하는 것 같은데요-
remove_list()에서 마지막 노드를 빼먹는 듯 하구요-
$PWD `date`
댓글 달기