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