imapext-2007

annotate src/osdep/nt/yunchan.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
rev   line source
yuuji@0 1 /* ========================================================================
yuuji@0 2 * Copyright 1988-2006 University of Washington
yuuji@0 3 *
yuuji@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
yuuji@0 5 * you may not use this file except in compliance with the License.
yuuji@0 6 * You may obtain a copy of the License at
yuuji@0 7 *
yuuji@0 8 * http://www.apache.org/licenses/LICENSE-2.0
yuuji@0 9 *
yuuji@0 10 *
yuuji@0 11 * ========================================================================
yuuji@0 12 */
yuuji@0 13
yuuji@0 14 /*
yuuji@0 15 * Program: Unix compatibility routines
yuuji@0 16 *
yuuji@0 17 * Author: Mark Crispin
yuuji@0 18 * Networks and Distributed Computing
yuuji@0 19 * Computing & Communications
yuuji@0 20 * University of Washington
yuuji@0 21 * Administration Building, AG-44
yuuji@0 22 * Seattle, WA 98195
yuuji@0 23 * Internet: MRC@CAC.Washington.EDU
yuuji@0 24 *
yuuji@0 25 * Date: 14 September 1996
yuuji@0 26 * Last Edited: 30 August 2006
yuuji@0 27 */
yuuji@0 28
yuuji@0 29
yuuji@0 30 /* DEDICATION
yuuji@0 31 *
yuuji@0 32 * This file is dedicated to my dog, Unix, also known as Yun-chan and
yuuji@0 33 * Unix J. Terwilliker Jehosophat Aloysius Monstrosity Animal Beast. Unix
yuuji@0 34 * passed away at the age of 11 1/2 on September 14, 1996, 12:18 PM PDT, after
yuuji@0 35 * a two-month bout with cirrhosis of the liver.
yuuji@0 36 *
yuuji@0 37 * He was a dear friend, and I miss him terribly.
yuuji@0 38 *
yuuji@0 39 * Lift a leg, Yunie. Luv ya forever!!!!
yuuji@0 40 */
yuuji@0 41
yuuji@0 42 /* Emulator for BSD flock() call
yuuji@0 43 * Accepts: file descriptor
yuuji@0 44 * operation bitmask
yuuji@0 45 * Returns: 0 if successful, -1 if failure
yuuji@0 46 */
yuuji@0 47
yuuji@0 48 /* Our friends in Redmond have decided that you can not write to any segment
yuuji@0 49 * which has a shared lock. This screws up the shared-write mailbox drivers
yuuji@0 50 * (mbx, mtx, and tenex). As a workaround, we'll only lock the first byte of
yuuji@0 51 * the file, meaning that you can't write that byte shared.
yuuji@0 52 * This behavior seems to be new as of NT 4.0.
yuuji@0 53 */
yuuji@0 54
yuuji@0 55 int flock (int fd,int op)
yuuji@0 56 {
yuuji@0 57 HANDLE hdl = (HANDLE) _get_osfhandle (fd);
yuuji@0 58 DWORD flags = (op & LOCK_NB) ? LOCKFILE_FAIL_IMMEDIATELY : 0;
yuuji@0 59 OVERLAPPED offset = {NIL,NIL,0,0,NIL};
yuuji@0 60 int ret = -1;
yuuji@0 61 blocknotify_t bn = (blocknotify_t)
yuuji@0 62 ((op & LOCK_NB) ? NIL : mail_parameters (NIL,GET_BLOCKNOTIFY,NIL));
yuuji@0 63 if (hdl < 0) errno = EBADF; /* error in file descriptor */
yuuji@0 64 else switch (op & ~LOCK_NB) { /* translate to LockFileEx() op */
yuuji@0 65 case LOCK_EX: /* exclusive */
yuuji@0 66 flags |= LOCKFILE_EXCLUSIVE_LOCK;
yuuji@0 67 case LOCK_SH: /* shared */
yuuji@0 68 if (!check_nt ()) return 0; /* always succeeds if not NT */
yuuji@0 69 if (bn) (*bn) (BLOCK_FILELOCK,NIL);
yuuji@0 70 /* bug for bug compatible with Unix */
yuuji@0 71 UnlockFileEx (hdl,NIL,1,0,&offset);
yuuji@0 72 /* lock the file as requested */
yuuji@0 73 if (LockFileEx (hdl,flags,NIL,1,0,&offset)) ret = 0;
yuuji@0 74 if (bn) (*bn) (BLOCK_NONE,NIL);
yuuji@0 75 /* if failed */
yuuji@0 76 if (ret) errno = (op & LOCK_NB) ? EAGAIN : EBADF;
yuuji@0 77 break;
yuuji@0 78 case LOCK_UN: /* unlock */
yuuji@0 79 if (check_nt ()) UnlockFileEx (hdl,NIL,1,0,&offset);
yuuji@0 80 ret = 0; /* always succeeds */
yuuji@0 81 default: /* default */
yuuji@0 82 errno = EINVAL; /* bad call */
yuuji@0 83 break;
yuuji@0 84 }
yuuji@0 85 return ret;
yuuji@0 86 }
yuuji@0 87
yuuji@0 88 /* Local storage */
yuuji@0 89
yuuji@0 90 static char *loghdr; /* log file header string */
yuuji@0 91 static HANDLE loghdl = NIL; /* handle of event source */
yuuji@0 92
yuuji@0 93 /* Emulator for BSD syslog() routine
yuuji@0 94 * Accepts: priority
yuuji@0 95 * message
yuuji@0 96 * parameters
yuuji@0 97 */
yuuji@0 98
yuuji@0 99 void syslog (int priority,const char *message,...)
yuuji@0 100 {
yuuji@0 101 va_list args;
yuuji@0 102 LPTSTR strs[2];
yuuji@0 103 char tmp[MAILTMPLEN]; /* callers must be careful not to pop this */
yuuji@0 104 unsigned short etype;
yuuji@0 105 if (!check_nt ()) return; /* no-op on non-NT system */
yuuji@0 106 /* default event source */
yuuji@0 107 if (!loghdl) openlog ("c-client",LOG_PID,LOG_MAIL);
yuuji@0 108 switch (priority) { /* translate UNIX type into NT type */
yuuji@0 109 case LOG_ALERT:
yuuji@0 110 etype = EVENTLOG_ERROR_TYPE;
yuuji@0 111 break;
yuuji@0 112 case LOG_INFO:
yuuji@0 113 etype = EVENTLOG_INFORMATION_TYPE;
yuuji@0 114 break;
yuuji@0 115 default:
yuuji@0 116 etype = EVENTLOG_WARNING_TYPE;
yuuji@0 117 }
yuuji@0 118 va_start (args,message); /* initialize vararg mechanism */
yuuji@0 119 vsprintf (tmp,message,args); /* build message */
yuuji@0 120 strs[0] = loghdr; /* write header */
yuuji@0 121 strs[1] = tmp; /* then the message */
yuuji@0 122 /* report the event */
yuuji@0 123 ReportEvent (loghdl,etype,(unsigned short) priority,2000,NIL,2,0,strs,NIL);
yuuji@0 124 va_end (args);
yuuji@0 125 }
yuuji@0 126
yuuji@0 127
yuuji@0 128 /* Emulator for BSD openlog() routine
yuuji@0 129 * Accepts: identity
yuuji@0 130 * options
yuuji@0 131 * facility
yuuji@0 132 */
yuuji@0 133
yuuji@0 134 void openlog (const char *ident,int logopt,int facility)
yuuji@0 135 {
yuuji@0 136 char tmp[MAILTMPLEN];
yuuji@0 137 if (!check_nt ()) return; /* no-op on non-NT system */
yuuji@0 138 if (loghdl) fatal ("Duplicate openlog()!");
yuuji@0 139 loghdl = RegisterEventSource (NIL,ident);
yuuji@0 140 sprintf (tmp,(logopt & LOG_PID) ? "%s[%d]" : "%s",ident,getpid ());
yuuji@0 141 loghdr = cpystr (tmp); /* save header for later */
yuuji@0 142 }
yuuji@0 143
yuuji@0 144 /* Copy Unix string with CRLF newlines
yuuji@0 145 * Accepts: destination string
yuuji@0 146 * pointer to size of destination string buffer
yuuji@0 147 * source string
yuuji@0 148 * length of source string
yuuji@0 149 * Returns: length of copied string
yuuji@0 150 */
yuuji@0 151
yuuji@0 152 unsigned long unix_crlfcpy (char **dst,unsigned long *dstl,char *src,
yuuji@0 153 unsigned long srcl)
yuuji@0 154 {
yuuji@0 155 unsigned long i,j;
yuuji@0 156 char *d = src;
yuuji@0 157 /* count number of LF's in source string(s) */
yuuji@0 158 for (i = srcl,j = 0; j < srcl; j++) if (*d++ == '\012') i++;
yuuji@0 159 /* flush destination buffer if too small */
yuuji@0 160 if (*dst && (i > *dstl)) fs_give ((void **) dst);
yuuji@0 161 if (!*dst) { /* make a new buffer if needed */
yuuji@0 162 *dst = (char *) fs_get ((*dstl = i) + 1);
yuuji@0 163 if (dstl) *dstl = i; /* return new buffer length to main program */
yuuji@0 164 }
yuuji@0 165 d = *dst; /* destination string */
yuuji@0 166 /* copy strings, inserting CR's before LF's */
yuuji@0 167 while (srcl--) switch (*src) {
yuuji@0 168 case '\015': /* unlikely carriage return */
yuuji@0 169 *d++ = *src++; /* copy it and any succeeding linefeed */
yuuji@0 170 if (srcl && *src == '\012') {
yuuji@0 171 *d++ = *src++;
yuuji@0 172 srcl--;
yuuji@0 173 }
yuuji@0 174 break;
yuuji@0 175 case '\012': /* line feed? */
yuuji@0 176 *d++ ='\015'; /* yes, prepend a CR, drop into default case */
yuuji@0 177 default: /* ordinary chararacter */
yuuji@0 178 *d++ = *src++; /* just copy character */
yuuji@0 179 break;
yuuji@0 180 }
yuuji@0 181 *d = '\0'; /* tie off destination */
yuuji@0 182 return d - *dst; /* return length */
yuuji@0 183 }
yuuji@0 184
yuuji@0 185 /* Length of Unix string after unix_crlfcpy applied
yuuji@0 186 * Accepts: source string
yuuji@0 187 * Returns: length of string
yuuji@0 188 */
yuuji@0 189
yuuji@0 190 unsigned long unix_crlflen (STRING *s)
yuuji@0 191 {
yuuji@0 192 unsigned long pos = GETPOS (s);
yuuji@0 193 unsigned long i = SIZE (s);
yuuji@0 194 unsigned long j = i;
yuuji@0 195 while (j--) switch (SNX (s)) {/* search for newlines */
yuuji@0 196 case '\015': /* unlikely carriage return */
yuuji@0 197 if (j && (CHR (s) == '\012')) {
yuuji@0 198 SNX (s); /* eat the line feed */
yuuji@0 199 j--;
yuuji@0 200 }
yuuji@0 201 break;
yuuji@0 202 case '\012': /* line feed? */
yuuji@0 203 i++;
yuuji@0 204 default: /* ordinary chararacter */
yuuji@0 205 break;
yuuji@0 206 }
yuuji@0 207 SETPOS (s,pos); /* restore old position */
yuuji@0 208 return i;
yuuji@0 209 }
yuuji@0 210
yuuji@0 211 /* Undoubtably, I'm going to regret these two routines in the future. I
yuuji@0 212 * regret them now. Their purpose is to work around two problems in the
yuuji@0 213 * VC++ 6.0 C library:
yuuji@0 214 * (1) tmpfile() creates the file in the current directory instead of a
yuuji@0 215 * temporary directory
yuuji@0 216 * (2) tmpfile() and fclose() think that on NT systems, it works to unlink
yuuji@0 217 * the file while it's still open, so there's no need for the _tmpfname
yuuji@0 218 * hook at fclose(). Unfortunately, that doesn't work in Win2K.
yuuji@0 219 * I would be delighted to have a better alternative.
yuuji@0 220 */
yuuji@0 221
yuuji@0 222 #undef fclose /* use the real fclose() in close_file() */
yuuji@0 223
yuuji@0 224 /* Substitute for Microsoft's tmpfile() that uses the real temporary directory
yuuji@0 225 * Returns: FILE structure if success, NIL if failure
yuuji@0 226 */
yuuji@0 227
yuuji@0 228 FILE *create_tempfile (void)
yuuji@0 229 {
yuuji@0 230 FILE *ret = NIL;
yuuji@0 231 char *s = _tempnam (getenv ("TEMP"),"msg");
yuuji@0 232 if (s) { /* if got temporary name... */
yuuji@0 233 /* open file, and stash name on _tmpfname */
yuuji@0 234 if (ret = fopen (s,"w+b")) ret->_tmpfname = s;
yuuji@0 235 else fs_give ((void **) &s);/* flush temporary string */
yuuji@0 236 }
yuuji@0 237 return ret;
yuuji@0 238 }
yuuji@0 239
yuuji@0 240
yuuji@0 241 /* Substitute for Microsoft's fclose() that always flushes _tmpfname
yuuji@0 242 * Returns: FILE structure if success, NIL if failure
yuuji@0 243 */
yuuji@0 244
yuuji@0 245 int close_file (FILE *stream)
yuuji@0 246 {
yuuji@0 247 int ret;
yuuji@0 248 char *s = stream->_tmpfname;
yuuji@0 249 stream->_tmpfname = NIL; /* just in case fclose() tries to delete it */
yuuji@0 250 ret = fclose (stream); /* close the file */
yuuji@0 251 if (s) { /* was there a _tmpfname? */
yuuji@0 252 unlink (s); /* yup, delete it */
yuuji@0 253 fs_give ((void **) &s); /* and flush the name */
yuuji@0 254 }
yuuji@0 255 return ret;
yuuji@0 256 }
yuuji@0 257
yuuji@0 258 /* Get password from console
yuuji@0 259 * Accepts: prompt
yuuji@0 260 * Returns: password
yuuji@0 261 */
yuuji@0 262
yuuji@0 263 #define PWDLEN 128 /* used by Linux */
yuuji@0 264
yuuji@0 265 char *getpass (const char *prompt)
yuuji@0 266 {
yuuji@0 267 static char pwd[PWDLEN];
yuuji@0 268 int ch,i,done;
yuuji@0 269 fputs (prompt,stderr); /* output prompt */
yuuji@0 270 for (i = done = 0; !done; ) switch (ch = _getch()) {
yuuji@0 271 case 0x03: /* CTRL/C stops program */
yuuji@0 272 _exit (1);
yuuji@0 273 case '\b': /* BACKSPACE erase previous character */
yuuji@0 274 if (i) pwd[--i] = '\0';
yuuji@0 275 break;
yuuji@0 276 case '\n': case '\r': /* CR or LF terminates string */
yuuji@0 277 done = 1;
yuuji@0 278 break;
yuuji@0 279 default: /* any other character is a pwd char */
yuuji@0 280 if (i < (PWDLEN - 1)) pwd[i++] = ch;
yuuji@0 281 break;
yuuji@0 282 }
yuuji@0 283 pwd[i] = '\0'; /* tie off string with null */
yuuji@0 284 putchar ('\n'); /* echo newline */
yuuji@0 285 return pwd;
yuuji@0 286 }

UW-IMAP'd extensions by yuuji