X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fmessages.c;h=5bd965bd2a55fd569942f550173b80a44e27c1a5;hb=HEAD;hp=f371d959ad60078dd2fb189aa423a460963fc083;hpb=73eced85d8e37bac86d2c424d52bd27c245b26cc;p=netatalk.git diff --git a/etc/afpd/messages.c b/etc/afpd/messages.c index f371d959..5bd965bd 100644 --- a/etc/afpd/messages.c +++ b/etc/afpd/messages.c @@ -1,6 +1,4 @@ /* - * $Id: messages.c,v 1.12 2002-01-03 17:29:10 sibaz Exp $ - * * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. */ @@ -9,48 +7,69 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#include #include #include +#include +#include #include -#include -#ifdef HAVE_UNISTD_H -#include -#endif /* HAVE_UNISTD_H */ -#include "globals.h" +#include +#include +#include +#include +#include + #include "misc.h" #define MAXMESGSIZE 199 /* this is only used by afpd children, so it's okay. */ -static char servermesg[MAXMESGSIZE] = ""; - -void setmessage(const char *message) +static char servermesg[MAXPATHLEN] = ""; +static char localized_message[MAXPATHLEN] = ""; + +/*! + * Copy AFP message to message buffer + * @param message (r) message to send + * @returns 0 if this message is being set the first time, return 1 if the preceeding + * message was the same + */ +int setmessage(const char *message) { - strncpy(servermesg, message, MAXMESGSIZE); + if (strncmp(message, servermesg, MAXMESGSIZE) == 0) + return 1; + strlcpy(servermesg, message, MAXMESGSIZE); + return 0; } -void readmessage(void) +void readmessage(AFPObj *obj) { /* Read server message from file defined as SERVERTEXT */ #ifdef SERVERTEXT FILE *message; char * filename; - int i, rc; + unsigned int i; + int rc; static int c; - uid_t euid; + uint32_t maxmsgsize; + + maxmsgsize = MIN(MAX(obj->dsi->attn_quantum, MAXMESGSIZE), MAXPATHLEN); i=0; /* Construct file name SERVERTEXT/message.[pid] */ - filename=malloc(sizeof(SERVERTEXT)+15); + if ( NULL == (filename=(char*) malloc(sizeof(SERVERTEXT)+15)) ) { + LOG(log_error, logtype_afpd, "readmessage: malloc: %s", strerror(errno) ); + return; + } + sprintf(filename, "%s/message.%d", SERVERTEXT, getpid()); #ifdef DEBUG - syslog(LOG_DEBUG, "Reading file %s ", filename); -#endif /* DEBUG */ + LOG(log_debug9, logtype_afpd, "Reading file %s ", filename); +#endif message=fopen(filename, "r"); if (message==NULL) { - syslog(LOG_INFO, "Unable to open file %s", filename); + /* try without the process id */ sprintf(filename, "%s/message", SERVERTEXT); message=fopen(filename, "r"); } @@ -58,7 +77,7 @@ void readmessage(void) /* if either message.pid or message exists */ if (message!=NULL) { /* added while loop to get characters and put in servermesg */ - while ((( c=fgetc(message)) != EOF) && (i < (MAXMESGSIZE - 1))) { + while ((( c=fgetc(message)) != EOF) && (i < (maxmsgsize - 1))) { if ( c == '\n') c = ' '; servermesg[i++] = c; } @@ -67,75 +86,106 @@ void readmessage(void) /* cleanup */ fclose(message); - /* Save effective uid and switch to root to delete file. */ - /* Delete will probably fail otherwise, but let's try anyways */ - euid = geteuid(); - if (seteuid(0) < 0) { - syslog(LOG_ERR, "Could not switch back to root: %m"); - } + become_root(); - rc = unlink(filename); + if ((rc = unlink(filename)) != 0) + LOG(log_error, logtype_afpd, "File '%s' could not be deleted", strerror(errno)); - /* Drop privs again, failing this is very bad */ - if (seteuid(euid) < 0) { - syslog(LOG_ERR, "Could not switch back to uid %d: %m", euid); - } + unbecome_root(); if (rc < 0) { - syslog(LOG_ERR, "Error deleting %s: %m", filename); + LOG(log_error, logtype_afpd, "Error deleting %s: %s", filename, strerror(rc)); } #ifdef DEBUG else { - syslog(LOG_INFO, "Deleted %s", filename); + LOG(log_debug9, logtype_afpd, "Deleted %s", filename); } - syslog(LOG_INFO, "Set server message to \"%s\"", servermesg); -#endif /* DEBUG */ + LOG(log_debug9, logtype_afpd, "Set server message to \"%s\"", servermesg); +#endif } free(filename); #endif /* SERVERTEXT */ } -int afp_getsrvrmesg(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_getsrvrmesg(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { char *message; - u_int16_t type, bitmap; + uint16_t type, bitmap; + uint16_t msgsize; + size_t outlen = 0; + size_t msglen = 0; + int utf8 = 0; + + *rbuflen = 0; + + msgsize = MAX(obj->dsi->attn_quantum, MAXMESGSIZE); memcpy(&type, ibuf + 2, sizeof(type)); memcpy(&bitmap, ibuf + 4, sizeof(bitmap)); + message = servermesg; switch (ntohs(type)) { case AFPMESG_LOGIN: /* login */ - message = obj->options.loginmesg; + /* at least TIGER loses server messages + * if it receives a server msg attention before + * it has asked the login msg... + * Workaround: concatenate the two if any, ugly. + */ + if (obj->options.loginmesg) { + if (*message) + strlcat(message, " - ", MAXMESGSIZE); + strlcat(message, obj->options.loginmesg, MAXMESGSIZE); + } break; case AFPMESG_SERVER: /* server */ - message = servermesg; break; default: - *rbuflen = 0; return AFPERR_BITMAP; } /* output format: * message type: 2 bytes * bitmap: 2 bytes - * message length: 1 byte - * message: up to 199 bytes + * message length: 1 byte ( 2 bytes for utf8) + * message: up to 199 bytes (dsi attn_quantum for utf8) */ memcpy(rbuf, &type, sizeof(type)); rbuf += sizeof(type); + *rbuflen += sizeof(type); memcpy(rbuf, &bitmap, sizeof(bitmap)); rbuf += sizeof(bitmap); - *rbuflen = strlen(message); - if (*rbuflen > MAXMESGSIZE) - *rbuflen = MAXMESGSIZE; - *rbuf++ = *rbuflen; - memcpy(rbuf, message, *rbuflen); - - *rbuflen += 5; - + *rbuflen += sizeof(bitmap); + + utf8 = ntohs(bitmap) & 2; + msglen = strlen(message); + if (msglen > msgsize) + msglen = msgsize; + + if (msglen) { + if ( (size_t)-1 == (outlen = convert_string(obj->options.unixcharset, utf8?CH_UTF8_MAC:obj->options.maccharset, + message, msglen, localized_message, msgsize)) ) + { + memcpy(rbuf+((utf8)?2:1), message, msglen); /*FIXME*/ + outlen = msglen; + } + else + { + memcpy(rbuf+((utf8)?2:1), localized_message, outlen); + } + } + + if ( utf8 ) { + /* UTF8 message, 2 byte length */ + msgsize = htons(outlen); + memcpy(rbuf, &msgsize, sizeof(msgsize)); + *rbuflen += sizeof(msgsize); + } + else { + *rbuf = outlen; + *rbuflen += 1; + } + *rbuflen += outlen; +// *message = 0; return AFP_OK; }