authutil.c revision d17cd367
1/******************************************************************************
2
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26Author: Ralph Mor, X Consortium
27******************************************************************************/
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <X11/ICE/ICElib.h>
33#include "ICElibint.h"
34#include <X11/ICE/ICEutil.h>
35#include <X11/Xos.h>
36#include <sys/stat.h>
37#include <errno.h>
38
39#include <time.h>
40#define Time_t time_t
41#ifdef __UNIXOS2__
42extern char* getenv(const char*);
43#define link rename
44#endif
45#ifndef X_NOT_POSIX
46#include <unistd.h>
47#else
48#ifndef WIN32
49extern unsigned	sleep ();
50#else
51#define link rename
52#endif
53#endif
54
55static Status read_short (FILE *file, unsigned short *shortp);
56static Status read_string (FILE *file, char **stringp);
57static Status read_counted_string (FILE *file, unsigned short *countp, char **stringp);
58static Status write_short (FILE *file, unsigned short s);
59static Status write_string (FILE *file, char *string);
60static Status write_counted_string (FILE *file, unsigned short count, char *string);
61
62
63
64/*
65 * The following routines are for manipulating the .ICEauthority file
66 * These are utility functions - they are not part of the standard
67 * ICE library specification.
68 */
69
70char *
71IceAuthFileName (void)
72{
73    static char slashDotICEauthority[] = "/.ICEauthority";
74    char    	*name;
75    static char	*buf;
76    static int	bsize;
77    int	    	size;
78#if defined(WIN32) || defined(__UNIXOS2__)
79#ifndef PATH_MAX
80#define PATH_MAX 512
81#endif
82    char    	dir[PATH_MAX];
83#endif
84
85    if ((name = getenv ("ICEAUTHORITY")))
86	return (name);
87
88    name = getenv ("HOME");
89
90    if (!name)
91    {
92#ifdef WIN32
93    register char *ptr1;
94    register char *ptr2;
95    int len1 = 0, len2 = 0;
96
97    if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
98	len1 = strlen (ptr1);
99	len2 = strlen (ptr2);
100    } else if ((ptr2 = getenv("USERNAME"))) {
101	len1 = strlen (ptr1 = "/users/");
102	len2 = strlen (ptr2);
103    }
104    if ((len1 + len2 + 1) < PATH_MAX) {
105	sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : "");
106	name = dir;
107    }
108    if (!name)
109#endif
110#ifdef __UNIXOS2__
111	strcpy (dir,"c:");
112	name = dir;
113	if (!name)
114#endif
115	return (NULL);
116    }
117
118    size = strlen (name) + strlen (&slashDotICEauthority[1]) + 2;
119
120    if (size > bsize)
121    {
122	if (buf)
123	    free (buf);
124	buf = malloc ((unsigned) size);
125	if (!buf)
126	    return (NULL);
127	bsize = size;
128    }
129
130    strcpy (buf, name);
131    strcat (buf, slashDotICEauthority + (name[1] == '\0' ? 1 : 0));
132
133    return (buf);
134}
135
136
137
138int
139IceLockAuthFile (
140	char	*file_name,
141	int	retries,
142	int	timeout,
143	long	dead
144)
145{
146    char	creat_name[1025], link_name[1025];
147    struct stat	statb;
148    Time_t	now;
149    int		creat_fd = -1;
150
151    if ((int) strlen (file_name) > 1022)
152	return (IceAuthLockError);
153
154    strcpy (creat_name, file_name);
155    strcat (creat_name, "-c");
156    strcpy (link_name, file_name);
157    strcat (link_name, "-l");
158
159    if (stat (creat_name, &statb) != -1)
160    {
161	now = time ((Time_t *) 0);
162
163	/*
164	 * NFS may cause ctime to be before now, special
165	 * case a 0 deadtime to force lock removal
166	 */
167
168	if (dead == 0 || now - statb.st_ctime > dead)
169	{
170	    unlink (creat_name);
171	    unlink (link_name);
172	}
173    }
174
175    while (retries > 0)
176    {
177	if (creat_fd == -1)
178	{
179	    creat_fd = creat (creat_name, 0666);
180
181	    if (creat_fd == -1)
182	    {
183		if (errno != EACCES)
184		    return (IceAuthLockError);
185	    }
186	    else
187		close (creat_fd);
188	}
189
190	if (creat_fd != -1)
191	{
192	    if (link (creat_name, link_name) != -1)
193		return (IceAuthLockSuccess);
194
195	    if (errno == ENOENT)
196	    {
197		creat_fd = -1;	/* force re-creat next time around */
198		continue;
199	    }
200
201	    if (errno != EEXIST)
202		return (IceAuthLockError);
203	}
204
205	sleep ((unsigned) timeout);
206	--retries;
207    }
208
209    return (IceAuthLockTimeout);
210}
211
212
213
214void
215IceUnlockAuthFile (
216	char	*file_name
217)
218{
219#ifndef WIN32
220    char	creat_name[1025];
221#endif
222    char	link_name[1025];
223
224    if ((int) strlen (file_name) > 1022)
225	return;
226
227#ifndef WIN32
228    strcpy (creat_name, file_name);
229    strcat (creat_name, "-c");
230#endif
231    strcpy (link_name, file_name);
232    strcat (link_name, "-l");
233
234#ifndef WIN32
235    unlink (creat_name);
236#endif
237    unlink (link_name);
238}
239
240
241
242IceAuthFileEntry *
243IceReadAuthFileEntry (
244	FILE	*auth_file
245)
246{
247    IceAuthFileEntry   	local;
248    IceAuthFileEntry   	*ret;
249
250    local.protocol_name = NULL;
251    local.protocol_data = NULL;
252    local.network_id = NULL;
253    local.auth_name = NULL;
254    local.auth_data = NULL;
255
256    if (!read_string (auth_file, &local.protocol_name))
257	return (NULL);
258
259    if (!read_counted_string (auth_file,
260	&local.protocol_data_length, &local.protocol_data))
261	goto bad;
262
263    if (!read_string (auth_file, &local.network_id))
264	goto bad;
265
266    if (!read_string (auth_file, &local.auth_name))
267	goto bad;
268
269    if (!read_counted_string (auth_file,
270	&local.auth_data_length, &local.auth_data))
271	goto bad;
272
273    if (!(ret = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry))))
274	goto bad;
275
276    *ret = local;
277
278    return (ret);
279
280 bad:
281
282    if (local.protocol_name) free (local.protocol_name);
283    if (local.protocol_data) free (local.protocol_data);
284    if (local.network_id) free (local.network_id);
285    if (local.auth_name) free (local.auth_name);
286    if (local.auth_data) free (local.auth_data);
287
288    return (NULL);
289}
290
291
292
293void
294IceFreeAuthFileEntry (
295	IceAuthFileEntry	*auth
296)
297{
298    if (auth)
299    {
300	if (auth->protocol_name) free (auth->protocol_name);
301	if (auth->protocol_data) free (auth->protocol_data);
302	if (auth->network_id) free (auth->network_id);
303	if (auth->auth_name) free (auth->auth_name);
304	if (auth->auth_data) free (auth->auth_data);
305	free ((char *) auth);
306    }
307}
308
309
310
311Status
312IceWriteAuthFileEntry (
313	FILE			*auth_file,
314	IceAuthFileEntry	*auth
315)
316{
317    if (!write_string (auth_file, auth->protocol_name))
318	return (0);
319
320    if (!write_counted_string (auth_file,
321	auth->protocol_data_length, auth->protocol_data))
322	return (0);
323
324    if (!write_string (auth_file, auth->network_id))
325	return (0);
326
327    if (!write_string (auth_file, auth->auth_name))
328	return (0);
329
330    if (!write_counted_string (auth_file,
331	auth->auth_data_length, auth->auth_data))
332	return (0);
333
334    return (1);
335}
336
337
338
339IceAuthFileEntry *
340IceGetAuthFileEntry (
341	char	*protocol_name,
342	char	*network_id,
343	char	*auth_name
344)
345{
346    FILE    		*auth_file;
347    char    		*filename;
348    IceAuthFileEntry    *entry;
349
350    if (!(filename = IceAuthFileName ()))
351	return (NULL);
352
353    if (access (filename, R_OK) != 0)		/* checks REAL id */
354	return (NULL);
355
356    if (!(auth_file = fopen (filename, "rb")))
357	return (NULL);
358
359    for (;;)
360    {
361	if (!(entry = IceReadAuthFileEntry (auth_file)))
362	    break;
363
364	if (strcmp (protocol_name, entry->protocol_name) == 0 &&
365	    strcmp (network_id, entry->network_id) == 0 &&
366            strcmp (auth_name, entry->auth_name) == 0)
367	{
368	    break;
369	}
370
371	IceFreeAuthFileEntry (entry);
372    }
373
374    fclose (auth_file);
375
376    return (entry);
377}
378
379
380
381/*
382 * local routines
383 */
384
385static Status
386read_short (FILE *file, unsigned short *shortp)
387{
388    unsigned char   file_short[2];
389
390    if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
391	return (0);
392
393    *shortp = file_short[0] * 256 + file_short[1];
394    return (1);
395}
396
397
398static Status
399read_string (FILE *file, char **stringp)
400
401{
402    unsigned short  len;
403    char	    *data;
404
405    if (!read_short (file, &len))
406	return (0);
407
408    data = malloc ((unsigned) len + 1);
409
410    if (!data)
411	    return (0);
412
413    if (len != 0)
414    {
415	if (fread (data, (int) sizeof (char), (int) len, file) != len)
416	{
417	    free (data);
418	    return (0);
419	}
420
421    }
422    data[len] = '\0';
423
424    *stringp = data;
425
426    return (1);
427}
428
429
430static Status
431read_counted_string (FILE *file, unsigned short	*countp, char **stringp)
432{
433    unsigned short  len;
434    char	    *data;
435
436    if (!read_short (file, &len))
437	return (0);
438
439    if (len == 0)
440    {
441	data = NULL;
442    }
443    else
444    {
445    	data = malloc ((unsigned) len);
446
447    	if (!data)
448	    return (0);
449
450    	if (fread (data, (int) sizeof (char), (int) len, file) != len)
451	{
452	    free (data);
453	    return (0);
454    	}
455    }
456
457    *stringp = data;
458    *countp = len;
459
460    return (1);
461}
462
463
464static Status
465write_short (FILE *file, unsigned short s)
466{
467    unsigned char   file_short[2];
468
469    file_short[0] = (s & (unsigned) 0xff00) >> 8;
470    file_short[1] = s & 0xff;
471
472    if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
473	return (0);
474
475    return (1);
476}
477
478
479static Status
480write_string (FILE *file, char *string)
481{
482    unsigned short count = strlen (string);
483
484    if (!write_short (file, count))
485	return (0);
486
487    if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
488	return (0);
489
490    return (1);
491}
492
493
494static Status
495write_counted_string (FILE *file, unsigned short count, char *string)
496{
497    if (!write_short (file, count))
498	return (0);
499
500    if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
501	return (0);
502
503    return (1);
504}
505