ptg10805159
Section 21.5 Source Code 831
581 /*
582 * Add an option to the IPP header.
583 *
584 * LOCKING: none.
585 */
586 char *
587 add_option(char *cp, int tag, char *optname, char *optval)
588 {
589 int n;
590 union {
591 int16_t s;
592 char c[2];
593 } u;
594 *cp++=tag;
595 n=strlen(optname);
596 u.s=htons(n);
597 *cp++=u.c[0];
598 *cp++=u.c[1];
599 strcpy(cp, optname);
600 cp += n;
601 n=strlen(optval);
602 u.s=htons(n);
603 *cp++=u.c[0];
604 *cp++=u.c[1];
605 strcpy(cp, optval);
606 return(cp+n);
607 }
[581 – 593] Theadd_optionfunction is used to add an option to the IPP header that
we build to send to the printer.Recall from Figure21.4 that the format of an
attribute is a 1-byte tag describing the type of the attribute, followed by the
length of the attribute name stored in binary as a 2-byte integer,followed by
the name, the size of the attribute value, and finally the value itself.
IPP makes no attempt to control the alignment of the binary integers
embedded in the header.Some processor architectures, such as the SPARC,
can’t load an integer from an arbitrary address. This means that we can’t
storethe integers in the header by casting a pointer toint16_tto the
address in the header wherethe integer is to be stored. Instead, we need to
copy the integer 1 byte at a time. This is why we define the union
containing a 16-bit integer and 2 bytes.
[594 – 607] We storethe tag in the header and convert the length of the attribute name to
network byte order.Wecopy the length 1 byte at a time to the header.Then
we copy the attribute name. We repeat this process for the attribute value
and return the address in the header wherethe next part of the header
should begin.