Annotation of sys/arch/zaurus/stand/zboot/cmd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cmd.c,v 1.3 2007/03/21 03:29:05 tedu Exp $ */
2:
3: /*
4: * Copyright (c) 1997-1999 Michael Shalayeff
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: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: #include <sys/param.h>
30: #include <sys/reboot.h>
31:
32: #ifdef REGRESS
33: #include <sys/stat.h>
34: #include <errno.h>
35: #else
36: #include <libsa.h>
37: #include <lib/libkern/funcs.h>
38: #endif
39:
40: #include <stand/boot/cmd.h>
41:
42: #define CTRL(c) ((c)&0x1f)
43:
44: static int Xboot(void);
45: static int Xclear(void);
46: static int Xecho(void);
47: static int Xhelp(void);
48: static int Xls(void);
49: static int Xnop(void);
50: static int Xreboot(void);
51: static int Xstty(void);
52: static int Xtime(void);
53: #ifdef MACHINE_CMD
54: static int Xmachine(void);
55: extern const struct cmd_table MACHINE_CMD[];
56: #endif
57: extern int Xset(void);
58: extern int Xenv(void);
59:
60: extern const struct cmd_table cmd_set[];
61: const struct cmd_table cmd_table[] = {
62: {"#", CMDT_CMD, Xnop}, /* XXX must be first */
63: {"boot", CMDT_CMD, Xboot},
64: {"clear", CMDT_CMD, Xclear},
65: {"echo", CMDT_CMD, Xecho},
66: {"env", CMDT_CMD, Xenv},
67: {"help", CMDT_CMD, Xhelp},
68: {"ls", CMDT_CMD, Xls},
69: #ifdef MACHINE_CMD
70: {"machine",CMDT_MDC, Xmachine},
71: #endif
72: {"reboot", CMDT_CMD, Xreboot},
73: {"set", CMDT_SET, Xset},
74: {"stty", CMDT_CMD, Xstty},
75: {"time", CMDT_CMD, Xtime},
76: {NULL, 0},
77: };
78:
79: static void ls(char *, struct stat *);
80: static int readline(char *, size_t, int);
81: char *nextword(char *);
82: static char *whatcmd(const struct cmd_table **ct, char *);
83: static char *qualify(char *);
84:
85: char cmd_buf[CMD_BUFF_SIZE];
86:
87: int
88: getcmd(void)
89: {
90: cmd.cmd = NULL;
91:
92: if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout))
93: cmd.cmd = cmd_table;
94:
95: return docmd();
96: }
97:
98: int
99: read_conf(void)
100: {
101: #ifndef INSECURE
102: struct stat sb;
103: #endif
104: int fd, rc = 0;
105:
106: if ((fd = open(qualify(cmd.conf), 0)) < 0) {
107: if (errno != ENOENT && errno != ENXIO) {
108: printf("open(%s): %s\n", cmd.path, strerror(errno));
109: return 0;
110: }
111: return -1;
112: }
113:
114: #ifndef INSECURE
115: (void) fstat(fd, &sb);
116: if (sb.st_uid || (sb.st_mode & 2)) {
117: printf("non-secure %s, will not proceed\n", cmd.path);
118: close(fd);
119: return -1;
120: }
121: #endif
122:
123: do {
124: char *p = cmd_buf;
125:
126: cmd.cmd = NULL;
127: do {
128: rc = read(fd, p, 1);
129: } while (rc > 0 && *p++ != '\n' &&
130: (p-cmd_buf) < sizeof(cmd_buf));
131:
132: if (rc < 0) { /* Error from read() */
133: printf("%s: %s\n", cmd.path, strerror(errno));
134: break;
135: }
136:
137: if (rc == 0) { /* eof from read() */
138: if (p != cmd_buf) { /* Line w/o trailing \n */
139: *p = '\0';
140: rc = docmd();
141: break;
142: }
143: } else { /* rc > 0, read a char */
144: p--; /* Get back to last character */
145:
146: if (*p != '\n') { /* Line was too long */
147: printf("%s: line too long\n", cmd.path);
148:
149: /* Don't want to run the truncated command */
150: rc = -1;
151: }
152: *p = '\0';
153: }
154: } while (rc > 0 && !(rc = docmd()));
155:
156: close(fd);
157: return rc;
158: }
159:
160: int
161: docmd(void)
162: {
163: char *p = NULL;
164: const struct cmd_table *ct = cmd_table, *cs;
165:
166: cmd.argc = 1;
167: if (cmd.cmd == NULL) {
168:
169: /* command */
170: for (p = cmd_buf; *p == ' ' || *p == '\t'; p++)
171: ;
172: if (*p == '#' || *p == '\0') { /* comment or empty string */
173: #ifdef DEBUG
174: printf("rem\n");
175: #endif
176: return 0;
177: }
178: ct = cmd_table;
179: cs = NULL;
180: cmd.argv[cmd.argc] = p; /* in case it's shortcut boot */
181: p = whatcmd(&ct, p);
182: if (ct == NULL) {
183: cmd.argc++;
184: ct = cmd_table;
185: } else if (ct->cmd_type == CMDT_SET && p != NULL) {
186: cs = cmd_set;
187: #ifdef MACHINE_CMD
188: } else if (ct->cmd_type == CMDT_MDC && p != NULL) {
189: cs = MACHINE_CMD;
190: #endif
191: }
192:
193: if (cs != NULL) {
194: p = whatcmd(&cs, p);
195: if (cs == NULL) {
196: printf("%s: syntax error\n", ct->cmd_name);
197: return 0;
198: }
199: ct = cs;
200: }
201: cmd.cmd = ct;
202: }
203:
204: cmd.argv[0] = ct->cmd_name;
205: while (p && cmd.argc+1 < sizeof(cmd.argv) / sizeof(cmd.argv[0])) {
206: cmd.argv[cmd.argc++] = p;
207: p = nextword(p);
208: }
209: cmd.argv[cmd.argc] = NULL;
210:
211: #ifdef REGRESS
212: printf("%s %s\n", cmd.argv[0],
213: (cmd.argv[1] == NULL) ? "(null)" : cmd.argv[1]);
214: #else
215: return (*cmd.cmd->cmd_exec)();
216: #endif
217: }
218:
219: static char *
220: whatcmd(const struct cmd_table **ct, char *p)
221: {
222: char *q;
223: int l;
224:
225: q = nextword(p);
226:
227: for (l = 0; p[l]; l++)
228: ;
229:
230: while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l))
231: (*ct)++;
232:
233: if ((*ct)->cmd_name == NULL)
234: *ct = NULL;
235:
236: return q;
237: }
238:
239: static int
240: readline(char *buf, size_t n, int to)
241: {
242: #ifdef DEBUG
243: extern int debug;
244: #endif
245: char *p = buf, ch;
246:
247: /* Only do timeout if greater than 0 */
248: if (to > 0) {
249: u_long i = 0;
250: time_t tt = getsecs() + to;
251: #ifdef DEBUG
252: if (debug > 2)
253: printf ("readline: timeout(%d) at %u\n", to, tt);
254: #endif
255: /* check for timeout expiration less often
256: (for some very constrained archs) */
257: while (!cnischar())
258: if (!(i++ % 1000) && (getsecs() >= tt))
259: break;
260:
261: if (!cnischar()) {
262: strlcpy(buf, "boot", 5);
263: putchar('\n');
264: return strlen(buf);
265: }
266: } else
267: while (!cnischar())
268: ;
269:
270: /* User has typed something. Turn off timeouts. */
271: cmd.timeout = 0;
272:
273: while (1) {
274: switch ((ch = getchar())) {
275: case CTRL('u'):
276: while (p > buf) {
277: putchar('\177');
278: p--;
279: }
280: continue;
281: case '\n':
282: case '\r':
283: p[1] = *p = '\0';
284: break;
285: case '\b':
286: case '\177':
287: if (p > buf) {
288: putchar('\177');
289: p--;
290: }
291: continue;
292: default:
293: if (p - buf < n-1)
294: *p++ = ch;
295: else {
296: putchar('\007');
297: putchar('\177');
298: }
299: continue;
300: }
301: break;
302: }
303:
304: return p - buf;
305: }
306:
307: /*
308: * Search for spaces/tabs after the current word. If found, \0 the
309: * first one. Then pass a pointer to the first character of the
310: * next word, or NULL if there is no next word.
311: */
312: char *
313: nextword(char *p)
314: {
315: /* skip blanks */
316: while (*p && *p != '\t' && *p != ' ')
317: p++;
318: if (*p) {
319: *p++ = '\0';
320: while (*p == '\t' || *p == ' ')
321: p++;
322: }
323: if (*p == '\0')
324: p = NULL;
325: return p;
326: }
327:
328: static void
329: print_help(const struct cmd_table *ct)
330: {
331: for (; ct->cmd_name != NULL; ct++)
332: printf(" %s", ct->cmd_name);
333: putchar('\n');
334: }
335:
336: static int
337: Xhelp(void)
338: {
339: printf("commands:");
340: print_help(cmd_table);
341: #ifdef MACHINE_CMD
342: return Xmachine();
343: #else
344: return 0;
345: #endif
346: }
347:
348: #ifdef MACHINE_CMD
349: static int
350: Xmachine(void)
351: {
352: printf("machine:");
353: print_help(MACHINE_CMD);
354: return 0;
355: }
356: #endif
357:
358: static int
359: Xclear(void)
360: {
361: int i;
362:
363: printf("\033[H\033[J");
364: return 0;
365: }
366:
367: static int
368: Xecho(void)
369: {
370: int i;
371:
372: for (i = 1; i < cmd.argc; i++)
373: printf("%s ", cmd.argv[i]);
374: putchar('\n');
375: return 0;
376: }
377:
378: static int
379: Xstty(void)
380: {
381: int sp;
382: char *cp;
383: dev_t dev;
384:
385: if (cmd.argc == 1) {
386: printf("%s speed is %d\n", ttyname(0), cnspeed(0, -1));
387: return 0;
388: }
389: dev = ttydev(cmd.argv[1]);
390: if (dev == NODEV) {
391: printf("%s not a console device\n", cmd.argv[1]);
392: return 0;
393: }
394:
395: if (cmd.argc == 2)
396: printf("%s speed is %d\n", cmd.argv[1],
397: cnspeed(dev, -1));
398: else {
399: sp = 0;
400: for (cp = cmd.argv[2]; isdigit(*cp); cp++)
401: sp = sp * 10 + (*cp - '0');
402: cnspeed(dev, sp);
403: }
404: return 0;
405: }
406:
407: static int
408: Xtime(void)
409: {
410: time_t tt = getsecs();
411:
412: if (cmd.argc == 1)
413: printf(ctime(&tt));
414:
415: return 0;
416: }
417:
418: static int
419: Xls(void)
420: {
421: struct stat sb;
422: char *p;
423: int fd;
424:
425: if (stat(qualify((cmd.argv[1]? cmd.argv[1]: "/.")), &sb) < 0) {
426: printf("stat(%s): %s\n", cmd.path, strerror(errno));
427: return 0;
428: }
429:
430: if ((sb.st_mode & S_IFMT) != S_IFDIR)
431: ls(cmd.path, &sb);
432: else {
433: if ((fd = opendir(cmd.path)) < 0) {
434: printf("opendir(%s): %s\n", cmd.path,
435: strerror(errno));
436: return 0;
437: }
438:
439: /* no strlen in lib !!! */
440: for (p = cmd.path; *p; p++)
441: ;
442: *p++ = '/';
443: *p = '\0';
444:
445: while (readdir(fd, p) >= 0) {
446: if (stat(cmd.path, &sb) < 0)
447: printf("stat(%s): %s\n", cmd.path,
448: strerror(errno));
449: else
450: ls(p, &sb);
451: }
452: closedir (fd);
453: }
454: return 0;
455: }
456:
457: #define lsrwx(mode,s) \
458: putchar ((mode) & S_IROTH? 'r' : '-'); \
459: putchar ((mode) & S_IWOTH? 'w' : '-'); \
460: putchar ((mode) & S_IXOTH? *(s): (s)[1]);
461:
462: static void
463: ls(char *name, struct stat *sb)
464: {
465: putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT) >> 12]);
466: lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID? "sS" : "x-"));
467: lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID? "sS" : "x-"));
468: lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT? "tT" : "x-"));
469:
470: printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid,
471: (u_long)sb->st_size, name);
472: }
473: #undef lsrwx
474:
475: int doboot = 1;
476:
477: static int
478: Xnop(void)
479: {
480: if (doboot) {
481: doboot = 0;
482: return (Xboot());
483: }
484:
485: return 0;
486: }
487:
488: static int
489: Xboot(void)
490: {
491: if (cmd.argc > 1 && cmd.argv[1][0] != '-') {
492: qualify((cmd.argv[1]? cmd.argv[1]: cmd.image));
493: if (bootparse(2))
494: return 0;
495: } else {
496: if (bootparse(1))
497: return 0;
498: snprintf(cmd.path, sizeof cmd.path, "%s:%s",
499: cmd.bootdev, cmd.image);
500: }
501:
502: return 1;
503: }
504:
505: /*
506: * Qualifies the path adding necessary dev
507: */
508:
509: static char *
510: qualify(char *name)
511: {
512: char *p;
513:
514: for (p = name; *p; p++)
515: if (*p == ':')
516: break;
517: if (*p == ':')
518: strlcpy(cmd.path, name, sizeof(cmd.path));
519: else
520: snprintf(cmd.path, sizeof cmd.path, "%s:%s",
521: cmd.bootdev, name);
522: return cmd.path;
523: }
524:
525: static int
526: Xreboot(void)
527: {
528: printf("Rebooting...\n");
529: exit();
530: return 0; /* just in case */
531: }
532:
CVSweb