xref: /openbsd-src/usr.bin/rdist/isexec.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: isexec.c,v 1.7 2003/06/03 02:56:14 millert Exp $	*/
2 
3 /*
4  * Copyright (c) 1983 Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "defs.h"
33 
34 #ifndef lint
35 #if 0
36 static char RCSid[] __attribute__((__unused__)) =
37 "$From: isexec.c,v 1.2 1999/08/04 15:57:33 christos Exp $";
38 #else
39 static char RCSid[] __attribute__((__unused__)) =
40 "$OpenBSD: isexec.c,v 1.7 2003/06/03 02:56:14 millert Exp $";
41 #endif
42 
43 static char sccsid[] __attribute__((__unused__)) =
44 "@(#)client.c";
45 
46 static char copyright[] __attribute__((__unused__)) =
47 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
48  All rights reserved.\n";
49 #endif /* not lint */
50 
51 static int _isexec(int);
52 
53 #if	EXE_TYPE == EXE_AOUT
54 /*
55  * BSD style A.OUT
56  */
57 #include <a.out.h>
58 
59 static int
60 _isexec(int fd)
61 {
62 	struct exec ehdr;
63 
64 	if ((read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) &&
65 	    !N_BADMAG(ehdr))
66 		return(TRUE);
67 	else
68 		return(FALSE);
69 }
70 #endif /* EXE_AOUT */
71 
72 
73 #if	EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_ELF
74 /*
75  * Elf
76  */
77 #include <elf_abi.h>
78 #define ISELF(h)	(h.e_type == ET_EXEC)
79 #endif	/* EXE_ELF_AND_COFF || EXE_ELF */
80 
81 #if 	EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_COFF
82 
83 /*
84  * COFF
85  */
86 #if defined(FILEHDR_H)
87 #include FILEHDR_H
88 #endif	/* FILEHDR_H */
89 
90 #if !defined(ISCOFF)
91 
92 /*
93  * Stupid AIX
94  */
95 #if defined(U802WRMAGIC) && defined(U802ROMAGIC) && defined(U802TOCMAGIC)
96 #define ISCOFF(x) (((x)==U802WRMAGIC) || ((x)==U802TOCMAGIC) || \
97 		   ((x)==U802TOCMAGIC))
98 #endif	/* U802... */
99 /*
100  * Stupid Umax4.3
101  */
102 #if 	defined(NS32GMAGIC) || defined(NS32SMAGIC)
103 #define ISCOFF(x) (((x)==NS32GMAGIC) || ((x)==NS32SMAGIC))
104 #endif 	/* NS32 ... */
105 
106 #endif	/* ISCOFF */
107 
108 #endif /* EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_COFF */
109 
110 #if	EXE_TYPE == EXE_ELF_AND_COFF
111 /*
112  * ELF and COFF
113  */
114 typedef union {
115     struct filehdr 	coffhdr;
116     Elf32_Ehdr 		elfhdr;
117 } hdr_t;
118 #endif	/* EXE_TYPE == EXE_ELF_AND_COFF */
119 
120 #if	EXE_TYPE == EXE_ELF
121 /*
122  * Elf
123  */
124 typedef Elf32_Ehdr 	hdr_t;
125 #endif	/* EXE_TYPE == EXE_ELF */
126 
127 #if	EXE_TYPE == EXE_COFF
128 /*
129  * COFF
130  */
131 
132 #if	defined(FILEHDR_H)
133 #include FILEHDR_H
134 #endif	/* FILEHDR_H */
135 
136 typedef struct filehdr 	hdr_t;
137 #endif	/* EXE_TYPE == EXE_COFF */
138 
139 #if	EXE_TYPE == EXE_ELF_AND_COFF || EXE_TYPE == EXE_ELF || EXE_TYPE == EXE_COFF
140 /*
141  * System V style COFF and System V R4 style ELF
142  */
143 static int
144 _isexec(int fd)
145 {
146 	hdr_t hdr;
147 
148 	if (read(fd, &hdr, sizeof(hdr)) == sizeof(hdr)) {
149 #if EXE_TYPE == EXE_ELF_AND_COFF
150 	    if (ISELF(hdr.elfhdr) || ISCOFF(hdr.coffhdr.f_magic))
151 		return(TRUE);
152 #endif
153 #if EXE_TYPE == EXE_ELF
154 	    if (ISELF(hdr))
155 		return(TRUE);
156 #endif
157 #if EXE_TYPE == EXE_COFF
158 	    if (ISCOFF(hdr.f_magic))
159 		return(TRUE);
160 #endif
161 	}
162 
163 	return(FALSE);
164 }
165 #endif /* EXE_ELF_AND_COFF */
166 
167 
168 #if	EXE_TYPE == EXE_MACHO
169 /*
170  * Mach-O format
171  */
172 
173 #if	defined(NEXTSTEP) && NEXTSTEP >= 3
174 #	include <mach-o/loader.h>
175 #else
176 #	include <sys/loader.h>
177 #endif	/* NEXTSTEP */
178 
179 #ifndef MH_CIGAM
180 #define MH_CIGAM  	0xcefaedfe
181 #endif
182 #ifndef FAT_MAGIC
183 #define FAT_MAGIC 	0xcafebabe
184 #endif
185 #ifndef FAT_CIGAM
186 #define FAT_CIGAM 	0xbebafeca
187 #endif
188 
189 static int
190 _isexec(int fd)
191 {
192 	struct mach_header ehdr;
193 
194 	if ((read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) &&
195 	    (ehdr.magic == MH_MAGIC || ehdr.magic == MH_CIGAM ||
196 	     ehdr.magic == FAT_MAGIC || ehdr.magic == FAT_CIGAM))
197 		return(TRUE);
198 	else
199 		return(FALSE);
200 }
201 #endif /* EXE_COFF */
202 
203 
204 #if	EXE_TYPE == EXE_HPEXEC
205 /*
206  * HP 9000 executable format
207  */
208 
209 #ifdef hp9000s300
210 
211 #include <a.out.h>
212 #define header exec
213 #define ISEXEC(a) ((a.file_type)==EXEC_MAGIC || (a.file_type)==SHARE_MAGIC || \
214 		   (a.file_type)==DEMAND_MAGIC)
215 
216 #else	/* ! hp9000s300 */
217 
218 #define ISEXEC(a) ((a)==EXEC_MAGIC || (a)==SHARE_MAGIC || (a)==DEMAND_MAGIC)
219 #include <filehdr.h>
220 
221 #endif	/* hp9000s300 */
222 
223 static int
224 _isexec(int fd)
225 {
226 	struct header ehdr;
227 
228 	if ((read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) &&
229 	    ISEXEC(ehdr.a_magic))
230 		return(TRUE);
231 	else
232 		return(FALSE);
233 }
234 #endif	/* EXE_HPEXEC */
235 
236 
237 #if	!defined(EXE_TYPE)
238 /*
239  * Fake _isexec() call for unknown executable formats.
240  */
241 static int
242 _isexec(int fd)
243 {
244 	return(FALSE);
245 }
246 #endif	/* !defined(EXE_TYPE) */
247 
248 /*
249  * Determine whether 'file' is an executable or not.
250  */
251 int
252 isexec(char *file, struct stat *statp)
253 {
254 	int fd, r;
255 
256 	/*
257 	 * Must be a regular file that has some executable mode bit on
258 	 */
259 	if (!S_ISREG(statp->st_mode) ||
260 	    !(statp->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
261 		return(FALSE);
262 
263 	if ((fd = open(file, O_RDONLY, 0)) < 0)
264 		return(FALSE);
265 	r = _isexec(fd);
266 	(void) close(fd);
267 
268 	return(r);
269 }
270 
271