1 /*
2  * Copyright (c) 2000, 2017 Peter Pentchev
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 #include <err.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #ifndef __unused
36 #ifdef __GNUC__
37 #define __unused	__attribute__((unused))
38 #else
39 #define __unused
40 #endif /* __GNUC__ */
41 #endif /* __unused */
42 
43 static void	rn_help(void);
44 static void	rn_version(void);
45 static void	rn_init(int argc, char * const argv[]);
46 static void	rn_doit(int argc, char * const argv[]);
47 
48 /***
49 Function:
50 	rn_init				- general-purpose init function
51 Inputs:
52 	argc, argv			- main() args for option processing
53 Returns:
54 	Nothing; dies on error.
55 Modifies:
56 	Nothing.
57 ***/
58 
59 static void
rn_init(const int argc,char * const argv[])60 rn_init(const int argc, char * const argv[]) {
61 	int ch;
62 	bool helpq = false, versq = false;
63 
64 	/* Process cmdline options */
65 
66 	while (ch = getopt(argc, argv, "hV"), ch != -1)
67 		switch(ch) {
68 			case 'h':
69 				helpq = true;
70 				break;
71 			case 'V':
72 				versq = true;
73 				break;
74 			case '?':
75 			default:
76 				exit(1);
77 				/* NOTREACHED */
78 		}
79 
80 	if (versq)
81 		rn_version();
82 	if (helpq)
83 		rn_help();
84 	if (versq || helpq)
85 		exit(0);
86 
87 	if (argc < optind + 2) {
88 		warnx("At least two arguments expected: a fake name and the real program's name");
89 		rn_help();
90 		exit(1);
91 	}
92 }
93 
94 /***
95 Function:
96 	rn_help					- startup help info
97 Inputs:
98 	none
99 Returns:
100 	Nothing.
101 Modifies:
102 	nothing, writes to stdout
103 ***/
104 
105 static void
rn_help(void)106 rn_help(void) {
107 	puts(
108 	"Usage:\trname fakename realname [args..]\n"
109 	"\trname -V | -h\n"
110 	"\n"
111 	"\t-h\tprint this help text and exit;\n"
112 	"\t-V\tprint version information and exit."
113 	);
114 }
115 
116 /***
117 function:
118 	rn_version				- output version info
119 Inputs:
120 	none
121 Returns:
122 	Nothing.
123 Modifies:
124 	nothing, writes to stdout
125 ***/
126 
127 static void
rn_version(void)128 rn_version(void) {
129 	puts("rname 1.0.2");
130 }
131 
132 /***
133 Function:
134 	rn_doit				- actually execute something
135 Inputs:
136 	none
137 Returns:
138 	Nothing; dies on error.
139 Modifies:
140 	copies argv to a newly-allocated array with the first element replaced,
141 	then exec's the requested program
142 ***/
143 
144 static void
rn_doit(const int argc,char * const argv[])145 rn_doit(const int argc, char * const argv[]) {
146 	const size_t nargc = argc - 1;
147 	char ** const nargv = malloc((nargc + 1) * sizeof(*nargv));
148 	if (nargv == NULL)
149 		err(1, "Could not allocate memory for the new command line array");
150 	nargv[0] = argv[0];
151 	for (size_t i = 1; i < nargc; i++)
152 		nargv[i] = argv[i + 1];
153 	nargv[nargc] = NULL;
154 
155 	execvp(argv[1], nargv);
156 	err(1, "Could not execute '%s' as '%s'", argv[1], nargv[0]);
157 }
158 
159 int
main(const int argc,char * const argv[])160 main(const int argc, char * const argv[]) {
161 	rn_init(argc, argv);
162 	rn_doit(argc - optind, argv + optind);
163 	return 0;
164 }
165