1 /* This file is part of Eclat.
2    Copyright (C) 2012-2018 Sergey Poznyakoff.
3 
4    Eclat is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    Eclat is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Eclat.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include "eclat.h"
18 
19 static char *attrs[] = {
20 	"InstanceType.Value",
21 	"Kernel.Value",
22 	"Ramdisk.Value",
23 	"UserData.Value",
24 	"DisableApiTermination.Value",
25 	"InstanceInitiatedShutdownBehavior.Value",
26 	"BlockDeviceMapping.ebs",
27 	"SourceDestCheck.Value",
28 	"GroupId.%d",
29 	"EbsOptimized",
30 	NULL
31 };
32 
33 static void
list_mod_attrs(FILE * fp)34 list_mod_attrs(FILE *fp)
35 {
36 	size_t ncols = get_scr_cols();
37 	int i, col, len, alen;
38 	char *delim = "";
39 
40 	fprintf(fp, "Available attributes are:\n");
41 	col = 0;
42 	for (i = 0; attrs[i]; i++) {
43 		alen = strcspn(attrs[i], ".");
44 		len = strlen(delim) + alen;
45 		if (col + len > ncols) {
46 			fprintf(fp, ",\n%*.*s", alen, alen, attrs[i]);
47 			col = strlen(attrs[i]);
48 		} else
49 			col += fprintf(fp, "%s%*.*s", delim,
50 				       alen, alen, attrs[i]);
51 		delim = ", ";
52 	}
53 	fputc('\n', fp);
54 	fputc('\n', fp);
55 }
56 
57 int from_file;
58 int is_base64;
59 #include "setiattr-cl.h"
60 
61 int
eclat_modify_instance_attribute(eclat_command_env_t * env,int argc,char ** argv)62 eclat_modify_instance_attribute(eclat_command_env_t *env, int argc, char **argv)
63 {
64 	int i;
65 	struct ec2_request *q = env->request;
66 	const char *canonattr;
67 	size_t canonlen;
68 	char *bufptr = NULL;
69 	size_t bufsize = 0;
70 
71 	parse_options(env, argc, argv, &i);
72         argv += i;
73         argc -= i;
74 
75 	if (argc < 3)
76 		die(EX_USAGE, "wrong number of arguments");
77 
78 	translate_ids(1, argv, MAP_INSTANCE);
79 	eclat_request_add_param(q, "InstanceId", argv[0]);
80 
81 	canonattr = canonattrname(attrs, argv[1], ".", &canonlen);
82 	if (!canonattr)
83 		die(EX_USAGE, "unrecognized attribute: %s", argv[1]);
84 
85 	if (canonattr[canonlen] == '.' &&
86 	    strcmp(canonattr+canonlen+1, "%d") == 0) {
87 		for (i = 2; i < argc; i++) {
88 			grecs_asprintf(&bufptr, &bufsize, canonattr, i - 1);
89 			eclat_request_add_param(q, bufptr, argv[i]);
90 		}
91 	} else if (canonattr[canonlen] == '.' &&
92 	    strcmp(canonattr+canonlen, ".ebs") == 0) {
93 		for (i = 2; i < argc; i++) {
94 			char *p = strchr(argv[i], '=');
95 
96 			if (!p)
97 				die(EX_USAGE, "DeleteOnTermination must be supplied in %s", argv[i]);
98 			*p++ = 0;
99 			grecs_asprintf(&bufptr, &bufsize,
100 				       "%*.*s.%d.DeviceName",
101 				       canonlen, canonlen, canonattr, i - 1);
102 			eclat_request_add_param(q, bufptr, argv[i]);
103 
104 			grecs_asprintf(&bufptr,
105 				       &bufsize,
106 				       "%*.*s.%d.Ebs.DeleteOnTermination",
107 				       canonlen, canonlen, canonattr,
108 				       i - 1);
109 			if (strcmp(p, "false") && strcmp(p, "true"))
110 				die(EX_USAGE, "not a valid boolean in %s",
111 				    argv[i]);
112 			eclat_request_add_param(q, bufptr, p);
113 		}
114 	} else if (strcmp(canonattr, "UserData.Value") == 0) {
115 		char *input = from_file ? read_file(argv[2]) : argv[2];
116 		size_t enclen = 0;
117 		char *data;
118 
119 		if (is_base64)
120 			data = input;
121 		else
122 			eclat_base64_encode((unsigned char *)input,
123 					    strlen(input),
124 					    (unsigned char**) &data, &enclen);
125 		eclat_request_add_param(q, canonattr, data);
126 		if (enclen)
127 			free(data);
128 	} else
129 		eclat_request_add_param(q, canonattr, argv[2]);
130 	free(bufptr);
131 	return 0;
132 }
133