usr/src/lib/libc/port/gen/nlspath_checks.c
author stevel@tonic-gate
Tue, 14 Jun 2005 00:00:00 -0700
changeset 0 68f95e015346
child 6812 febeba71273d
permissions -rw-r--r--
OpenSolaris Launch
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
#include "synonyms.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
#include "mtlib.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include <syslog.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <fcntl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <limits.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <unistd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <thread.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <synch.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <ctype.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include "libc.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include "nlspath_checks.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
extern const char **environ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 * We want to prevent the use of NLSPATH by setugid applications but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 * not completely.  CDE depends on this very much.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 * Yes, this is ugly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
struct trusted_systemdirs {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
	const char	*dir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
	size_t	dirlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#define	_USRLIB	"/usr/lib/"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#define	_USRDT	"/usr/dt/"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#define	_USROW	"/usr/openwin/"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
static const struct trusted_systemdirs	prefix[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
	{ _USRLIB,	sizeof (_USRLIB) - 1 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
	{ _USRDT,	sizeof (_USRDT) - 1 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
	{ _USROW,	sizeof (_USROW) - 1 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
	{ NULL,		0 }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
static int8_t nlspath_safe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
 * Routine to check the safety of a messages file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 * When the program specifies a pathname and doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
 * use NLSPATH, it should specify the "safe" flag as 1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 * Most checks will be disabled then.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 * fstat64 is done here and the stat structure is returned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
 * to prevent duplication of system calls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
 * The trust return value contains an indication of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 * trustworthiness (i.e., does check_format need to be called or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 * not)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
nls_safe_open(const char *path, struct stat64 *statbuf, int *trust, int safe)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
	int	fd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
	int	trust_path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
	int	systemdir = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
	int	abs_path = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
	int	trust_owner = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
	int	trust_group = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
	const struct trusted_systemdirs	*p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
	 * If SAFE_F has been specified or NLSPATH is safe (or not set),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
	 * set trust_path and trust the file as an initial value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
	trust_path = *trust = safe || nlspath_safe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
	fd = open(path, O_RDONLY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
	if (fd < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
	if (fstat64(fd, statbuf) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
		(void) close(fd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
	 * Trust only files owned by root or bin (uid 2), except
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
	 * when specified as full path or when NLSPATH is known to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
	 * be safe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	 * Don't trust files writable by other or writable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
	 * by non-bin, non-root system group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	 * Don't trust these files even if the path is correct.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
	 * Since we don't support changing uids/gids on our files,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	 * we hardcode them here for now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
	 * if the path is absolute and does not contain "/../",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
	 * set abs_path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	if (*path == '/' && strstr(path, "/../") == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
		abs_path = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
		 * if the path belongs to the trusted system directory,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
		 * set systemdir.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
		for (p = prefix; p->dir; p++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
			if (strncmp(p->dir, path, p->dirlen) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
				systemdir = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	 * If the owner is root or bin, set trust_owner.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	if (statbuf->st_uid == 0 || statbuf->st_uid == 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
		trust_owner = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	 * If the file is neither other-writable nor group-writable by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	 * non-bin and non-root system group, set trust_group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	if ((statbuf->st_mode & (S_IWOTH)) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	    ((statbuf->st_mode & (S_IWGRP)) == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
		(statbuf->st_gid < 4 && statbuf->st_gid != 1))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
		trust_group = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	 * Even if UNSAFE_F has been specified and unsafe-NLSPATH
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	 * has been set, trust the file as long as it belongs to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	 * the trusted system directory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	if (!*trust && systemdir) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
		*trust = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	 * If:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	 *	file is not a full pathname,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	 * or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
	 *	neither trust_owner nor trust_path is set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	 * or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
	 *	trust_group is not set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	 * untrust it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	if (*trust &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	    (!abs_path || (!trust_owner && !trust_path) || !trust_group)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
		*trust = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	 * If set[ug]id process, open for the untrusted file should fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	 * Otherwise, the message extracted from the untrusted file
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
	 * will have to be checked by check_format().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
	if (issetugid()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
		if (!*trust) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
			 * Open should fail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
			(void) close(fd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
		 * if the path does not belong to the trusted system directory
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
		 * or if the owner is neither root nor bin, untrust it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
		if (!systemdir || !trust_owner) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
			*trust = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	return (fd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
 * Extract a format into a normalized format string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
 * Returns the number of arguments converted, -1 on error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
 * The string norm should contain 2N bytes; an upperbound is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
 * length of the format string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
 * The canonical format consists of two chars: one is the conversion
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
 * character (s, c, d, x, etc), the second one is the option flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
 * L, ll, l, w as defined below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
 * A special conversion character, '*', indicates that the argument
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
 * is used as a precision specifier.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
#define	OPT_L		0x01
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
#define	OPT_l		0x02
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
#define	OPT_ll		0x04
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
#define	OPT_w		0x08
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
#define	OPT_h		0x10
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
#define	OPT_hh		0x20
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
#define	OPT_j		0x40
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
/* Number of bytes per canonical format entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
#define	FORMAT_SIZE	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
 * Check and store the argument; allow each argument to be used only as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
 * one type even though printf allows multiple uses.  The specification only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
 * allows one use, but we don't want to break existing functional code,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
 * even if it's buggy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
#define	STORE(buf, size, arg, val) 	if (arg * FORMAT_SIZE + 1 >= size ||\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
					    (strict ? \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
					    (buf[arg*FORMAT_SIZE] != '\0' && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
					    buf[arg*FORMAT_SIZE] != val) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
						: \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
					    (buf[arg*FORMAT_SIZE] == 'n'))) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
						return (-1); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
					else {\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
						if (arg >= maxarg) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
							maxarg = arg + 1; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
						narg++; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
						buf[arg*FORMAT_SIZE] = val; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
 * This function extracts sprintf format into a canonical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
 * sprintf form.  It's not as easy as just removing everything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
 * that isn't a format specifier, because of "%n$" specifiers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
 * Ideally, this should be compatible with printf and not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
 * fail on bad formats.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
 * However, that makes writing a proper check_format that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
 * doesn't cause crashes a lot harder.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
extract_format(const char *fmt, char *norm, size_t sz, int strict)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	int narg = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
	int t, arg, argp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	int dotseen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	char flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
	char conv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
	int lastarg = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
	int prevarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	int maxarg = 0;		/* Highest index seen + 1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
	int lflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
	(void) memset(norm, '\0', sz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	printf("Format \"%s\" canonical form: ", fmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
	for (; *fmt; fmt++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
		if (*fmt == '%') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
			if (*++fmt == '%')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
			if (*fmt == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
			prevarg = lastarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
			arg = ++lastarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
			t = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
			while (*fmt && isdigit(*fmt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
				t = t * 10 + *fmt++ - '0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
			if (*fmt == '$') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
				lastarg = arg = t - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
				fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
			if (*fmt == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
				goto end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
			dotseen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
			flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
			lflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
			/* Skip flags */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
			while (*fmt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
				switch (*fmt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
				case '\'':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
				case '+':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
				case '-':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
				case ' ':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
				case '#':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
				case '0':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
					fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
			while (*fmt && isdigit(*fmt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
				fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
			if (*fmt == '*') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
				if (isdigit(fmt[1])) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
					fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
					t = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
					while (*fmt && isdigit(*fmt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
						t = t * 10 + *fmt++ - '0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
					if (*fmt == '$') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
						argp = t - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
						STORE(norm, sz, argp, '*');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
					 * If digits follow a '*', it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
					 * not loaded as an argument, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
					 * digits are used instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
					 * Weird as it may seem, if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
					 * use an numbered argument, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
					 * get the next one if we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
					 * an unnumbered '*'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
					if (fmt[1] == '$')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
						fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
					else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
						argp = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
						prevarg = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
						lastarg = ++arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
						STORE(norm, sz, argp, '*');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
				fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
			/* Fail on two or more dots if we do strict checking */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
			if (*fmt == '.' || *fmt == '*') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
				if (dotseen && strict)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
					return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
				dotseen = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
				fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
				goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
			if (*fmt == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
				goto end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
			while (*fmt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
				switch (*fmt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
				case 'l':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
					if (!(flag & OPT_ll)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
						if (lflag) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
							flag &= ~OPT_l;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
							flag |= OPT_ll;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
						} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
							flag |= OPT_l;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
						}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
					lflag++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
				case 'L':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
					flag |= OPT_L;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
				case 'w':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
					flag |= OPT_w;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
				case 'h':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
					if (flag & (OPT_h|OPT_hh))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
						flag |= OPT_hh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
					else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
						flag |= OPT_h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
				case 'j':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
					flag |= OPT_j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
				case 'z':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
				case 't':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
					if (!(flag & OPT_ll)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
						flag |= OPT_l;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
				case '\'':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
				case '+':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
				case '-':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
				case ' ':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
				case '#':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
				case '.':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
				case '*':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
					goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
				default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
					if (isdigit(*fmt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
						goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
					else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
						goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
				fmt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
			if (*fmt == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
				goto end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
			switch (*fmt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
			case 'C':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
				flag |= OPT_l;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
				/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
			case 'd':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
			case 'i':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
			case 'o':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
			case 'u':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
			case 'c':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
			case 'x':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
			case 'X':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
				conv = 'I';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
			case 'e':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
			case 'E':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
			case 'f':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
			case 'F':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
			case 'a':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
			case 'A':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
			case 'g':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
			case 'G':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
				conv = 'D';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
			case 'S':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
				flag |= OPT_l;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
				/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
			case 's':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
				conv = 's';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
			case 'p':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
			case 'n':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
				conv = *fmt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
				lastarg = prevarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
			STORE(norm, sz, arg, conv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
			norm[arg*FORMAT_SIZE + 1] = flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
	for (t = 0; t < maxarg * FORMAT_SIZE; t += FORMAT_SIZE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	    printf("%c(%d)", norm[t], norm[t+1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
	putchar('\n');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
end:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
	if (strict)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
		for (arg = 0; arg < maxarg; arg++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
			if (norm[arg*FORMAT_SIZE] == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
	return (maxarg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
check_format(const char *org, const char *new, int strict)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
	char *ofmt, *nfmt, *torg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
	size_t osz, nsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
	int olen, nlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
	if (!org) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
		 * Default message is NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
		 * dtmail uses NULL for default message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
		torg = "(NULL)";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
		torg = (char *)org;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
	/* Short cut */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
	if (org == new || strcmp(torg, new) == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	    strchr(new, '%') == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
		return ((char *)new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
	osz = strlen(torg) * FORMAT_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
	ofmt = malloc(osz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
	if (ofmt == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
		return ((char *)org);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
	olen = extract_format(torg, ofmt, osz, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
	if (olen == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
		syslog(LOG_AUTH|LOG_INFO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
		    "invalid format in gettext argument: \"%s\"", torg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
	nsz = strlen(new) * FORMAT_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
	nfmt = malloc(nsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
	if (nfmt == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
		free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		return ((char *)org);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
	nlen = extract_format(new, nfmt, nsz, strict);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
	if (nlen == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
		free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		free(nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
		syslog(LOG_AUTH|LOG_NOTICE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		    "invalid format in message file \"%.100s\" -> \"%s\"",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
		    torg, new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		errno = EBADMSG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
		return ((char *)org);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
	if (strict && (olen != nlen || olen == -1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
		free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
		free(nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
		syslog(LOG_AUTH|LOG_NOTICE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		    "incompatible format in message file: \"%.100s\" != \"%s\"",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		    torg, new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
		errno = EBADMSG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		return ((char *)org);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
	if (strict && memcmp(ofmt, nfmt, nlen * FORMAT_SIZE) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
		free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
		free(nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
		return ((char *)new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
		if (!strict) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
			char *n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
			nlen *= FORMAT_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
			for (n = nfmt; n = memchr(n, 'n', nfmt + nlen - n);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
			    n++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
				int off = (n - nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
				if (off >= olen * FORMAT_SIZE ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
				    ofmt[off] != 'n' ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
				    ofmt[off+1] != nfmt[off+1]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
					free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
					free(nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
					syslog(LOG_AUTH|LOG_NOTICE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
					    "dangerous format in message file: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
					    "\"%.100s\" -> \"%s\"", torg, new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
					errno = EBADMSG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
					return ((char *)org);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
			free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
			free(nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
			return ((char *)new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
		free(ofmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
		free(nfmt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
		syslog(LOG_AUTH|LOG_NOTICE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
		    "incompatible format in message file \"%.100s\" != \"%s\"",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
		    torg, new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
		errno = EBADMSG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
		return ((char *)org);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
 * s1 is either name, or name=value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
 * s2 is name=value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
 * if names match, return value of s2, else NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
 * used for environment searching: see getenv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
const char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
nvmatch(const char *s1, const char *s2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	while (*s1 == *s2++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
		if (*s1++ == '=')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
			return (s2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	if (*s1 == '\0' && *(s2-1) == '=')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
		return (s2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
 * Handle NLSPATH environment variables in the environment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
 * This routine is hooked into getenv/putenv at first call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
 * The intention is to ignore NLSPATH in set-uid applications,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
 * and determine whether the NLSPATH in an application was set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
 * by the applications or derived from the user's environment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
clean_env(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
	const char **p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
	/* Find the first NLSPATH occurrence */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
	for (p = environ; *p; p++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
		if (**p == 'N' && nvmatch("NLSPATH", *p) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
	if (!*p)				/* None found, we're safe */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
		nlspath_safe = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
	else if (issetugid()) {			/* Found and set-uid, clean */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
		int off = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
		for (p++; (p[-off] = p[0]) != '\0'; p++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
			if (**p == 'N' && nvmatch("NLSPATH", *p) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
				off++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
		nlspath_safe = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
}