1/* 2 * $Id: messages.c,v 1.23 2009-11-24 15:44:40 didg Exp $ 3 * 4 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) 5 * All Rights Reserved. See COPYRIGHT. 6 */ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif /* HAVE_CONFIG_H */ 11 12#ifdef HAVE_UNISTD_H 13#include <unistd.h> 14#endif /* HAVE_UNISTD_H */ 15#include <stdio.h> 16#include <string.h> 17#include <errno.h> 18#include <stdlib.h> 19#include <atalk/afp.h> 20#include <atalk/dsi.h> 21#include <atalk/util.h> 22#include <atalk/logger.h> 23#include <atalk/globals.h> 24 25#include "misc.h" 26 27 28#define MAXMESGSIZE 199 29 30/* this is only used by afpd children, so it's okay. */ 31static char servermesg[MAXPATHLEN] = ""; 32static char localized_message[MAXPATHLEN] = ""; 33 34void setmessage(const char *message) 35{ 36 strlcpy(servermesg, message, MAXMESGSIZE); 37} 38 39void readmessage(AFPObj *obj) 40{ 41 /* Read server message from file defined as SERVERTEXT */ 42#ifdef SERVERTEXT 43 FILE *message; 44 char * filename; 45 unsigned int i; 46 int rc; 47 static int c; 48 uid_t euid; 49 u_int32_t maxmsgsize; 50 51 maxmsgsize = (obj->proto == AFPPROTO_DSI)?MIN(MAX(((DSI*)obj->handle)->attn_quantum, MAXMESGSIZE),MAXPATHLEN):MAXMESGSIZE; 52 53 i=0; 54 /* Construct file name SERVERTEXT/message.[pid] */ 55 if ( NULL == (filename=(char*) malloc(sizeof(SERVERTEXT)+15)) ) { 56 LOG(log_error, logtype_afpd, "readmessage: malloc: %s", strerror(errno) ); 57 return; 58 } 59 60 sprintf(filename, "%s/message.%d", SERVERTEXT, getpid()); 61 62#ifdef DEBUG 63 LOG(log_debug9, logtype_afpd, "Reading file %s ", filename); 64#endif 65 66 message=fopen(filename, "r"); 67 if (message==NULL) { 68 /* try without the process id */ 69 sprintf(filename, "%s/message", SERVERTEXT); 70 message=fopen(filename, "r"); 71 } 72 73 /* if either message.pid or message exists */ 74 if (message!=NULL) { 75 /* added while loop to get characters and put in servermesg */ 76 while ((( c=fgetc(message)) != EOF) && (i < (maxmsgsize - 1))) { 77 if ( c == '\n') c = ' '; 78 servermesg[i++] = c; 79 } 80 servermesg[i] = 0; 81 82 /* cleanup */ 83 fclose(message); 84 85 /* Save effective uid and switch to root to delete file. */ 86 /* Delete will probably fail otherwise, but let's try anyways */ 87 euid = geteuid(); 88 if (seteuid(0) < 0) { 89 LOG(log_error, logtype_afpd, "Could not switch back to root: %s", 90 strerror(errno)); 91 } 92 93 if ((rc = unlink(filename)) != 0) 94 LOG(log_error, logtype_afpd, "File '%s' could not be deleted", strerror(errno)); 95 96 /* Drop privs again, failing this is very bad */ 97 if (seteuid(euid) < 0) { 98 LOG(log_error, logtype_afpd, "Could not switch back to uid %d: %s", euid, strerror(errno)); 99 exit(EXITERR_SYS); 100 } 101 102 if (rc < 0) { 103 LOG(log_error, logtype_afpd, "Error deleting %s: %s", filename, strerror(rc)); 104 } 105#ifdef DEBUG 106 else { 107 LOG(log_debug9, logtype_afpd, "Deleted %s", filename); 108 } 109 110 LOG(log_debug9, logtype_afpd, "Set server message to \"%s\"", servermesg); 111#endif 112 } 113 free(filename); 114#endif /* SERVERTEXT */ 115} 116 117int afp_getsrvrmesg(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) 118{ 119 char *message; 120 u_int16_t type, bitmap; 121 u_int16_t msgsize; 122 size_t outlen = 0; 123 size_t msglen = 0; 124 int utf8 = 0; 125 126 *rbuflen = 0; 127 128 msgsize = (obj->proto == AFPPROTO_DSI)?MAX(((DSI*)obj->handle)->attn_quantum, MAXMESGSIZE):MAXMESGSIZE; 129 130 memcpy(&type, ibuf + 2, sizeof(type)); 131 memcpy(&bitmap, ibuf + 4, sizeof(bitmap)); 132 133 message = servermesg; 134 switch (ntohs(type)) { 135 case AFPMESG_LOGIN: /* login */ 136 /* at least TIGER loses server messages 137 * if it receives a server msg attention before 138 * it has asked the login msg... 139 * Workaround: concatenate the two if any, ugly. 140 */ 141 if (*message && *obj->options.loginmesg) { 142 strlcat(message, " - ", MAXMESGSIZE); 143 } 144 strlcat(message, obj->options.loginmesg, MAXMESGSIZE); 145 break; 146 case AFPMESG_SERVER: /* server */ 147 break; 148 default: 149 return AFPERR_BITMAP; 150 } 151 152 /* output format: 153 * message type: 2 bytes 154 * bitmap: 2 bytes 155 * message length: 1 byte ( 2 bytes for utf8) 156 * message: up to 199 bytes (dsi attn_quantum for utf8) 157 */ 158 memcpy(rbuf, &type, sizeof(type)); 159 rbuf += sizeof(type); 160 *rbuflen += sizeof(type); 161 memcpy(rbuf, &bitmap, sizeof(bitmap)); 162 rbuf += sizeof(bitmap); 163 *rbuflen += sizeof(bitmap); 164 165 utf8 = ntohs(bitmap) & 2; 166 msglen = strlen(message); 167 if (msglen > msgsize) 168 msglen = msgsize; 169 170 if (msglen) { 171 if ( (size_t)-1 == (outlen = convert_string(obj->options.unixcharset, utf8?CH_UTF8_MAC:obj->options.maccharset, 172 message, msglen, localized_message, msgsize)) ) 173 { 174 memcpy(rbuf+((utf8)?2:1), message, msglen); /*FIXME*/ 175 outlen = msglen; 176 } 177 else 178 { 179 memcpy(rbuf+((utf8)?2:1), localized_message, outlen); 180 } 181 } 182 183 if ( utf8 ) { 184 /* UTF8 message, 2 byte length */ 185 msgsize = htons(outlen); 186 memcpy(rbuf, &msgsize, sizeof(msgsize)); 187 *rbuflen += sizeof(msgsize); 188 } 189 else { 190 *rbuf = outlen; 191 *rbuflen += 1; 192 } 193 *rbuflen += outlen; 194 *message = 0; 195 return AFP_OK; 196} 197