int va_printf(void (*putc)(int), const char *formato, va_list va)
{
char buf[16];
char *s, *ps;
int c,  frac, n, sinal, base, nprinted;
int campo,padchar;
double x, y;
s=(char *)formato;
nprinted=campo=0;
while((c=*s++)) {
	if(c=='%'){
		c=*s++;
		sinal=frac=campo=0;
		padchar = ((c=='0')? '0' + 0x100:' ' + 0x100);
		if(c=='-') { padchar =' '; c=*s++; }
		while(edigito(c)) { campo=10*campo+c-'0'; c=*s++; }
		if(c=='.') {
			c=*s++;
			while(edigito(c)) { frac=10*frac+c-'0'; c=*s++; }
			}
		while(c=='l' || c=='L' || c=='h') c=*s++;
		base=10;
		if(c >= 'A' && c <= 'Z') c ^= 0x20;
		switch(c){
		case 'o': case 'q': base=8; goto lbl_u;
		case 'x': base=16;
		case 'u':
		lbl_u:
			n = u2str(buf, va_arg(va, unsigned int), base);
		lbl_escrevei:
			nprinted += n;
			campo -= (n+sinal);
			if(campo < 0) campo=0;
			nprinted +=campo;
			if(padchar & 0x100) while(campo--) putc(padchar);
			if(sinal) putc('-');
			while(n--) putc(buf[n]);
			break;
		case 'd': case 'i':
			base=va_arg(va, int);
			if(base < 0) { sinal=1; base=-base; }
			n = u2str(buf, base, 10);
			goto lbl_escrevei;
		case 'c':
			if(campo < 0) campo=0;
			nprinted +=campo;
			if(padchar & 0x100) while(campo--) putc(padchar);
			putc(va_arg(va, int)); nprinted++; break;
		case 's':
			ps = va_arg(va, char *);
			for(n=0; ps[n]; n++);
			nprinted += n;
			campo -= n;
			if(campo < 0) campo=0;
			nprinted +=campo;
			if(padchar & 0x100) while(campo--) putc(padchar);
			while(*ps) { putc(*ps); ps++; }
			break;
		case 'e': case 'f': case 'g':
			n=0;
			x=y=va_arg(va, double);
			if(x<0) { x=-x; sinal=1; }
			while((x > 1.0)) { x /= 10.0; n++; }
			if(x) while((x < 1.0)) { x *= 10.0; n--; }
			if(c=='e' || ((c=='g') && 
				((n > 9) || ((-n >= frac)&& frac)))){
				y = (sinal ? -x: x);
				sinal = 2;
				campo -=4;
				if(frac<2) frac=2;
				}
			c = dprint(y, (padchar & 0x100)?campo:0, frac, putc);
			campo -=c;
			nprinted +=c;
			if(sinal & 2){
				putc('E');
				if(n < 0) { putc('-'); n=-n; }
				else putc('+');
				if(n>99) { putc((n/100) + '0'); n %= 100; }
				putc((n / 10) + '0');
				putc((n % 10) + '0');
				}
			break;
		case '%': putc(c); nprinted++; break;
			}
		if(campo < 0) campo=0;
		nprinted +=campo;
		if(!(padchar & 0x100)) while(campo--) putc(padchar);
		}
	else { putc(c); nprinted++; }
Ejemplo n.º 2
0
static void
display_med(struct writer *w, struct lldpd_chassis *chassis, struct lldpd_port *port)
{
	int i;
	char *value;

	tag_start(w, "lldp-med", "LLDP-MED");

	tag_datatag(w, "device-type", "Device Type",
		map_lookup(chassis_med_type_map, chassis->c_med_type));

	display_med_capability(w, chassis, LLDPMED_CAP_CAP);
	display_med_capability(w, chassis, LLDPMED_CAP_POLICY);
	display_med_capability(w, chassis, LLDPMED_CAP_LOCATION);
	display_med_capability(w, chassis, LLDPMED_CAP_MDI_PSE);
	display_med_capability(w, chassis, LLDPMED_CAP_MDI_PD);
	display_med_capability(w, chassis, LLDPMED_CAP_IV);

	for (i = 0; i < LLDPMED_APPTYPE_LAST; i++) {
		if (i+1 == port->p_med_policy[i].type) {
			tag_start(w, "policy", "LLDP-MED Network Policy for");
			tag_attr(w, "apptype", "AppType",
				 u2str(port->p_med_policy[i].type));
			tag_attr(w, "defined", "Defined",
			         (port->p_med_policy[i].unknown)?"no":"yes");

			tag_datatag(w, "descr", "",
			    map_lookup(port_med_policy_map, port->p_med_policy[i].type));

			if (port->p_med_policy[i].tagged) {
				tag_start(w, "vlan", "VLAN");
				if (port->p_med_policy[i].vid == 0) {
					tag_attr(w, "vid", "", "priority");
				} else if (port->p_med_policy[i].vid == 4095) {
					tag_attr(w, "vid", "", "reserved");
				} else {
					tag_attr(w, "vid", "",
						 u2str(port->p_med_policy[i].vid));
				}
				tag_end(w);
			}

			tag_datatag(w, "priority", "Layer 2 Priority",
				    u2str(port->p_med_policy[i].priority));

			tag_datatag(w, "dscp", "DSCP Value",
				    u2str(port->p_med_policy[i].dscp));

			tag_end(w);
		}
	}
	for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) {
		if (i+1 == port->p_med_location[i].format) {
			tag_start(w, "location", "LLDP-MED Location Identification");

			switch(port->p_med_location[i].format) {
			case LLDPMED_LOCFORMAT_COORD:
				tag_attr(w, "type", "Type", "coordinates");

				if (port->p_med_location[i].data_len != 16) {
					tag_datatag(w, "error", "Error", "bad data length");
				} else {
					u_int64_t l;
					u_int8_t  v;
					char *    s;

					v = *(u_int8_t*)(port->p_med_location[i].data + 15);
					tag_attr(w, "geoid", "Geoid",
						 map_lookup(port_med_geoid_map,v));

					/* Latitude and longitude */
					memcpy(&l, port->p_med_location[i].data,
					    sizeof(u_int64_t));
					l = (ntohll(l) &
					    0x03FFFFFFFF000000ULL) >> 24;
					display_latitude_or_longitude(w,0, l);
					memcpy(&l, port->p_med_location[i].data + 5,
					    sizeof(u_int64_t));
					l = (ntohll(l) &
					    0x03FFFFFFFF000000ULL) >> 24;
					display_latitude_or_longitude(w,1, l);

					/* Altitude */
					memcpy(&l, port->p_med_location[i].data + 10,
					    sizeof(u_int64_t));
					l = (ntohll(l) &
					    0x3FFFFFFF000000ULL) >> 24;
					display_fixed_precision(l, 22, 8, 1, &s);

					tag_start(w, "altitude", "Altitude");
					switch ((*(u_int8_t*)(port->p_med_location[i].data +
						    10)) & 0xf0) {
					case (1 << 4):
						tag_attr(w, "unit", "", "m");
						break;
					case (2 << 4):
						tag_attr(w, "unit", "", "floor");
						break;
					default:
						tag_attr(w, "unit", "", "unknown");
					}
					tag_data(w,s);
					tag_end(w);

				}
				break;
			case LLDPMED_LOCFORMAT_CIVIC:
				tag_attr(w, "type", "Type", "address");

				if ((port->p_med_location[i].data_len < 3) ||
				    (port->p_med_location[i].data_len - 1 !=
					*(u_int8_t*)port->p_med_location[i].data)) {
					tag_datatag(w, "error", "Error", "bad data length");
				} else {
					int l = 4, n, catype, calength; 
					char country[3];
					country[0] = ((char *)port->p_med_location[i].data)[2];
					country[1] = ((char *)port->p_med_location[i].data)[3];
					country[2] = 0;

					tag_datatag(w, "country", "Country", country);

					while ((n = (port->
						    p_med_location[i].data_len - l)) >= 2) {
						catype = *(u_int8_t*)(port->
						    p_med_location[i].data + l);
						calength = *(u_int8_t*)(port->
						    p_med_location[i].data + l + 1);
						if (n < 2 + calength) {
							tag_datatag(w, "error", "Error", "bad data length");
							break;
						}

						if ((value = strndup((char *)(port->
							p_med_location[i].data + l + 2),
							    calength)) == NULL) {
							fatalx("not enough memory");
							break;
						}
						tag_datatag(w,
							map_lookup(civic_address_type_tags,catype),
							map_lookup(civic_address_type_values,catype),
							value);
						free(value);
						l += 2 + calength;
					}
				}
				break;
			case LLDPMED_LOCFORMAT_ELIN:
				if ((value = strndup((char *)(port->
						p_med_location[i].data),
					    port->p_med_location[i].data_len)) == NULL) {
					fatalx( "not enough memory");
					break;
				}
				tag_attr(w, "type", "Type", "elin");
				tag_datatag(w, "ecs", "ECS ELIN", value);
				free(value);
				break;
			default:
				tag_attr(w, "type", "", "unknown");
				tag_datatag(w, "unknown", "Data",
					dump(port->p_med_location[i].data,
				             port->p_med_location[i].data_len, 20, ' '));
			}
			tag_end(w);
		}
	}