imapext-2007
diff src/osdep/nt/yunchan.c @ 0:ada5e610ab86
imap-2007e
author | yuuji@gentei.org |
---|---|
date | Mon, 14 Sep 2009 15:17:45 +0900 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/osdep/nt/yunchan.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,286 @@ 1.4 +/* ======================================================================== 1.5 + * Copyright 1988-2006 University of Washington 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * 1.14 + * ======================================================================== 1.15 + */ 1.16 + 1.17 +/* 1.18 + * Program: Unix compatibility routines 1.19 + * 1.20 + * Author: Mark Crispin 1.21 + * Networks and Distributed Computing 1.22 + * Computing & Communications 1.23 + * University of Washington 1.24 + * Administration Building, AG-44 1.25 + * Seattle, WA 98195 1.26 + * Internet: MRC@CAC.Washington.EDU 1.27 + * 1.28 + * Date: 14 September 1996 1.29 + * Last Edited: 30 August 2006 1.30 + */ 1.31 + 1.32 + 1.33 +/* DEDICATION 1.34 + * 1.35 + * This file is dedicated to my dog, Unix, also known as Yun-chan and 1.36 + * Unix J. Terwilliker Jehosophat Aloysius Monstrosity Animal Beast. Unix 1.37 + * passed away at the age of 11 1/2 on September 14, 1996, 12:18 PM PDT, after 1.38 + * a two-month bout with cirrhosis of the liver. 1.39 + * 1.40 + * He was a dear friend, and I miss him terribly. 1.41 + * 1.42 + * Lift a leg, Yunie. Luv ya forever!!!! 1.43 + */ 1.44 + 1.45 +/* Emulator for BSD flock() call 1.46 + * Accepts: file descriptor 1.47 + * operation bitmask 1.48 + * Returns: 0 if successful, -1 if failure 1.49 + */ 1.50 + 1.51 +/* Our friends in Redmond have decided that you can not write to any segment 1.52 + * which has a shared lock. This screws up the shared-write mailbox drivers 1.53 + * (mbx, mtx, and tenex). As a workaround, we'll only lock the first byte of 1.54 + * the file, meaning that you can't write that byte shared. 1.55 + * This behavior seems to be new as of NT 4.0. 1.56 + */ 1.57 + 1.58 +int flock (int fd,int op) 1.59 +{ 1.60 + HANDLE hdl = (HANDLE) _get_osfhandle (fd); 1.61 + DWORD flags = (op & LOCK_NB) ? LOCKFILE_FAIL_IMMEDIATELY : 0; 1.62 + OVERLAPPED offset = {NIL,NIL,0,0,NIL}; 1.63 + int ret = -1; 1.64 + blocknotify_t bn = (blocknotify_t) 1.65 + ((op & LOCK_NB) ? NIL : mail_parameters (NIL,GET_BLOCKNOTIFY,NIL)); 1.66 + if (hdl < 0) errno = EBADF; /* error in file descriptor */ 1.67 + else switch (op & ~LOCK_NB) { /* translate to LockFileEx() op */ 1.68 + case LOCK_EX: /* exclusive */ 1.69 + flags |= LOCKFILE_EXCLUSIVE_LOCK; 1.70 + case LOCK_SH: /* shared */ 1.71 + if (!check_nt ()) return 0; /* always succeeds if not NT */ 1.72 + if (bn) (*bn) (BLOCK_FILELOCK,NIL); 1.73 + /* bug for bug compatible with Unix */ 1.74 + UnlockFileEx (hdl,NIL,1,0,&offset); 1.75 + /* lock the file as requested */ 1.76 + if (LockFileEx (hdl,flags,NIL,1,0,&offset)) ret = 0; 1.77 + if (bn) (*bn) (BLOCK_NONE,NIL); 1.78 + /* if failed */ 1.79 + if (ret) errno = (op & LOCK_NB) ? EAGAIN : EBADF; 1.80 + break; 1.81 + case LOCK_UN: /* unlock */ 1.82 + if (check_nt ()) UnlockFileEx (hdl,NIL,1,0,&offset); 1.83 + ret = 0; /* always succeeds */ 1.84 + default: /* default */ 1.85 + errno = EINVAL; /* bad call */ 1.86 + break; 1.87 + } 1.88 + return ret; 1.89 +} 1.90 + 1.91 +/* Local storage */ 1.92 + 1.93 +static char *loghdr; /* log file header string */ 1.94 +static HANDLE loghdl = NIL; /* handle of event source */ 1.95 + 1.96 +/* Emulator for BSD syslog() routine 1.97 + * Accepts: priority 1.98 + * message 1.99 + * parameters 1.100 + */ 1.101 + 1.102 +void syslog (int priority,const char *message,...) 1.103 +{ 1.104 + va_list args; 1.105 + LPTSTR strs[2]; 1.106 + char tmp[MAILTMPLEN]; /* callers must be careful not to pop this */ 1.107 + unsigned short etype; 1.108 + if (!check_nt ()) return; /* no-op on non-NT system */ 1.109 + /* default event source */ 1.110 + if (!loghdl) openlog ("c-client",LOG_PID,LOG_MAIL); 1.111 + switch (priority) { /* translate UNIX type into NT type */ 1.112 + case LOG_ALERT: 1.113 + etype = EVENTLOG_ERROR_TYPE; 1.114 + break; 1.115 + case LOG_INFO: 1.116 + etype = EVENTLOG_INFORMATION_TYPE; 1.117 + break; 1.118 + default: 1.119 + etype = EVENTLOG_WARNING_TYPE; 1.120 + } 1.121 + va_start (args,message); /* initialize vararg mechanism */ 1.122 + vsprintf (tmp,message,args); /* build message */ 1.123 + strs[0] = loghdr; /* write header */ 1.124 + strs[1] = tmp; /* then the message */ 1.125 + /* report the event */ 1.126 + ReportEvent (loghdl,etype,(unsigned short) priority,2000,NIL,2,0,strs,NIL); 1.127 + va_end (args); 1.128 +} 1.129 + 1.130 + 1.131 +/* Emulator for BSD openlog() routine 1.132 + * Accepts: identity 1.133 + * options 1.134 + * facility 1.135 + */ 1.136 + 1.137 +void openlog (const char *ident,int logopt,int facility) 1.138 +{ 1.139 + char tmp[MAILTMPLEN]; 1.140 + if (!check_nt ()) return; /* no-op on non-NT system */ 1.141 + if (loghdl) fatal ("Duplicate openlog()!"); 1.142 + loghdl = RegisterEventSource (NIL,ident); 1.143 + sprintf (tmp,(logopt & LOG_PID) ? "%s[%d]" : "%s",ident,getpid ()); 1.144 + loghdr = cpystr (tmp); /* save header for later */ 1.145 +} 1.146 + 1.147 +/* Copy Unix string with CRLF newlines 1.148 + * Accepts: destination string 1.149 + * pointer to size of destination string buffer 1.150 + * source string 1.151 + * length of source string 1.152 + * Returns: length of copied string 1.153 + */ 1.154 + 1.155 +unsigned long unix_crlfcpy (char **dst,unsigned long *dstl,char *src, 1.156 + unsigned long srcl) 1.157 +{ 1.158 + unsigned long i,j; 1.159 + char *d = src; 1.160 + /* count number of LF's in source string(s) */ 1.161 + for (i = srcl,j = 0; j < srcl; j++) if (*d++ == '\012') i++; 1.162 + /* flush destination buffer if too small */ 1.163 + if (*dst && (i > *dstl)) fs_give ((void **) dst); 1.164 + if (!*dst) { /* make a new buffer if needed */ 1.165 + *dst = (char *) fs_get ((*dstl = i) + 1); 1.166 + if (dstl) *dstl = i; /* return new buffer length to main program */ 1.167 + } 1.168 + d = *dst; /* destination string */ 1.169 + /* copy strings, inserting CR's before LF's */ 1.170 + while (srcl--) switch (*src) { 1.171 + case '\015': /* unlikely carriage return */ 1.172 + *d++ = *src++; /* copy it and any succeeding linefeed */ 1.173 + if (srcl && *src == '\012') { 1.174 + *d++ = *src++; 1.175 + srcl--; 1.176 + } 1.177 + break; 1.178 + case '\012': /* line feed? */ 1.179 + *d++ ='\015'; /* yes, prepend a CR, drop into default case */ 1.180 + default: /* ordinary chararacter */ 1.181 + *d++ = *src++; /* just copy character */ 1.182 + break; 1.183 + } 1.184 + *d = '\0'; /* tie off destination */ 1.185 + return d - *dst; /* return length */ 1.186 +} 1.187 + 1.188 +/* Length of Unix string after unix_crlfcpy applied 1.189 + * Accepts: source string 1.190 + * Returns: length of string 1.191 + */ 1.192 + 1.193 +unsigned long unix_crlflen (STRING *s) 1.194 +{ 1.195 + unsigned long pos = GETPOS (s); 1.196 + unsigned long i = SIZE (s); 1.197 + unsigned long j = i; 1.198 + while (j--) switch (SNX (s)) {/* search for newlines */ 1.199 + case '\015': /* unlikely carriage return */ 1.200 + if (j && (CHR (s) == '\012')) { 1.201 + SNX (s); /* eat the line feed */ 1.202 + j--; 1.203 + } 1.204 + break; 1.205 + case '\012': /* line feed? */ 1.206 + i++; 1.207 + default: /* ordinary chararacter */ 1.208 + break; 1.209 + } 1.210 + SETPOS (s,pos); /* restore old position */ 1.211 + return i; 1.212 +} 1.213 + 1.214 +/* Undoubtably, I'm going to regret these two routines in the future. I 1.215 + * regret them now. Their purpose is to work around two problems in the 1.216 + * VC++ 6.0 C library: 1.217 + * (1) tmpfile() creates the file in the current directory instead of a 1.218 + * temporary directory 1.219 + * (2) tmpfile() and fclose() think that on NT systems, it works to unlink 1.220 + * the file while it's still open, so there's no need for the _tmpfname 1.221 + * hook at fclose(). Unfortunately, that doesn't work in Win2K. 1.222 + * I would be delighted to have a better alternative. 1.223 + */ 1.224 + 1.225 +#undef fclose /* use the real fclose() in close_file() */ 1.226 + 1.227 +/* Substitute for Microsoft's tmpfile() that uses the real temporary directory 1.228 + * Returns: FILE structure if success, NIL if failure 1.229 + */ 1.230 + 1.231 +FILE *create_tempfile (void) 1.232 +{ 1.233 + FILE *ret = NIL; 1.234 + char *s = _tempnam (getenv ("TEMP"),"msg"); 1.235 + if (s) { /* if got temporary name... */ 1.236 + /* open file, and stash name on _tmpfname */ 1.237 + if (ret = fopen (s,"w+b")) ret->_tmpfname = s; 1.238 + else fs_give ((void **) &s);/* flush temporary string */ 1.239 + } 1.240 + return ret; 1.241 +} 1.242 + 1.243 + 1.244 +/* Substitute for Microsoft's fclose() that always flushes _tmpfname 1.245 + * Returns: FILE structure if success, NIL if failure 1.246 + */ 1.247 + 1.248 +int close_file (FILE *stream) 1.249 +{ 1.250 + int ret; 1.251 + char *s = stream->_tmpfname; 1.252 + stream->_tmpfname = NIL; /* just in case fclose() tries to delete it */ 1.253 + ret = fclose (stream); /* close the file */ 1.254 + if (s) { /* was there a _tmpfname? */ 1.255 + unlink (s); /* yup, delete it */ 1.256 + fs_give ((void **) &s); /* and flush the name */ 1.257 + } 1.258 + return ret; 1.259 +} 1.260 + 1.261 +/* Get password from console 1.262 + * Accepts: prompt 1.263 + * Returns: password 1.264 + */ 1.265 + 1.266 +#define PWDLEN 128 /* used by Linux */ 1.267 + 1.268 +char *getpass (const char *prompt) 1.269 +{ 1.270 + static char pwd[PWDLEN]; 1.271 + int ch,i,done; 1.272 + fputs (prompt,stderr); /* output prompt */ 1.273 + for (i = done = 0; !done; ) switch (ch = _getch()) { 1.274 + case 0x03: /* CTRL/C stops program */ 1.275 + _exit (1); 1.276 + case '\b': /* BACKSPACE erase previous character */ 1.277 + if (i) pwd[--i] = '\0'; 1.278 + break; 1.279 + case '\n': case '\r': /* CR or LF terminates string */ 1.280 + done = 1; 1.281 + break; 1.282 + default: /* any other character is a pwd char */ 1.283 + if (i < (PWDLEN - 1)) pwd[i++] = ch; 1.284 + break; 1.285 + } 1.286 + pwd[i] = '\0'; /* tie off string with null */ 1.287 + putchar ('\n'); /* echo newline */ 1.288 + return pwd; 1.289 +}