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 }
|