+ * makes a trace
+ */
+char *admin_trace(int sock, int argc, char *argv[])
+{
+ static struct admin_message msg;
+ int i;
+
+ /* show help */
+ if (argc > 2) if (!strcasecmp(argv[2], "help"))
+ {
+ printf("Trace Help\n----------\n");
+ printf("%s trace [brief|short] [<filter>=<value> [...]]\n\n", argv[0]);
+ printf("By default a complete trace is shown in detailed format.\n");
+ printf("To show a more compact format, use 'brief' or 'short' keyword.\n");
+ printf("Use filter values to select specific trace messages.\n");
+ printf("All given filter values must match. If no filter is given, anything matches.\n\n");
+ printf("Filters:\n");
+ printf(" category=<mask bits>\n");
+ printf(" 0x01 = CH: channel object trace\n");
+ printf(" 0x02 = EP: endpoint object trace\n");
+ printf(" port=<mISDN port> select only given port for trace\n");
+ printf(" interface=<interface name> select only given interface for trace\n");
+ printf(" caller=<caller id> select only given caller id for trace\n");
+ printf(" dialing=<number> select only given dialed number for trace\n");
+ return(NULL);
+ }
+
+ /* init trace request */
+ memset(&msg, 0, sizeof(msg));
+ msg.message = ADMIN_TRACE_REQUEST;
+ msg.u.trace_req.detail = 3;
+
+ /* parse args */
+ i = 2;
+ while(i < argc)
+ {
+ if (!strcasecmp(argv[i], "brief"))
+ msg.u.trace_req.detail = 1;
+ else if (!strcasecmp(argv[i], "short"))
+ msg.u.trace_req.detail = 2;
+ else if (!strncasecmp(argv[i], "category=", 9))
+ msg.u.trace_req.category = atoi(argv[i]+9);
+ else if (!strncasecmp(argv[i], "port=", 5))
+ msg.u.trace_req.port = atoi(argv[i]+5);
+ else if (!strncasecmp(argv[i], "interface=", 10))
+ SCPY(msg.u.trace_req.interface, argv[i]+10);
+ else if (!strncasecmp(argv[i], "caller=", 7))
+ SCPY(msg.u.trace_req.caller, argv[i]+7);
+ else if (!strncasecmp(argv[i], "dialing=", 8))
+ SCPY(msg.u.trace_req.dialing, argv[i]+8);
+ else return("Invalid trace option, try 'trace help'.");
+
+ i++;
+ }
+
+ /* send trace request */
+ if (write(sock, &msg, sizeof(msg)) != sizeof(msg))
+ return("Broken pipe while sending trace request.");
+
+ /* receive response */
+next:
+ if (read(sock, &msg, sizeof(msg)) != sizeof(msg))
+ return("Broken pipe while receiving response.");
+
+ if (msg.message != ADMIN_TRACE_RESPONSE)
+ return("Response not valid.");
+
+ printf("%s", msg.u.trace_rsp.text);
+ goto next;
+}
+
+
+/*