interact.c revision 1.1 1 /* $NetBSD: interact.c,v 1.1 1997/03/08 23:46:12 christos Exp $ */
2
3 /*
4 * Copyright (c) 1997 Christos Zoulas. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christos Zoulas.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef lint
33 static char rcsid[] = "$NetBSD: interact.c,v 1.1 1997/03/08 23:46:12 christos Exp $";
34 #endif /* lint */
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #define DKTYPENAMES
42 #include <sys/disklabel.h>
43
44 #include "extern.h"
45
46 static void cmd_help __P((struct disklabel *, char *, int));
47 static void cmd_print __P((struct disklabel *, char *, int));
48 static void cmd_part __P((struct disklabel *, char *, int));
49 static void cmd_label __P((struct disklabel *, char *, int));
50 static void cmd_round __P((struct disklabel *, char *, int));
51 static void cmd_name __P((struct disklabel *, char *, int));
52 static int runcmd __P((char *, struct disklabel *, int));
53 static int getinput __P((const char *, const char *, const char *, char *));
54 static void defnum __P((char *, struct disklabel *, int));
55 static int getnum __P((char *, struct disklabel *));
56 static void deffstypename __P((char *, int));
57 static int getfstypename __P((const char *));
58
59 static int rounding = 0; /* sector rounding */
60
61 static struct cmds {
62 const char *name;
63 void (*func) __P((struct disklabel *, char *, int));
64 const char *help;
65 } cmds[] = {
66 { "a", cmd_part, "define partition a" },
67 { "b", cmd_part, "define partition b" },
68 { "c", cmd_part, "define partition c" },
69 { "d", cmd_part, "define partition d" },
70 { "e", cmd_part, "define partition e" },
71 { "f", cmd_part, "define partition f" },
72 { "g", cmd_part, "define partition g" },
73 { "h", cmd_part, "define partition h" },
74 { "l", cmd_label, "write the current partition table" },
75 { "n", cmd_name, "name the label" },
76 { "p", cmd_print, "print current partition table" },
77 { "q", NULL, "quit" },
78 { "r", cmd_round, "rounding (c)ylinders (s)ectors" },
79 { "?", cmd_help, "print this menu" },
80 { NULL, NULL, NULL }
81 };
82
83
84
85 static void
86 cmd_help(lp, s, fd)
87 struct disklabel *lp;
88 char *s;
89 int fd;
90 {
91 struct cmds *cmd;
92 for (cmd = cmds; cmd->name != NULL; cmd++)
93 printf("%s\t%s\n", cmd->name, cmd->help);
94 }
95
96
97 static void
98 cmd_print(lp, s, fd)
99 struct disklabel *lp;
100 char *s;
101 int fd;
102 {
103 display(stdout, lp);
104 }
105
106
107 static void
108 cmd_name(lp, s, fd)
109 struct disklabel *lp;
110 char *s;
111 int fd;
112 {
113 char line[BUFSIZ];
114 int i = getinput(":", "Label name", lp->d_packname, line);
115
116 if (i <= 0)
117 return;
118 (void) strncpy(lp->d_packname, line, sizeof(lp->d_packname));
119 }
120
121
122 static void
123 cmd_round(lp, s, fd)
124 struct disklabel *lp;
125 char *s;
126 int fd;
127 {
128 int i;
129 char line[BUFSIZ];
130
131 i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line);
132
133 if (i <= 0)
134 return;
135
136 switch (line[0]) {
137 case 'c':
138 rounding = 1;
139 return;
140 case 's':
141 rounding = 0;
142 return;
143 default:
144 printf("Rounding can be (c)ylinders or (s)ectors\n");
145 return;
146 }
147 }
148
149
150 static void
151 cmd_part(lp, s, fd)
152 struct disklabel *lp;
153 char *s;
154 int fd;
155 {
156 int i;
157 char line[BUFSIZ];
158 char def[BUFSIZ];
159 int part = *s - 'a';
160 struct partition *p = &lp->d_partitions[part];
161
162 if (part <= lp->d_npartitions)
163 lp->d_npartitions = part + 1;
164
165 for (;;) {
166 deffstypename(def, p->p_fstype);
167 i = getinput(":", "Filesystem type", def, line);
168 if (i <= 0)
169 break;
170 if ((i = getfstypename(line)) == -1) {
171 printf("Invalid file system typename `%s'\n", line);
172 continue;
173 }
174 p->p_fstype = i;
175 break;
176 }
177 for (;;) {
178 defnum(def, lp, p->p_offset);
179 i = getinput(":", "Start offset", def, line);
180 if (i <= 0)
181 break;
182 if ((i = getnum(line, lp)) == -1) {
183 printf("Bad offset `%s'\n", line);
184 continue;
185 }
186 p->p_offset = i;
187 break;
188 }
189 for (;;) {
190 defnum(def, lp, p->p_size);
191 i = getinput(":", "Partition size", def, line);
192 if (i <= 0)
193 break;
194 if ((i = getnum(line, lp)) == -1) {
195 printf("Bad size `%s'\n", line);
196 continue;
197 }
198 p->p_size = i;
199 break;
200 }
201 }
202
203
204 static void
205 cmd_label(lp, s, fd)
206 struct disklabel *lp;
207 char *s;
208 int fd;
209 {
210 char line[BUFSIZ];
211 int i;
212
213 i = getinput("?", "Label disk", "n", line);
214
215 if (i <= 0 || *line != 'y')
216 return;
217
218 if (checklabel(lp) != 0) {
219 printf("Label not written\n");
220 return;
221 }
222
223 if ((i = writelabel(fd, bootarea, lp)) != 0) {
224 printf("Label not written %d\n", strerror(i));
225 return;
226 }
227 printf("Label written\n");
228 }
229
230
231 static int
232 runcmd(line, lp, fd)
233 char *line;
234 struct disklabel *lp;
235 int fd;
236 {
237 struct cmds *cmd;
238
239 for (cmd = cmds; cmd->name != NULL; cmd++)
240 if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
241 if (cmd->func == NULL)
242 return -1;
243 (*cmd->func)(lp, line, fd);
244 return;
245 }
246 printf("Unknown command %s\n", line);
247 }
248
249
250 static int
251 getinput(sep, prompt, def, line)
252 const char *sep;
253 const char *prompt;
254 const char *def;
255 char *line;
256 {
257 for (;;) {
258 printf("%s", prompt);
259 if (def)
260 printf(" [%s]", def);
261 printf("%s ", sep);
262
263 if (fgets(line, BUFSIZ, stdin) == NULL)
264 return -1;
265 if (line[0] == '\n' || line[0] == '\0') {
266 if (def)
267 return 0;
268 }
269 else {
270 char *p;
271
272 if ((p = strrchr(line, '\n')) != NULL)
273 *p = '\0';
274 return 1;
275 }
276 }
277 }
278
279
280 static void
281 defnum(buf, lp, size)
282 char *buf;
283 struct disklabel *lp;
284 int size;
285 {
286 (void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM",
287 size / (float) lp->d_secpercyl,
288 size, size * (lp->d_secsize / (float) (1024 * 1024)));
289 }
290
291
292 static int
293 getnum(buf, lp)
294 char *buf;
295 struct disklabel *lp;
296 {
297 char *ep;
298 double d = strtod(buf, &ep);
299 int rv;
300
301 if (buf == ep)
302 return -1;
303
304 #define ROUND(a) ((a / lp->d_secpercyl) + \
305 ((a % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl
306
307 switch (*ep) {
308 case '\0':
309 case 's':
310 rv = (int) d;
311 break;
312
313 case 'c':
314 rv = (int) (d * lp->d_secpercyl);
315 break;
316
317 case 'M':
318 rv = (int) (d * 1024 * 1024 / lp->d_secsize);
319 break;
320
321 default:
322 printf("Unit error %c\n", *ep);
323 return -1;
324 }
325
326 if (rounding)
327 return ROUND(rv);
328 else
329 return rv;
330 }
331
332
333 static void
334 deffstypename(buf, i)
335 char *buf;
336 int i;
337 {
338 if (i < 0 || i >= DKMAXTYPES)
339 i = 0;
340 (void) strcpy(buf, fstypenames[i]);
341 }
342
343
344 static int
345 getfstypename(buf)
346 const char *buf;
347 {
348 int i;
349
350 for (i = 0; i < DKMAXTYPES; i++)
351 if (strcmp(buf, fstypenames[i]) == 0)
352 return i;
353 return -1;
354 }
355
356
357 void
358 interact(lp, fd)
359 struct disklabel *lp;
360 int fd;
361 {
362 char line[BUFSIZ];
363
364 for (;;) {
365 if (getinput(">", "partition", NULL, line) == -1)
366 return;
367 if (runcmd(line, lp, fd) == -1)
368 return;
369 }
370 }
371