xref: /freebsd/usr.sbin/ppp/log.c (revision 0f2f3eb39529ac52402b20eeca35857885301c4e)
1c39934eaSBrian Somers /*-
2c39934eaSBrian Somers  * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
3c39934eaSBrian Somers  * All rights reserved.
4c39934eaSBrian Somers  *
5c39934eaSBrian Somers  * Redistribution and use in source and binary forms, with or without
6c39934eaSBrian Somers  * modification, are permitted provided that the following conditions
7c39934eaSBrian Somers  * are met:
8c39934eaSBrian Somers  * 1. Redistributions of source code must retain the above copyright
9c39934eaSBrian Somers  *    notice, this list of conditions and the following disclaimer.
10c39934eaSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
11c39934eaSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
12c39934eaSBrian Somers  *    documentation and/or other materials provided with the distribution.
13c39934eaSBrian Somers  *
14c39934eaSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c39934eaSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c39934eaSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c39934eaSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c39934eaSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c39934eaSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c39934eaSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c39934eaSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c39934eaSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c39934eaSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c39934eaSBrian Somers  * SUCH DAMAGE.
25c39934eaSBrian Somers  *
260f2f3eb3SBrian Somers  *	$Id: log.c,v 1.27 1998/05/21 21:46:25 brian Exp $
2775240ed1SBrian Somers  */
2875240ed1SBrian Somers 
292764b86aSBrian Somers #include <sys/types.h>
3075240ed1SBrian Somers 
3153c9f6c0SAtsushi Murai #include <stdarg.h>
3253c9f6c0SAtsushi Murai #include <stdio.h>
3370a91e4cSBrian Somers #include <string.h>
3475240ed1SBrian Somers #include <syslog.h>
3585b542cfSBrian Somers #include <termios.h>
3675240ed1SBrian Somers 
37b6e82f33SBrian Somers #include "command.h"
38927145beSBrian Somers #include "mbuf.h"
39927145beSBrian Somers #include "log.h"
4085b542cfSBrian Somers #include "descriptor.h"
4185b542cfSBrian Somers #include "prompt.h"
42af57ed9fSAtsushi Murai 
43b6e82f33SBrian Somers static const char *LogNames[] = {
44927145beSBrian Somers   "Async",
45cb611434SBrian Somers   "CCP",
46927145beSBrian Somers   "Chat",
47927145beSBrian Somers   "Command",
48927145beSBrian Somers   "Connect",
49927145beSBrian Somers   "Debug",
50927145beSBrian Somers   "HDLC",
515106c671SBrian Somers   "ID0",
52cb611434SBrian Somers   "IPCP",
53927145beSBrian Somers   "LCP",
54927145beSBrian Somers   "LQM",
55927145beSBrian Somers   "Phase",
56927145beSBrian Somers   "TCP/IP",
57b1ac9332SBrian Somers   "Timer",
58927145beSBrian Somers   "Tun",
59927145beSBrian Somers   "Warning",
60927145beSBrian Somers   "Error",
61927145beSBrian Somers   "Alert"
62927145beSBrian Somers };
63af57ed9fSAtsushi Murai 
64927145beSBrian Somers #define MSK(n) (1<<((n)-1))
65af57ed9fSAtsushi Murai 
66d47dceb8SBrian Somers static u_long LogMask = MSK(LogPHASE);
67a1e8f937SBrian Somers static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
68927145beSBrian Somers static int LogTunno = -1;
690f2f3eb3SBrian Somers static struct prompt *promptlist;	/* Where to log local stuff */
700f2f3eb3SBrian Somers 
710f2f3eb3SBrian Somers struct prompt *
720f2f3eb3SBrian Somers log_PromptList()
730f2f3eb3SBrian Somers {
740f2f3eb3SBrian Somers   return promptlist;
750f2f3eb3SBrian Somers }
76b6217683SBrian Somers 
77b6217683SBrian Somers void
78b6217683SBrian Somers log_RegisterPrompt(struct prompt *prompt)
79b6217683SBrian Somers {
800f2f3eb3SBrian Somers   prompt->next = promptlist;
810f2f3eb3SBrian Somers   promptlist = prompt;
820f2f3eb3SBrian Somers   prompt->active = 1;
830f2f3eb3SBrian Somers   log_DiscardAllLocal(&prompt->logmask);
84b6217683SBrian Somers }
850f2f3eb3SBrian Somers 
860f2f3eb3SBrian Somers void
870f2f3eb3SBrian Somers log_ActivatePrompt(struct prompt *prompt)
880f2f3eb3SBrian Somers {
890f2f3eb3SBrian Somers   prompt->active = 1;
900f2f3eb3SBrian Somers   LogMaskLocal |= prompt->logmask;
91b6217683SBrian Somers }
92b6217683SBrian Somers 
9367568487SBrian Somers static void
9467568487SBrian Somers LogSetMaskLocal(void)
9567568487SBrian Somers {
9667568487SBrian Somers   struct prompt *p;
9767568487SBrian Somers 
9867568487SBrian Somers   LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
990f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
10067568487SBrian Somers     LogMaskLocal |= p->logmask;
10167568487SBrian Somers }
10267568487SBrian Somers 
103b6217683SBrian Somers void
1040f2f3eb3SBrian Somers log_DeactivatePrompt(struct prompt *prompt)
1050f2f3eb3SBrian Somers {
1060f2f3eb3SBrian Somers   if (prompt->active) {
1070f2f3eb3SBrian Somers     prompt->active = 0;
1080f2f3eb3SBrian Somers     LogSetMaskLocal();
1090f2f3eb3SBrian Somers   }
1100f2f3eb3SBrian Somers }
1110f2f3eb3SBrian Somers 
1120f2f3eb3SBrian Somers void
113b6217683SBrian Somers log_UnRegisterPrompt(struct prompt *prompt)
114b6217683SBrian Somers {
115b6217683SBrian Somers   if (prompt) {
116b6217683SBrian Somers     struct prompt **p;
117b6217683SBrian Somers 
1180f2f3eb3SBrian Somers     for (p = &promptlist; *p; p = &(*p)->next)
119b6217683SBrian Somers       if (*p == prompt) {
1200f2f3eb3SBrian Somers         *p = prompt->next;
1210f2f3eb3SBrian Somers         prompt->next = NULL;
122b6217683SBrian Somers         break;
123b6217683SBrian Somers       }
12467568487SBrian Somers     LogSetMaskLocal();
125b6217683SBrian Somers   }
126b6217683SBrian Somers }
127af57ed9fSAtsushi Murai 
1280f2f3eb3SBrian Somers void
1290f2f3eb3SBrian Somers log_DestroyPrompts(struct server *s)
1300f2f3eb3SBrian Somers {
1310f2f3eb3SBrian Somers   struct prompt *p, *pn;
1320f2f3eb3SBrian Somers 
1330f2f3eb3SBrian Somers   p = promptlist;
1340f2f3eb3SBrian Somers   while (p) {
1350f2f3eb3SBrian Somers     pn = p->next;
1360f2f3eb3SBrian Somers     if (s && p->owner != s) {
1370f2f3eb3SBrian Somers       p->next = NULL;
1380f2f3eb3SBrian Somers       prompt_Destroy(p, 1);
1390f2f3eb3SBrian Somers     }
1400f2f3eb3SBrian Somers     p = pn;
1410f2f3eb3SBrian Somers   }
1420f2f3eb3SBrian Somers }
1430f2f3eb3SBrian Somers 
1440f2f3eb3SBrian Somers void
1450f2f3eb3SBrian Somers log_DisplayPrompts()
1460f2f3eb3SBrian Somers {
1470f2f3eb3SBrian Somers   struct prompt *p;
1480f2f3eb3SBrian Somers 
1490f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1500f2f3eb3SBrian Somers     prompt_Required(p);
1510f2f3eb3SBrian Somers }
1520f2f3eb3SBrian Somers 
1530f2f3eb3SBrian Somers void
1540f2f3eb3SBrian Somers log_WritePrompts(struct datalink *dl, const char *data, int len)
1550f2f3eb3SBrian Somers {
1560f2f3eb3SBrian Somers   struct prompt *p;
1570f2f3eb3SBrian Somers 
1580f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1590f2f3eb3SBrian Somers     if (prompt_IsTermMode(p, dl))
1600f2f3eb3SBrian Somers       prompt_Printf(p, "%.*s", len, data);
1610f2f3eb3SBrian Somers }
1620f2f3eb3SBrian Somers 
1630f2f3eb3SBrian Somers void
1640f2f3eb3SBrian Somers log_SetTtyCommandMode(struct datalink *dl)
1650f2f3eb3SBrian Somers {
1660f2f3eb3SBrian Somers   struct prompt *p;
1670f2f3eb3SBrian Somers 
1680f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1690f2f3eb3SBrian Somers     if (prompt_IsTermMode(p, dl))
1700f2f3eb3SBrian Somers       prompt_TtyCommandMode(p);
1710f2f3eb3SBrian Somers }
1720f2f3eb3SBrian Somers 
173927145beSBrian Somers static int
174927145beSBrian Somers syslogLevel(int lev)
175927145beSBrian Somers {
176927145beSBrian Somers   switch (lev) {
1776f384573SBrian Somers   case LogDEBUG:
1786f384573SBrian Somers   case LogTIMER:
1796f384573SBrian Somers     return LOG_DEBUG;
180944f7098SBrian Somers   case LogWARN:
181944f7098SBrian Somers     return LOG_WARNING;
182944f7098SBrian Somers   case LogERROR:
183944f7098SBrian Somers     return LOG_ERR;
184944f7098SBrian Somers   case LogALERT:
185944f7098SBrian Somers     return LOG_ALERT;
186927145beSBrian Somers   }
187927145beSBrian Somers   return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
188927145beSBrian Somers }
189af57ed9fSAtsushi Murai 
190927145beSBrian Somers const char *
191dd7e2610SBrian Somers log_Name(int id)
192927145beSBrian Somers {
193927145beSBrian Somers   return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
194927145beSBrian Somers }
195af57ed9fSAtsushi Murai 
196af57ed9fSAtsushi Murai void
197dd7e2610SBrian Somers log_Keep(int id)
198af57ed9fSAtsushi Murai {
199927145beSBrian Somers   if (id >= LogMIN && id <= LogMAXCONF)
200927145beSBrian Somers     LogMask |= MSK(id);
201af57ed9fSAtsushi Murai }
202927145beSBrian Somers 
203927145beSBrian Somers void
204dd7e2610SBrian Somers log_KeepLocal(int id, u_long *mask)
205a1e8f937SBrian Somers {
206b6217683SBrian Somers   if (id >= LogMIN && id <= LogMAXCONF) {
207a1e8f937SBrian Somers     LogMaskLocal |= MSK(id);
208b6217683SBrian Somers     *mask |= MSK(id);
209b6217683SBrian Somers   }
210a1e8f937SBrian Somers }
211a1e8f937SBrian Somers 
212a1e8f937SBrian Somers void
213dd7e2610SBrian Somers log_Discard(int id)
214927145beSBrian Somers {
215927145beSBrian Somers   if (id >= LogMIN && id <= LogMAXCONF)
216927145beSBrian Somers     LogMask &= ~MSK(id);
217927145beSBrian Somers }
218927145beSBrian Somers 
219927145beSBrian Somers void
220dd7e2610SBrian Somers log_DiscardLocal(int id, u_long *mask)
221a1e8f937SBrian Somers {
222b6217683SBrian Somers   if (id >= LogMIN && id <= LogMAXCONF) {
223b6217683SBrian Somers     *mask &= ~MSK(id);
22467568487SBrian Somers     LogSetMaskLocal();
225b6217683SBrian Somers   }
226a1e8f937SBrian Somers }
227a1e8f937SBrian Somers 
228a1e8f937SBrian Somers void
229dd7e2610SBrian Somers log_DiscardAll()
230927145beSBrian Somers {
231927145beSBrian Somers   LogMask = 0;
232af57ed9fSAtsushi Murai }
233af57ed9fSAtsushi Murai 
234a1e8f937SBrian Somers void
235dd7e2610SBrian Somers log_DiscardAllLocal(u_long *mask)
236a1e8f937SBrian Somers {
23767568487SBrian Somers   *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
23867568487SBrian Somers   LogSetMaskLocal();
239a1e8f937SBrian Somers }
240a1e8f937SBrian Somers 
241af57ed9fSAtsushi Murai int
242dd7e2610SBrian Somers log_IsKept(int id)
243af57ed9fSAtsushi Murai {
244a1e8f937SBrian Somers   if (id < LogMIN || id > LogMAX)
245927145beSBrian Somers     return 0;
246a1e8f937SBrian Somers   if (id > LogMAXCONF)
247a1e8f937SBrian Somers     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
248a1e8f937SBrian Somers 
249a1e8f937SBrian Somers   return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
250a1e8f937SBrian Somers     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
251af57ed9fSAtsushi Murai }
252af57ed9fSAtsushi Murai 
253b6217683SBrian Somers int
254dd7e2610SBrian Somers log_IsKeptLocal(int id, u_long mask)
255b6217683SBrian Somers {
256b6217683SBrian Somers   if (id < LogMIN || id > LogMAX)
257b6217683SBrian Somers     return 0;
258b6217683SBrian Somers   if (id > LogMAXCONF)
259b6217683SBrian Somers     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
260b6217683SBrian Somers 
261b6217683SBrian Somers   return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
262b6217683SBrian Somers     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
263b6217683SBrian Somers }
264b6217683SBrian Somers 
265af57ed9fSAtsushi Murai void
266dd7e2610SBrian Somers log_Open(const char *Name)
267af57ed9fSAtsushi Murai {
268927145beSBrian Somers   openlog(Name, LOG_PID, LOG_DAEMON);
269af57ed9fSAtsushi Murai }
270af57ed9fSAtsushi Murai 
271af57ed9fSAtsushi Murai void
272dd7e2610SBrian Somers log_SetTun(int tunno)
273af57ed9fSAtsushi Murai {
274927145beSBrian Somers   LogTunno = tunno;
275af57ed9fSAtsushi Murai }
276af57ed9fSAtsushi Murai 
277af57ed9fSAtsushi Murai void
278dd7e2610SBrian Somers log_Close()
279af57ed9fSAtsushi Murai {
280927145beSBrian Somers   closelog();
281927145beSBrian Somers   LogTunno = -1;
2826ed9fb2fSBrian Somers }
283af57ed9fSAtsushi Murai 
284af57ed9fSAtsushi Murai void
285dd7e2610SBrian Somers log_Printf(int lev, const char *fmt,...)
28653c9f6c0SAtsushi Murai {
28753c9f6c0SAtsushi Murai   va_list ap;
288b6217683SBrian Somers   struct prompt *prompt;
289944f7098SBrian Somers 
290927145beSBrian Somers   va_start(ap, fmt);
291dd7e2610SBrian Somers   if (log_IsKept(lev)) {
292927145beSBrian Somers     static char nfmt[200];
29353c9f6c0SAtsushi Murai 
2940f2f3eb3SBrian Somers     if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) {
295dd7e2610SBrian Somers       if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
296927145beSBrian Somers         snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s",
297dd7e2610SBrian Somers 	         LogTunno, log_Name(lev), fmt);
298927145beSBrian Somers       else
299dd7e2610SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
300b6217683SBrian Somers 
3010f2f3eb3SBrian Somers       for (prompt = promptlist; prompt; prompt = prompt->next)
302b6217683SBrian Somers         if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
303b6217683SBrian Somers           prompt_vPrintf(prompt, nfmt, ap);
304a1e8f937SBrian Somers     }
305a1e8f937SBrian Somers 
3060f2f3eb3SBrian Somers     if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) &&
3070f2f3eb3SBrian Somers         (lev != LogWARN || !promptlist)) {
308dd7e2610SBrian Somers       if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
309a1e8f937SBrian Somers         snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s",
310dd7e2610SBrian Somers 	         LogTunno, log_Name(lev), fmt);
311a1e8f937SBrian Somers       else
312dd7e2610SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
313927145beSBrian Somers       vsyslog(syslogLevel(lev), nfmt, ap);
314927145beSBrian Somers     }
315a1e8f937SBrian Somers   }
31653c9f6c0SAtsushi Murai   va_end(ap);
31753c9f6c0SAtsushi Murai }
31853c9f6c0SAtsushi Murai 
31953c9f6c0SAtsushi Murai void
320dd7e2610SBrian Somers log_DumpBp(int lev, const char *hdr, const struct mbuf * bp)
321af57ed9fSAtsushi Murai {
322dd7e2610SBrian Somers   if (log_IsKept(lev)) {
323a1e8f937SBrian Somers     char buf[50];
324a9e8f807SBrian Somers     char *b;
325a9e8f807SBrian Somers     u_char *ptr;
326a9e8f807SBrian Somers     int f;
327a9e8f807SBrian Somers 
328a9e8f807SBrian Somers     if (hdr && *hdr)
329dd7e2610SBrian Somers       log_Printf(lev, "%s\n", hdr);
330a9e8f807SBrian Somers 
331a9e8f807SBrian Somers     b = buf;
332a9e8f807SBrian Somers     do {
333a9e8f807SBrian Somers       f = bp->cnt;
334a9e8f807SBrian Somers       ptr = MBUF_CTOP(bp);
335a9e8f807SBrian Somers       while (f--) {
336a9e8f807SBrian Somers 	sprintf(b, " %02x", (int) *ptr++);
337a9e8f807SBrian Somers         b += 3;
338a1e8f937SBrian Somers         if (b == buf + sizeof buf - 2) {
339a1e8f937SBrian Somers           strcpy(b, "\n");
340dd7e2610SBrian Somers           log_Printf(lev, buf);
341a9e8f807SBrian Somers           b = buf;
342a9e8f807SBrian Somers         }
343a9e8f807SBrian Somers       }
344a9e8f807SBrian Somers     } while ((bp = bp->next) != NULL);
345a9e8f807SBrian Somers 
346a1e8f937SBrian Somers     if (b > buf) {
347a1e8f937SBrian Somers       strcpy(b, "\n");
348dd7e2610SBrian Somers       log_Printf(lev, buf);
349a9e8f807SBrian Somers     }
350af57ed9fSAtsushi Murai   }
351a1e8f937SBrian Somers }
352af57ed9fSAtsushi Murai 
353af57ed9fSAtsushi Murai void
354dd7e2610SBrian Somers log_DumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
355af57ed9fSAtsushi Murai {
356dd7e2610SBrian Somers   if (log_IsKept(lev)) {
357a1e8f937SBrian Somers     char buf[50];
358927145beSBrian Somers     char *b;
359af57ed9fSAtsushi Murai 
360927145beSBrian Somers     if (hdr && *hdr)
361dd7e2610SBrian Somers       log_Printf(lev, "%s\n", hdr);
362927145beSBrian Somers     while (n > 0) {
363927145beSBrian Somers       b = buf;
36470ee81ffSBrian Somers       for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3)
365927145beSBrian Somers 	sprintf(b, " %02x", (int) *ptr++);
366a1e8f937SBrian Somers       strcpy(b, "\n");
367dd7e2610SBrian Somers       log_Printf(lev, buf);
368af57ed9fSAtsushi Murai     }
369af57ed9fSAtsushi Murai   }
370c6c740beSBrian Somers }
371b6217683SBrian Somers 
372b6217683SBrian Somers int
373b6217683SBrian Somers log_ShowLevel(struct cmdargs const *arg)
374b6217683SBrian Somers {
375b6217683SBrian Somers   int i;
376b6217683SBrian Somers 
377b6217683SBrian Somers   prompt_Printf(arg->prompt, "Log:  ");
378b6217683SBrian Somers   for (i = LogMIN; i <= LogMAX; i++)
379dd7e2610SBrian Somers     if (log_IsKept(i) & LOG_KEPT_SYSLOG)
380dd7e2610SBrian Somers       prompt_Printf(arg->prompt, " %s", log_Name(i));
381b6217683SBrian Somers 
382b6217683SBrian Somers   prompt_Printf(arg->prompt, "\nLocal:");
383b6217683SBrian Somers   for (i = LogMIN; i <= LogMAX; i++)
384dd7e2610SBrian Somers     if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
385dd7e2610SBrian Somers       prompt_Printf(arg->prompt, " %s", log_Name(i));
386b6217683SBrian Somers 
387b6217683SBrian Somers   prompt_Printf(arg->prompt, "\n");
388b6217683SBrian Somers 
389b6217683SBrian Somers   return 0;
390b6217683SBrian Somers }
391b6217683SBrian Somers 
392b6217683SBrian Somers int
393b6217683SBrian Somers log_SetLevel(struct cmdargs const *arg)
394b6217683SBrian Somers {
395b6217683SBrian Somers   int i, res, argc, local;
396b6217683SBrian Somers   char const *const *argv, *argp;
397b6217683SBrian Somers 
39825092092SBrian Somers   argc = arg->argc - arg->argn;
39925092092SBrian Somers   argv = arg->argv + arg->argn;
400b6217683SBrian Somers   res = 0;
401b6217683SBrian Somers 
402b6217683SBrian Somers   if (argc == 0 || strcasecmp(argv[0], "local"))
403b6217683SBrian Somers     local = 0;
404b6217683SBrian Somers   else {
405b6217683SBrian Somers     if (arg->prompt == NULL) {
406dd7e2610SBrian Somers       log_Printf(LogWARN, "set log local: Only available on the command line\n");
407b6217683SBrian Somers       return 1;
408b6217683SBrian Somers     }
409b6217683SBrian Somers     argc--;
410b6217683SBrian Somers     argv++;
411b6217683SBrian Somers     local = 1;
412b6217683SBrian Somers   }
413b6217683SBrian Somers 
414e43ebac1SBrian Somers   if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
415b6217683SBrian Somers     if (local)
416dd7e2610SBrian Somers       log_DiscardAllLocal(&arg->prompt->logmask);
417b6217683SBrian Somers     else
418dd7e2610SBrian Somers       log_DiscardAll();
419e43ebac1SBrian Somers   }
420b6217683SBrian Somers 
421b6217683SBrian Somers   while (argc--) {
422b6217683SBrian Somers     argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
423b6217683SBrian Somers     for (i = LogMIN; i <= LogMAX; i++)
424dd7e2610SBrian Somers       if (strcasecmp(argp, log_Name(i)) == 0) {
425e43ebac1SBrian Somers 	if (**argv == '-') {
426b6217683SBrian Somers           if (local)
427dd7e2610SBrian Somers             log_DiscardLocal(i, &arg->prompt->logmask);
428b6217683SBrian Somers           else
429dd7e2610SBrian Somers 	    log_Discard(i);
430e43ebac1SBrian Somers 	} else if (local)
431dd7e2610SBrian Somers           log_KeepLocal(i, &arg->prompt->logmask);
432b6217683SBrian Somers         else
433dd7e2610SBrian Somers           log_Keep(i);
434b6217683SBrian Somers 	break;
435b6217683SBrian Somers       }
436b6217683SBrian Somers     if (i > LogMAX) {
437dd7e2610SBrian Somers       log_Printf(LogWARN, "%s: Invalid log value\n", argp);
438b6217683SBrian Somers       res = -1;
439b6217683SBrian Somers     }
440b6217683SBrian Somers     argv++;
441b6217683SBrian Somers   }
442b6217683SBrian Somers   return res;
443b6217683SBrian Somers }
444b6217683SBrian Somers 
445b6217683SBrian Somers int
446b6217683SBrian Somers log_ShowWho(struct cmdargs const *arg)
447b6217683SBrian Somers {
448b6217683SBrian Somers   struct prompt *p;
449b6217683SBrian Somers 
4500f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next) {
451565e35e5SBrian Somers     prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
452f91ad6b0SBrian Somers     if (p == arg->prompt)
453f91ad6b0SBrian Somers       prompt_Printf(arg->prompt, " *");
454f91ad6b0SBrian Somers     if (!p->active)
455f91ad6b0SBrian Somers       prompt_Printf(arg->prompt, " ^Z");
456f91ad6b0SBrian Somers     prompt_Printf(arg->prompt, "\n");
457f91ad6b0SBrian Somers   }
458b6217683SBrian Somers 
459b6217683SBrian Somers   return 0;
460b6217683SBrian Somers }
461