File: | src/sbin/scsi/scsi.c |
Warning: | line 776, column 3 Value stored to 'mode_pars' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: scsi.c,v 1.31 2021/06/22 14:51:29 jmc Exp $ */ |
2 | /* $FreeBSD: scsi.c,v 1.11 1996/04/06 11:00:28 joerg Exp $ */ |
3 | |
4 | /* |
5 | * Written By Julian ELischer |
6 | * Copyright julian Elischer 1993. |
7 | * Permission is granted to use or redistribute this file in any way as long |
8 | * as this notice remains. Julian Elischer does not guarantee that this file |
9 | * is totally correct for any given task and users of this file must |
10 | * accept responsibility for any damage that occurs from the application of this |
11 | * file. |
12 | * |
13 | * (julian@tfs.com julian@dialix.oz.au) |
14 | * |
15 | * User SCSI hooks added by Peter Dufault: |
16 | * |
17 | * Copyright (c) 1994 HD Associates |
18 | * (contact: dufault@hda.com) |
19 | * All rights reserved. |
20 | * |
21 | * Redistribution and use in source and binary forms, with or without |
22 | * modification, are permitted provided that the following conditions |
23 | * are met: |
24 | * 1. Redistributions of source code must retain the above copyright |
25 | * notice, this list of conditions and the following disclaimer. |
26 | * 2. Redistributions in binary form must reproduce the above copyright |
27 | * notice, this list of conditions and the following disclaimer in the |
28 | * documentation and/or other materials provided with the distribution. |
29 | * 3. The name of HD Associates |
30 | * may not be used to endorse or promote products derived from this software |
31 | * without specific prior written permission. |
32 | * |
33 | * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES ``AS IS'' AND |
34 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
36 | * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES BE LIABLE |
37 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
38 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
39 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
40 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
41 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
42 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
43 | * SUCH DAMAGE. |
44 | */ |
45 | |
46 | #include <sys/types.h> |
47 | #include <sys/wait.h> |
48 | |
49 | #include <fcntl.h> |
50 | #include <stdio.h> |
51 | #include <string.h> |
52 | #include <stdlib.h> |
53 | #include <unistd.h> |
54 | #include <errno(*__errno()).h> |
55 | #include <sys/scsiio.h> |
56 | #include <ctype.h> |
57 | #include <signal.h> |
58 | #include <err.h> |
59 | #include <paths.h> |
60 | |
61 | #include "libscsi.h" |
62 | |
63 | int fd; |
64 | int debuglevel; |
65 | int debugflag; |
66 | int commandflag; |
67 | int verbose = 0; |
68 | |
69 | int modeflag; |
70 | int editflag; |
71 | int modepage = 0; /* Read this mode page */ |
72 | int pagectl = 0; /* Mode sense page control */ |
73 | int seconds = 2; |
74 | |
75 | void procargs(int *argc_p, char ***argv_p); |
76 | int iget(void *hook, char *name); |
77 | char *cget(void *hook, char *name); |
78 | void arg_put(void *hook, int letter, void *arg, int count, char *name); |
79 | void mode_sense(int fd, u_char *data, int len, int pc, int page); |
80 | void mode_select(int fd, u_char *data, int len, int perm); |
81 | int editit(const char *pathname); |
82 | |
83 | static void |
84 | usage(void) |
85 | { |
86 | fprintf(stderr(&__sF[2]), |
87 | "usage: scsi -f device -d debug_level\n" |
88 | " scsi -f device -m page [-e] [-P pc]\n" |
89 | " scsi -f device [-v] [-s seconds] -c cmd_fmt [arg ...]" |
90 | " -o count out_fmt\n" |
91 | " [arg ...] -i count in_fmt [arg ...]\n"); |
92 | |
93 | exit (1); |
94 | } |
95 | |
96 | void |
97 | procargs(int *argc_p, char ***argv_p) |
98 | { |
99 | int argc = *argc_p; |
100 | char **argv = *argv_p; |
101 | int fflag, ch; |
102 | |
103 | fflag = 0; |
104 | commandflag = 0; |
105 | debugflag = 0; |
106 | while ((ch = getopt(argc, argv, "cef:d:m:P:s:v")) != -1) { |
107 | switch (ch) { |
108 | case 'c': |
109 | commandflag = 1; |
110 | break; |
111 | case 'e': |
112 | editflag = 1; |
113 | break; |
114 | case 'f': |
115 | if ((fd = scsi_open(optarg, O_RDWR0x0002)) < 0) |
116 | err(1, "unable to open device %s", optarg); |
117 | fflag = 1; |
118 | break; |
119 | case 'd': |
120 | debuglevel = strtol(optarg, 0, 0); |
121 | debugflag = 1; |
122 | break; |
123 | case 'm': |
124 | modeflag = 1; |
125 | modepage = strtol(optarg, 0, 0); |
126 | break; |
127 | case 'P': |
128 | pagectl = strtol(optarg, 0, 0); |
129 | break; |
130 | case 's': |
131 | seconds = strtol(optarg, 0, 0); |
132 | break; |
133 | case 'v': |
134 | verbose = 1; |
135 | break; |
136 | case '?': |
137 | default: |
138 | usage(); |
139 | } |
140 | } |
141 | *argc_p = argc - optind; |
142 | *argv_p = argv + optind; |
143 | |
144 | if (!fflag) usage(); |
145 | } |
146 | |
147 | /* get_hook: Structure for evaluating args in a callback. |
148 | */ |
149 | struct get_hook |
150 | { |
151 | int argc; |
152 | char **argv; |
153 | int got; |
154 | }; |
155 | |
156 | /* iget: Integer argument callback |
157 | */ |
158 | int |
159 | iget(void *hook, char *name) |
160 | { |
161 | struct get_hook *h = (struct get_hook *)hook; |
162 | int arg; |
163 | |
164 | if (h->got >= h->argc) |
165 | { |
166 | fprintf(stderr(&__sF[2]), "Expecting an integer argument.\n"); |
167 | usage(); |
168 | } |
169 | arg = strtol(h->argv[h->got], 0, 0); |
170 | h->got++; |
171 | |
172 | if (verbose && name && *name) |
173 | printf("%s: %d\n", name, arg); |
174 | |
175 | return arg; |
176 | } |
177 | |
178 | /* cget: char * argument callback |
179 | */ |
180 | char * |
181 | cget(void *hook, char *name) |
182 | { |
183 | struct get_hook *h = (struct get_hook *)hook; |
184 | char *arg; |
185 | |
186 | if (h->got >= h->argc) |
187 | { |
188 | fprintf(stderr(&__sF[2]), "Expecting a character pointer argument.\n"); |
189 | usage(); |
190 | } |
191 | arg = h->argv[h->got]; |
192 | h->got++; |
193 | |
194 | if (verbose && name) |
195 | printf("cget: %s: %s", name, arg); |
196 | |
197 | return arg; |
198 | } |
199 | |
200 | /* arg_put: "put argument" callback |
201 | */ |
202 | void arg_put(void *hook, int letter, void *arg, int count, char *name) |
203 | { |
204 | if (verbose && name && *name) |
205 | printf("%s: ", name); |
206 | |
207 | switch(letter) |
208 | { |
209 | case 'i': |
210 | case 'b': |
211 | printf("%ld ", (long)arg); |
212 | break; |
213 | |
214 | case 'c': |
215 | case 'z': |
216 | { |
217 | char *p = malloc(count + 1); |
218 | if (p == NULL((void *)0)) |
219 | err(1, NULL((void *)0)); |
220 | |
221 | p[count] = 0; |
222 | strncpy(p, (char *)arg, count); |
223 | if (letter == 'z') |
224 | { |
225 | int i; |
226 | for (i = count - 1; i >= 0; i--) |
227 | if (p[i] == ' ') |
228 | p[i] = 0; |
229 | else |
230 | break; |
231 | } |
232 | printf("%s ", p); |
233 | free(p); |
234 | } |
235 | |
236 | break; |
237 | |
238 | default: |
239 | printf("Unknown format letter: '%c'\n", letter); |
240 | } |
241 | if (verbose) |
242 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); |
243 | } |
244 | |
245 | /* data_phase: SCSI bus data phase: DATA IN, DATA OUT, or no data transfer. |
246 | */ |
247 | enum data_phase {none = 0, in, out}; |
248 | |
249 | /* do_cmd: Send a command to a SCSI device |
250 | */ |
251 | static void |
252 | do_cmd(int fd, char *fmt, int argc, char **argv) |
253 | { |
254 | struct get_hook h; |
255 | scsireq_t *scsireq = scsireq_new(); |
256 | enum data_phase data_phase; |
257 | int count, amount; |
258 | char *data_fmt, *bp; |
259 | |
260 | h.argc = argc; |
261 | h.argv = argv; |
262 | h.got = 0; |
263 | |
264 | scsireq_reset(scsireq); |
265 | |
266 | scsireq_build_visit(scsireq, 0, 0, 0, fmt, iget, (void *)&h); |
267 | |
268 | /* Three choices here: |
269 | * 1. We've used up all the args and have no data phase. |
270 | * 2. We have input data ("-i") |
271 | * 3. We have output data ("-o") |
272 | */ |
273 | |
274 | if (h.got >= h.argc) |
275 | { |
276 | data_phase = none; |
277 | count = scsireq->datalen = 0; |
278 | } |
279 | else |
280 | { |
281 | char *flag = cget(&h, 0); |
282 | |
283 | if (strcmp(flag, "-o") == 0) |
284 | { |
285 | data_phase = out; |
286 | scsireq->flags = SCCMD_WRITE0x00000002; |
287 | } |
288 | else if (strcmp(flag, "-i") == 0) |
289 | { |
290 | data_phase = in; |
291 | scsireq->flags = SCCMD_READ0x00000001; |
292 | } |
293 | else |
294 | { |
295 | fprintf(stderr(&__sF[2]), |
296 | "Need either \"-i\" or \"-o\" for data phase; not \"%s\".\n", flag); |
297 | usage(); |
298 | } |
299 | |
300 | count = scsireq->datalen = iget(&h, 0); |
301 | if (count) { |
302 | data_fmt = cget(&h, 0); |
303 | |
304 | scsireq->databuf = malloc(count); |
305 | if (scsireq->databuf == NULL((void *)0)) |
306 | err(1, NULL((void *)0)); |
307 | |
308 | if (data_phase == out) { |
309 | if (strcmp(data_fmt, "-") == 0) { |
310 | bp = (char *)scsireq->databuf; |
311 | while (count > 0 && |
312 | (amount = read(STDIN_FILENO0, |
313 | bp, count)) > 0) { |
314 | count -= amount; |
315 | bp += amount; |
316 | } |
317 | if (amount == -1) |
318 | err(1, "read"); |
319 | else if (amount == 0) { |
320 | /* early EOF */ |
321 | fprintf(stderr(&__sF[2]), |
322 | "Warning: only read %lu bytes out of %lu.\n", |
323 | scsireq->datalen - (u_long)count, |
324 | scsireq->datalen); |
325 | scsireq->datalen -= (u_long)count; |
326 | } |
327 | } |
328 | else |
329 | { |
330 | bzero(scsireq->databuf, count); |
331 | scsireq_encode_visit(scsireq, data_fmt, iget, (void *)&h); |
332 | } |
333 | } |
334 | } |
335 | } |
336 | |
337 | |
338 | scsireq->timeout = seconds * 1000; |
339 | |
340 | if (scsireq_enter(fd, scsireq) == -1) |
341 | { |
342 | scsi_debug(stderr(&__sF[2]), -1, scsireq); |
343 | exit(1); |
344 | } |
345 | |
346 | if (SCSIREQ_ERROR(scsireq)(scsireq->senselen_used || scsireq->status || scsireq-> retsts || scsireq->error)) |
347 | scsi_debug(stderr(&__sF[2]), 0, scsireq); |
348 | |
349 | if (count && data_phase == in) |
350 | { |
351 | if (strcmp(data_fmt, "-") == 0) /* stdout */ |
352 | { |
353 | bp = (char *)scsireq->databuf; |
354 | while (count > 0 && (amount = write(STDOUT_FILENO1, bp, count)) > 0) |
355 | { |
356 | count -= amount; |
357 | bp += amount; |
358 | } |
359 | if (amount < 0) |
360 | err(1, "write"); |
361 | else if (amount == 0) |
362 | fprintf(stderr(&__sF[2]), "Warning: wrote only %lu bytes out of %lu.\n", |
363 | scsireq->datalen - count, |
364 | scsireq->datalen); |
365 | |
366 | } |
367 | else |
368 | { |
369 | scsireq_decode_visit(scsireq, data_fmt, arg_put, 0); |
370 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); |
371 | } |
372 | } |
373 | } |
374 | |
375 | void mode_sense(int fd, u_char *data, int len, int pc, int page) |
376 | { |
377 | scsireq_t *scsireq; |
378 | |
379 | bzero(data, len); |
380 | |
381 | scsireq = scsireq_new(); |
382 | |
383 | if (scsireq_enter(fd, scsireq_build(scsireq, |
384 | len, data, SCCMD_READ0x00000001, |
385 | "1A 0 v:2 {Page Control} v:6 {Page Code} 0 v:i1 {Allocation Length} 0", |
386 | pc, page, len)) == -1) /* Mode sense */ |
387 | { |
388 | scsi_debug(stderr(&__sF[2]), -1, scsireq); |
389 | exit(1); |
390 | } |
391 | |
392 | if (SCSIREQ_ERROR(scsireq)(scsireq->senselen_used || scsireq->status || scsireq-> retsts || scsireq->error)) |
393 | { |
394 | scsi_debug(stderr(&__sF[2]), 0, scsireq); |
395 | exit(1); |
396 | } |
397 | |
398 | free(scsireq); |
399 | } |
400 | |
401 | void mode_select(int fd, u_char *data, int len, int perm) |
402 | { |
403 | scsireq_t *scsireq; |
404 | |
405 | scsireq = scsireq_new(); |
406 | |
407 | if (scsireq_enter(fd, scsireq_build(scsireq, |
408 | len, data, SCCMD_WRITE0x00000002, |
409 | "15 0:7 v:1 {SP} 0 0 v:i1 {Allocation Length} 0", perm, len)) == -1) /* Mode select */ |
410 | { |
411 | scsi_debug(stderr(&__sF[2]), -1, scsireq); |
412 | exit(1); |
413 | } |
414 | |
415 | if (SCSIREQ_ERROR(scsireq)(scsireq->senselen_used || scsireq->status || scsireq-> retsts || scsireq->error)) |
416 | { |
417 | scsi_debug(stderr(&__sF[2]), 0, scsireq); |
418 | exit(1); |
419 | } |
420 | |
421 | free(scsireq); |
422 | } |
423 | |
424 | |
425 | #define START_ENTRY'{' '{' |
426 | #define END_ENTRY'}' '}' |
427 | |
428 | static void |
429 | skipwhite(FILE *f) |
430 | { |
431 | int c; |
432 | |
433 | skip_again: |
434 | |
435 | while (isspace(c = getc(f)(!__isthreaded ? (--(f)->_r < 0 ? __srget(f) : (int)(*( f)->_p++)) : (getc)(f)))) |
436 | continue; |
437 | |
438 | if (c == '#') { |
439 | while ((c = getc(f)(!__isthreaded ? (--(f)->_r < 0 ? __srget(f) : (int)(*( f)->_p++)) : (getc)(f))) != '\n' && c != EOF(-1)) |
440 | continue; |
441 | goto skip_again; |
442 | } |
443 | |
444 | ungetc(c, f); |
445 | } |
446 | |
447 | /* mode_lookup: Lookup a format description for a given page. |
448 | */ |
449 | char *mode_db = "/usr/share/misc/scsi_modes"; |
450 | static char *mode_lookup(int page) |
451 | { |
452 | char *new_db; |
453 | FILE *modes; |
454 | int match, next, found, c; |
455 | static char fmt[1024]; /* XXX This should be with strealloc */ |
456 | int page_desc; |
457 | new_db = getenv("SCSI_MODES"); |
458 | |
459 | if (new_db) |
460 | mode_db = new_db; |
461 | |
462 | modes = fopen(mode_db, "r"); |
463 | if (modes == NULL((void *)0)) |
464 | return 0; |
465 | |
466 | next = 0; |
467 | found = 0; |
468 | |
469 | while (!found) { |
470 | |
471 | skipwhite(modes); |
472 | |
473 | if (fscanf(modes, "%i", &page_desc) != 1) |
474 | break; |
475 | |
476 | if (page_desc == page) |
477 | found = 1; |
478 | |
479 | skipwhite(modes); |
480 | if (getc(modes)(!__isthreaded ? (--(modes)->_r < 0 ? __srget(modes) : ( int)(*(modes)->_p++)) : (getc)(modes)) != START_ENTRY'{') { |
481 | errx(1, "Expected %c", START_ENTRY'{'); |
482 | } |
483 | |
484 | match = 1; |
485 | while (match != 0) { |
486 | c = getc(modes)(!__isthreaded ? (--(modes)->_r < 0 ? __srget(modes) : ( int)(*(modes)->_p++)) : (getc)(modes)); |
487 | if (c == EOF(-1)) |
488 | fprintf(stderr(&__sF[2]), "Expected %c.\n", END_ENTRY'}'); |
489 | |
490 | if (c == START_ENTRY'{') { |
491 | match++; |
492 | } |
493 | if (c == END_ENTRY'}') { |
494 | match--; |
495 | if (match == 0) |
496 | break; |
497 | } |
498 | if (found && c != '\n') { |
499 | if (next >= sizeof(fmt)) { |
500 | errx(1, "Stupid program: Buffer overflow.\n"); |
501 | } |
502 | |
503 | fmt[next++] = (u_char)c; |
504 | } |
505 | } |
506 | } |
507 | fclose(modes); |
508 | fmt[next] = 0; |
509 | |
510 | return (found) ? fmt : 0; |
511 | } |
512 | |
513 | /* -------- edit: Mode Select Editor --------- |
514 | */ |
515 | struct editinfo |
516 | { |
517 | long can_edit; |
518 | long default_value; |
519 | } editinfo[64]; /* XXX Bogus fixed size */ |
520 | |
521 | static int editind; |
522 | volatile int edit_opened; |
523 | static FILE *edit_file; |
524 | static char edit_name[L_tmpnam1024]; |
525 | |
526 | static void |
527 | edit_rewind(void) |
528 | { |
529 | editind = 0; |
530 | } |
531 | |
532 | static void |
533 | edit_done(void) |
534 | { |
535 | int opened; |
536 | |
537 | sigset_t all, prev; |
538 | sigfillset(&all); |
539 | |
540 | (void)sigprocmask(SIG_SETMASK3, &all, &prev); |
541 | |
542 | opened = (int)edit_opened; |
543 | edit_opened = 0; |
544 | |
545 | (void)sigprocmask(SIG_SETMASK3, &prev, 0); |
546 | |
547 | if (opened) |
548 | { |
549 | if (fclose(edit_file)) |
550 | perror(edit_name); |
551 | if (unlink(edit_name)) |
552 | perror(edit_name); |
553 | } |
554 | } |
555 | |
556 | static void |
557 | edit_init(void) |
558 | { |
559 | int fd; |
560 | |
561 | edit_rewind(); |
562 | strlcpy(edit_name, "/var/tmp/scXXXXXXXX", sizeof edit_name); |
563 | if ((fd = mkstemp(edit_name)) == -1) |
564 | err(1, "mkstemp"); |
565 | if ( (edit_file = fdopen(fd, "w+")) == 0) |
566 | err(1, "fdopen"); |
567 | edit_opened = 1; |
568 | |
569 | atexit(edit_done); |
570 | } |
571 | |
572 | static void |
573 | edit_check(void *hook, int letter, void *arg, int count, char *name) |
574 | { |
575 | if (letter != 'i' && letter != 'b') { |
576 | errx(1, "Can't edit format %c.\n", letter); |
577 | } |
578 | |
579 | if (editind >= sizeof(editinfo) / sizeof(editinfo[0])) { |
580 | errx(1, "edit table overflow"); |
581 | } |
582 | editinfo[editind].can_edit = ((long)arg != 0); |
583 | editind++; |
584 | } |
585 | |
586 | static void |
587 | edit_defaults(void *hook, int letter, void *arg, int count, char *name) |
588 | { |
589 | if (letter != 'i' && letter != 'b') { |
590 | errx(1, "Can't edit format %c.\n", letter); |
591 | } |
592 | |
593 | editinfo[editind].default_value = ((long)arg); |
594 | editind++; |
595 | } |
596 | |
597 | static void |
598 | edit_report(void *hook, int letter, void *arg, int count, char *name) |
599 | { |
600 | if (editinfo[editind].can_edit) { |
601 | if (letter != 'i' && letter != 'b') { |
602 | errx(1, "Can't report format %c.\n", letter); |
603 | } |
604 | |
605 | fprintf(edit_file, "%s: %ld\n", name, (long)arg); |
606 | } |
607 | |
608 | editind++; |
609 | } |
610 | |
611 | static int |
612 | edit_get(void *hook, char *name) |
613 | { |
614 | int arg = editinfo[editind].default_value; |
615 | |
616 | if (editinfo[editind].can_edit) { |
617 | char line[80]; |
618 | size_t len; |
619 | if (fgets(line, sizeof(line), edit_file) == NULL((void *)0)) |
620 | err(1, "fgets"); |
621 | |
622 | len = strlen(line); |
623 | if (len && line[len - 1] == '\n') |
624 | line[len - 1] = '\0'; |
625 | |
626 | if (strncmp(name, line, strlen(name)) != 0) { |
627 | errx(1, "Expected \"%s\" and read \"%s\"\n", |
628 | name, line); |
629 | } |
630 | |
631 | arg = strtoul(line + strlen(name) + 2, 0, 0); |
632 | } |
633 | |
634 | editind++; |
635 | return arg; |
636 | } |
637 | |
638 | int |
639 | editit(const char *pathname) |
640 | { |
641 | char *argp[] = {"sh", "-c", NULL((void *)0), NULL((void *)0)}, *ed, *p; |
642 | sig_t sighup, sigint, sigquit; |
643 | pid_t pid; |
644 | int st; |
645 | |
646 | ed = getenv("VISUAL"); |
647 | if (ed == NULL((void *)0) || ed[0] == '\0') |
648 | ed = getenv("EDITOR"); |
649 | if (ed == NULL((void *)0) || ed[0] == '\0') |
650 | ed = _PATH_VI"/usr/bin/vi"; |
651 | if (asprintf(&p, "%s %s", ed, pathname) == -1) |
652 | return (-1); |
653 | argp[2] = p; |
654 | |
655 | top: |
656 | sighup = signal(SIGHUP1, SIG_IGN(void (*)(int))1); |
657 | sigint = signal(SIGINT2, SIG_IGN(void (*)(int))1); |
658 | sigquit = signal(SIGQUIT3, SIG_IGN(void (*)(int))1); |
659 | if ((pid = fork()) == -1) { |
660 | int saved_errno = errno(*__errno()); |
661 | |
662 | (void)signal(SIGHUP1, sighup); |
663 | (void)signal(SIGINT2, sigint); |
664 | (void)signal(SIGQUIT3, sigquit); |
665 | if (saved_errno == EAGAIN35) { |
666 | sleep(1); |
667 | goto top; |
668 | } |
669 | free(p); |
670 | errno(*__errno()) = saved_errno; |
671 | return (-1); |
672 | } |
673 | if (pid == 0) { |
674 | execv(_PATH_BSHELL"/bin/sh", argp); |
675 | _exit(127); |
676 | } |
677 | free(p); |
678 | for (;;) { |
679 | if (waitpid(pid, &st, 0) == -1) { |
680 | if (errno(*__errno()) != EINTR4) |
681 | return (-1); |
682 | } else |
683 | break; |
684 | } |
685 | (void)signal(SIGHUP1, sighup); |
686 | (void)signal(SIGINT2, sigint); |
687 | (void)signal(SIGQUIT3, sigquit); |
688 | if (!WIFEXITED(st)(((st) & 0177) == 0) || WEXITSTATUS(st)(int)(((unsigned)(st) >> 8) & 0xff) != 0) { |
689 | errno(*__errno()) = ECHILD10; |
690 | return (-1); |
691 | } |
692 | return (0); |
693 | } |
694 | |
695 | static void |
696 | mode_edit(int fd, int page, int edit, int argc, char *argv[]) |
697 | { |
698 | int i; |
699 | u_char data[255]; |
700 | u_char *mode_pars; |
701 | struct mode_header |
702 | { |
703 | u_char mdl; /* Mode data length */ |
704 | u_char medium_type; |
705 | u_char dev_spec_par; |
706 | u_char bdl; /* Block descriptor length */ |
707 | }; |
708 | |
709 | struct mode_page_header |
710 | { |
711 | u_char page_code; |
712 | u_char page_length; |
713 | }; |
714 | |
715 | struct mode_header *mh; |
716 | struct mode_page_header *mph; |
717 | |
718 | char *fmt = mode_lookup(page); |
719 | if (!fmt && verbose) { |
720 | fprintf(stderr(&__sF[2]), |
721 | "No mode data base entry in \"%s\" for page %d; binary %s only.\n", |
722 | mode_db, page, (edit ? "edit" : "display")); |
723 | } |
724 | |
725 | if (edit) { |
726 | if (!fmt) { |
727 | errx(1, "Sorry: can't edit without a format.\n"); |
728 | } |
729 | |
730 | if (pagectl != 0 && pagectl != 3) { |
731 | errx(1, |
732 | "It only makes sense to edit page 0 (current) or page 3 (saved values)\n"); |
733 | } |
734 | |
735 | verbose = 1; |
736 | |
737 | mode_sense(fd, data, sizeof(data), 1, page); |
738 | |
739 | mh = (struct mode_header *)data; |
740 | mph = (struct mode_page_header *) |
741 | (((char *)mh) + sizeof(*mh) + mh->bdl); |
742 | |
743 | mode_pars = (char *)mph + sizeof(*mph); |
744 | |
745 | edit_init(); |
746 | scsireq_buff_decode_visit(mode_pars, mh->mdl, |
747 | fmt, edit_check, 0); |
748 | |
749 | mode_sense(fd, data, sizeof(data), 0, page); |
750 | |
751 | edit_rewind(); |
752 | scsireq_buff_decode_visit(mode_pars, mh->mdl, |
753 | fmt, edit_defaults, 0); |
754 | |
755 | edit_rewind(); |
756 | scsireq_buff_decode_visit(mode_pars, mh->mdl, |
757 | fmt, edit_report, 0); |
758 | |
759 | fclose(edit_file); |
760 | if (editit(edit_name) == -1 && errno(*__errno()) != ECHILD10) |
761 | err(1, "edit %s", edit_name); |
762 | if ((edit_file = fopen(edit_name, "r")) == NULL((void *)0)) |
763 | err(1, "open %s", edit_name); |
764 | |
765 | edit_rewind(); |
766 | scsireq_buff_encode_visit(mode_pars, mh->mdl, |
767 | fmt, edit_get, 0); |
768 | |
769 | /* Eliminate block descriptors: |
770 | */ |
771 | bcopy((char *)mph, ((char *)mh) + sizeof(*mh), |
772 | sizeof(*mph) + mph->page_length); |
773 | |
774 | mh->bdl = 0; |
775 | mph = (struct mode_page_header *) (((char *)mh) + sizeof(*mh)); |
776 | mode_pars = ((char *)mph) + 2; |
Value stored to 'mode_pars' is never read | |
777 | |
778 | #if 0 |
779 | /* Turn this on to see what you're sending to the |
780 | * device: |
781 | */ |
782 | edit_rewind(); |
783 | scsireq_buff_decode_visit(mode_pars, |
784 | mh->mdl, fmt, arg_put, 0); |
785 | #endif |
786 | |
787 | edit_done(); |
788 | |
789 | /* Make it permanent if pageselect is three. |
790 | */ |
791 | |
792 | mph->page_code &= ~0xC0; /* Clear PS and RESERVED */ |
793 | mh->mdl = 0; /* Reserved for mode select */ |
794 | |
795 | mode_select(fd, (char *)mh, |
796 | sizeof(*mh) + mh->bdl + sizeof(*mph) + mph->page_length, |
797 | (pagectl == 3)); |
798 | |
799 | exit(0); |
800 | } |
801 | |
802 | mode_sense(fd, data, sizeof(data), pagectl, page); |
803 | |
804 | /* Skip over the block descriptors. |
805 | */ |
806 | mh = (struct mode_header *)data; |
807 | mph = (struct mode_page_header *)(((char *)mh) + sizeof(*mh) + mh->bdl); |
808 | mode_pars = (char *)mph + sizeof(*mph); |
809 | |
810 | if (!fmt) { |
811 | for (i = 0; i < mh->mdl; i++) { |
812 | printf("%02x%c",mode_pars[i], |
813 | (((i + 1) % 8) == 0) ? '\n' : ' '); |
814 | } |
815 | putc('\n', stdout)(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); |
816 | } else { |
817 | verbose = 1; |
818 | scsireq_buff_decode_visit(mode_pars, |
819 | mh->mdl, fmt, arg_put, 0); |
820 | } |
821 | } |
822 | |
823 | int |
824 | main(int argc, char **argv) |
825 | { |
826 | procargs(&argc,&argv); |
827 | |
828 | /* XXX This has grown to the point that it should be cleaned up. |
829 | */ |
830 | if (debugflag) { |
831 | if (ioctl(fd,SCIOCDEBUG((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('Q')) << 8) | ((2))),&debuglevel) == -1) |
832 | err(1, "SCIOCDEBUG"); |
833 | } else if (commandflag) { |
834 | char *fmt; |
835 | |
836 | if (argc < 1) { |
837 | fprintf(stderr(&__sF[2]), "Need the command format string.\n"); |
838 | usage(); |
839 | } |
840 | |
841 | |
842 | fmt = argv[0]; |
843 | |
844 | argc -= 1; |
845 | argv += 1; |
846 | |
847 | do_cmd(fd, fmt, argc, argv); |
848 | } else if (modeflag) |
849 | mode_edit(fd, modepage, editflag, argc, argv); |
850 | |
851 | exit(0); |
852 | } |