3 * Author: Christian Borntraeger <cborntra@de.ibm.com>
5 * Copyright IBM Corp. 2005, 2006.
7 * Tool for accessing the control program of z/VM using the
10 * 0: everything was fine (VMCP_OK)
11 * 1: CP returned a nn zero response code (VMCP_CP)
12 * 2: the response buffer was not large enough (VMCP_BUF)
13 * 3: an internal Linux error occured (VMCP_LIN)
14 * 4: invalid options (VMCP_OPT)
16 * CREDITS: The idea is based on cpint of Neale Fergusson
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
32 static int keep_case
= 0;
33 static int buffersize
= 8192;
34 static char command
[MAXCMDLEN
+ 1];
36 static void print_help(const char *name
)
38 printf("%s: z/VM CP command interface.\n%s", name
, help_text
);
41 static void print_version(const char *name
)
43 printf("%s: z/VM CP command interface version %s\n"
44 "Copyright IBM Corp. 2005, 2006\n",
45 name
, RELEASE_STRING
);
48 static void uppercase(char *string
)
50 while (*string
!= '\0') {
51 *string
= toupper(*string
);
56 /* Parse STRING for buffer size in bytes, allowing size modifier suffix 'k' and
57 * 'm'. Return buffer size in bytes on success, -1 on error. */
58 static long parse_buffersize(char *string
)
63 bytes
= strtol(string
, &suffix
, 10);
64 if (strlen(suffix
) > 1)
80 if ((bytes
< MINBUFFER
) || (bytes
> MAXBUFFER
))
85 /* Parse tool parameters. Fill in global variables keep_case, buffersize and
86 * command according to parameters. Return VMCP_OK on success, VMCP_OPT
87 * in case of parameter errors. In case of --help or --version, print
88 * respective text to stdout and exit. */
89 static int parse_args(int argc
, char **argv
)
95 opt
= getopt_long(argc
, argv
, opt_string
, options
, NULL
);
98 /* Reached end of parameter list. */
104 print_version(argv
[0]);
110 buffersize
= (int) parse_buffersize(optarg
);
111 if (buffersize
== -1) {
112 fprintf(stderr
, "Error: Invalid buffersize "
113 "(needs to be between %d and %d)\n",
114 MINBUFFER
, MAXBUFFER
);
119 fprintf(stderr
, "Try 'vmcp --help' for more"
124 /* Merge remaining argv contents into command string. */
125 for (index
= optind
; index
< argc
; index
++) {
126 if (strlen(command
) + (strlen(command
) == 0 ? 0 : 1) +
127 strlen(argv
[index
]) > MAXCMDLEN
) {
128 fprintf(stderr
, "Error: Command too long (cannot be "
129 "longer than %d characters)\n", MAXCMDLEN
);
132 if (strlen(command
) > 0)
133 strcat(command
, " ");
134 strcat(command
, argv
[index
]);
136 if (strlen(command
) == 0) {
143 static inline void linux_error(const char *message
)
145 fprintf(stderr
, "Error: %s: %s\n", message
, strerror(errno
));
148 /* Read at most COUNT bytes from FD into memory at location BUF. Return
149 * number of bytes read on success, -1 on error. */
150 static ssize_t
read_buffer(int fd
, char *buf
, size_t count
)
155 for (done
= 0; done
< (ssize_t
) count
; done
+= ret
) {
156 ret
= read(fd
, &buf
[done
], count
- done
);
157 if (ret
== -1 && errno
== EINTR
)
167 /* Write COUNT bytes to FD from memory at location BUF. Return number of bytes
168 * written on success, -1 otherwise. */
169 static ssize_t
write_buffer(int fd
, const char *buf
, size_t count
)
174 for (done
= 0; done
< (ssize_t
) count
; done
+= ret
) {
175 ret
= write(fd
, &buf
[done
], count
- done
);
176 if (ret
== -1 && errno
== EINTR
)
186 int main(int argc
, char **argv
)
194 ret
= parse_args(argc
, argv
);
201 buffer
= malloc(buffersize
);
203 linux_error("Could not allocate return buffer");
206 fd
= open(DEVICE_NODE
, O_RDWR
);
208 linux_error("Could not open device " DEVICE_NODE
);
212 if (ioctl(fd
, VMCP_SETBUF
, &buffersize
) == -1) {
213 linux_error("Could not set buffer size");
218 if (write(fd
, command
, strlen(command
)) == -1) {
219 linux_error("Could not issue CP command");
224 if (ioctl(fd
, VMCP_GETCODE
, &response_code
) == -1) {
225 linux_error("Could not query return code");
230 if (ioctl(fd
, VMCP_GETSIZE
, &response_size
) == -1) {
231 linux_error("Could not query response size");
236 ret
= read_buffer(fd
, buffer
, buffersize
);
238 linux_error("Could not read CP response");
243 write_buffer(STDOUT_FILENO
, buffer
, ret
);
244 if (response_size
> buffersize
) {
245 fprintf(stderr
, "Error: output (%d bytes) was truncated, try "
246 "--buffer to increase size\n", response_size
);
251 if (response_code
> 0) {
252 fprintf(stderr
, "Error: non-zero CP response for command '%s': "
253 "#%d\n", command
, response_code
);