lintian doesn't like orphan packages with uploaders...
[debian/amanda] / common-src / columnar.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-2000 University of Maryland at College Park
4  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of U.M. not be used in advertising or
12  * publicity pertaining to distribution of the software without specific,
13  * written prior permission.  U.M. makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Author: James da Silva, Systems Design and Analysis Group
25  *                         Computer Science Department
26  *                         University of Maryland at College Park
27  */
28 /*
29  * Originally living in conffile.c, this stuff supports columnar output in amreport.
30  */
31
32
33 #include "amanda.h"
34 #include "columnar.h"
35
36 ColumnInfo ColumnData[] = {
37     { "HostName",   0, 12, 12, 0, "%-*.*s", "HOSTNAME" },
38     { "Disk",       1, 11, 11, 0, "%-*.*s", "DISK" },
39     { "Level",      1, 1,  1,  0, "%*.*d",  "L" },
40     { "OrigKB",     1, 7,  0,  1, "%*.*lf", "ORIG-KB" },
41     { "OutKB",      1, 7,  0,  1, "%*.*lf", "OUT-KB" },
42     { "Compress",   1, 6,  1,  1, "%*.*lf", "COMP%" },
43     { "DumpTime",   1, 7,  7,  1, "%*.*s",  "MMM:SS" },
44     { "DumpRate",   1, 6,  1,  1, "%*.*lf", "KB/s" },
45     { "TapeTime",   1, 6,  6,  1, "%*.*s",  "MMM:SS" },
46     { "TapeRate",   1, 6,  1,  1, "%*.*lf", "KB/s" },
47     { NULL,         0, 0,  0,  0, NULL,     NULL }
48 };
49
50
51 int
52 ColumnDataCount(void )
53 {
54     return (int)(SIZEOF(ColumnData) / SIZEOF(ColumnData[0]));
55 }
56
57 /* conversion from string to table index
58  */
59 int
60 StringToColumn(
61     char *s)
62 {
63     int cn;
64
65     for (cn=0; ColumnData[cn].Name != NULL; cn++) {
66         if (strcasecmp(s, ColumnData[cn].Name) == 0) {
67             break;
68         }
69     }
70     return cn;
71 }
72
73 char
74 LastChar(
75     char *s)
76 {
77     return s[strlen(s)-1];
78 }
79
80 int
81 SetColumnDataFromString(
82     ColumnInfo* ci,
83     char *s,
84     char **errstr)
85 {
86     ci = ci;
87
88     /* Convert from a Columnspec string to our internal format
89      * of columspec. The purpose is to provide this string
90      * as configuration paramter in the amanda.conf file or
91      * (maybe) as environment variable.
92      * 
93      * This text should go as comment into the sample amanda.conf
94      *
95      * The format for such a ColumnSpec string s is a ',' seperated
96      * list of triples. Each triple consists of
97      *   -the name of the column (as in ColumnData.Name)
98      *   -prefix before the column
99      *   -the width of the column
100      *       if set to -1 it will be recalculated
101      *       to the maximum length of a line to print.
102      *   -the precision (number of digit after the dot)
103      * Example:
104      *  "Disk=1:17,HostName=1:10,OutKB=1:7"
105      * or
106      *  "Disk=1:-1,HostName=1:10,OutKB=1:7"
107      *  
108      * You need only specify those colums that should be changed from
109      * the default. If nothing is specified in the configfile, the
110      * above compiled in values will be in effect, resulting in an
111      * output as it was all the time.
112      *                                                  ElB, 1999-02-24.
113      */
114
115     while (s && *s) {
116         int Space, Width, Precision;
117         int cn;
118         char *eon= strchr(s, '=');
119
120         if (eon == NULL) {
121             *errstr = stralloc2(_("invalid columnspec: "), s);
122             return -1;
123         }
124         *eon= '\0';
125         cn=StringToColumn(s);
126         if (ColumnData[cn].Name == NULL) {
127             *errstr = stralloc2(_("invalid column name: "), s);
128             return -1;
129         }
130         if (sscanf(eon+1, "%d:%d:%d", &Space, &Width, &Precision) == 3) {
131             ColumnData[cn].PrefixSpace = Space;
132             ColumnData[cn].Width = Width;
133             ColumnData[cn].Precision = Precision;
134             if (Width > 0)
135                 ColumnData[cn].MaxWidth = 0;
136         } else if (sscanf(eon+1, ":%d:%d", &Width, &Precision) == 2) {
137             ColumnData[cn].Width = Width;
138             ColumnData[cn].Precision = Precision;
139             if (Width > 0)
140                 ColumnData[cn].MaxWidth = 0;
141         } else if (sscanf(eon+1, "%d::%d", &Space, &Precision) == 2) {
142             ColumnData[cn].PrefixSpace = Space;
143             ColumnData[cn].Precision = Precision;
144         } else if (sscanf(eon+1, "%d:%d", &Space, &Width) == 2) {
145             ColumnData[cn].PrefixSpace = Space;
146             ColumnData[cn].Width = Width;
147         } else if (sscanf(eon+1, "::%d", &Precision) == 1) {
148             ColumnData[cn].Precision = Precision;
149         } else if (sscanf(eon+1, ":%d", &Width) == 1) {
150             ColumnData[cn].Width = Width;
151             if (Width > 0)
152                 ColumnData[cn].MaxWidth = 0;
153         } else if (sscanf(eon+1, "%d", &Space) == 1) {
154             ColumnData[cn].PrefixSpace = Space;
155         } else {
156             *errstr = stralloc2(_("invalid format: "), eon + 1);
157             return -1;
158         }
159
160         if (ColumnData[cn].Width < 0) {
161             ColumnData[cn].MaxWidth = 1;
162             ColumnData[cn].Width = abs(ColumnData[cn].MaxWidth);
163         } else {
164             if (LastChar(ColumnData[cn].Format) == 's') {
165                 if (ColumnData[cn].Width > ColumnData[cn].Precision)
166                     ColumnData[cn].Precision = ColumnData[cn].Width;
167             } else if (ColumnData[cn].Width < ColumnData[cn].Precision) {
168                 ColumnData[cn].Precision = ColumnData[cn].Width;
169             }
170         }
171         s= strchr(eon+1, ',');
172         if (s != NULL)
173             s++;
174     }
175     return 0;
176 }
177