diff --git a/lewdfingerd.c b/lewdfingerd.c index 8296634..ae7a55c 100644 --- a/lewdfingerd.c +++ b/lewdfingerd.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -141,8 +142,20 @@ ssize_t writeall_str(int fd, const char *s) { return writeall(fd, s, strlen(s)); } -void handle_userlist(int sock) { +bool handle_finger_response(int sock, const char *finger_response_file) { + (void)finger_response_file; + // TODO: Handle .finger-response + if(writeall_str(sock, "Lewd.\r\n") < 0) { + log_perror("writeall_str (lewd)"); + return false; + } + + return true; +} + +void handle_userlist(int sock, bool force_multiline) { // Go over users' home dirs and see if .finger-response is present + bool first_line = true; for(;;) { errno = 0; struct passwd *passwd_entry = getpwent(); @@ -160,18 +173,44 @@ void handle_userlist(int sock) { char *finger_response_file; if(asprintf(&finger_response_file, "%s/.finger-response", passwd_entry->pw_dir) < 0) { log_perror("asprintf"); + endpwent(); return; } if(access(finger_response_file, F_OK) == 0) { + if(force_multiline && !first_line) { + if(writeall_str(sock, "\r\n") < 0) { + log_perror("writeall_str (separating newline)"); + endpwent(); + return; + } + } + if(writeall_str(sock, passwd_entry->pw_name) < 0) { - log_perror("writeall_str"); + log_perror("writeall_str (username)"); + endpwent(); return; } - if(writeall_str(sock, "\r\n") < 0) { - log_perror("writeall_str"); + + const char *suffix = "\r\n"; + if(force_multiline) { + suffix = ":\r\n"; + } + + if(writeall_str(sock, suffix) < 0) { + log_perror("writeall_str (suffix)"); + endpwent(); return; } + + if(force_multiline) { + if(handle_finger_response(sock, finger_response_file) == false) { + endpwent(); + return; + } + } + + first_line = false; } } } @@ -199,15 +238,11 @@ void handle_query(int sock, const char *username) { if(access(finger_response_file, F_OK) != 0) { if(writeall_str(sock, "Can't finger\r\n") < 0) { - log_perror("writeall_str"); + log_perror("writeall_str (not found error)"); return; } } else { - const char *response = "Lewd.\r\n"; - if(writeall(sock, response, strlen(response)) < 0) { - log_perror("write"); - } - + handle_finger_response(sock, finger_response_file); } } @@ -247,14 +282,31 @@ void handle_connection(int sock) { } } + char *request_buffer = request; request[request_size-2] = '\0'; + // See if the multi-line format was requested + bool force_multiline = false; + if(request[0] == '/' && request[1] == 'W') { + if(request[2] == '\0') { + // Just "/W" + force_multiline = true; + request = &request[2]; + } else if(request[2] == ' ') { + // "/W " as prefix + force_multiline = true; + request = &request[3]; + } + } + if(!strcmp(request, "")) { - handle_userlist(sock); + handle_userlist(sock, force_multiline); } else { handle_query(sock, request); } + free(request_buffer); + shutdown(sock, SHUT_RDWR); close(sock); }