xref: /freebsd/usr.sbin/ppp/log.c (revision 1384bd27d8a0f3ca4fa7b4cbd15103c61c9fccb7)
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  *
261384bd27SBrian Somers  *	$Id: log.c,v 1.28 1998/05/23 22:24:40 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"
421384bd27SBrian Somers #include "defs.h"
43af57ed9fSAtsushi Murai 
44b6e82f33SBrian Somers static const char *LogNames[] = {
45927145beSBrian Somers   "Async",
46cb611434SBrian Somers   "CCP",
47927145beSBrian Somers   "Chat",
48927145beSBrian Somers   "Command",
49927145beSBrian Somers   "Connect",
50927145beSBrian Somers   "Debug",
51927145beSBrian Somers   "HDLC",
525106c671SBrian Somers   "ID0",
53cb611434SBrian Somers   "IPCP",
54927145beSBrian Somers   "LCP",
55927145beSBrian Somers   "LQM",
56927145beSBrian Somers   "Phase",
57927145beSBrian Somers   "TCP/IP",
58b1ac9332SBrian Somers   "Timer",
59927145beSBrian Somers   "Tun",
60927145beSBrian Somers   "Warning",
61927145beSBrian Somers   "Error",
62927145beSBrian Somers   "Alert"
63927145beSBrian Somers };
64af57ed9fSAtsushi Murai 
65927145beSBrian Somers #define MSK(n) (1<<((n)-1))
66af57ed9fSAtsushi Murai 
67d47dceb8SBrian Somers static u_long LogMask = MSK(LogPHASE);
68a1e8f937SBrian Somers static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
69927145beSBrian Somers static int LogTunno = -1;
700f2f3eb3SBrian Somers static struct prompt *promptlist;	/* Where to log local stuff */
710f2f3eb3SBrian Somers 
720f2f3eb3SBrian Somers struct prompt *
730f2f3eb3SBrian Somers log_PromptList()
740f2f3eb3SBrian Somers {
750f2f3eb3SBrian Somers   return promptlist;
760f2f3eb3SBrian Somers }
77b6217683SBrian Somers 
78b6217683SBrian Somers void
79b6217683SBrian Somers log_RegisterPrompt(struct prompt *prompt)
80b6217683SBrian Somers {
810f2f3eb3SBrian Somers   prompt->next = promptlist;
820f2f3eb3SBrian Somers   promptlist = prompt;
830f2f3eb3SBrian Somers   prompt->active = 1;
840f2f3eb3SBrian Somers   log_DiscardAllLocal(&prompt->logmask);
85b6217683SBrian Somers }
860f2f3eb3SBrian Somers 
870f2f3eb3SBrian Somers void
880f2f3eb3SBrian Somers log_ActivatePrompt(struct prompt *prompt)
890f2f3eb3SBrian Somers {
900f2f3eb3SBrian Somers   prompt->active = 1;
910f2f3eb3SBrian Somers   LogMaskLocal |= prompt->logmask;
92b6217683SBrian Somers }
93b6217683SBrian Somers 
9467568487SBrian Somers static void
9567568487SBrian Somers LogSetMaskLocal(void)
9667568487SBrian Somers {
9767568487SBrian Somers   struct prompt *p;
9867568487SBrian Somers 
9967568487SBrian Somers   LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
1000f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
10167568487SBrian Somers     LogMaskLocal |= p->logmask;
10267568487SBrian Somers }
10367568487SBrian Somers 
104b6217683SBrian Somers void
1050f2f3eb3SBrian Somers log_DeactivatePrompt(struct prompt *prompt)
1060f2f3eb3SBrian Somers {
1070f2f3eb3SBrian Somers   if (prompt->active) {
1080f2f3eb3SBrian Somers     prompt->active = 0;
1090f2f3eb3SBrian Somers     LogSetMaskLocal();
1100f2f3eb3SBrian Somers   }
1110f2f3eb3SBrian Somers }
1120f2f3eb3SBrian Somers 
1130f2f3eb3SBrian Somers void
114b6217683SBrian Somers log_UnRegisterPrompt(struct prompt *prompt)
115b6217683SBrian Somers {
116b6217683SBrian Somers   if (prompt) {
117b6217683SBrian Somers     struct prompt **p;
118b6217683SBrian Somers 
1190f2f3eb3SBrian Somers     for (p = &promptlist; *p; p = &(*p)->next)
120b6217683SBrian Somers       if (*p == prompt) {
1210f2f3eb3SBrian Somers         *p = prompt->next;
1220f2f3eb3SBrian Somers         prompt->next = NULL;
123b6217683SBrian Somers         break;
124b6217683SBrian Somers       }
12567568487SBrian Somers     LogSetMaskLocal();
126b6217683SBrian Somers   }
127b6217683SBrian Somers }
128af57ed9fSAtsushi Murai 
1290f2f3eb3SBrian Somers void
1300f2f3eb3SBrian Somers log_DestroyPrompts(struct server *s)
1310f2f3eb3SBrian Somers {
1320f2f3eb3SBrian Somers   struct prompt *p, *pn;
1330f2f3eb3SBrian Somers 
1340f2f3eb3SBrian Somers   p = promptlist;
1350f2f3eb3SBrian Somers   while (p) {
1360f2f3eb3SBrian Somers     pn = p->next;
1370f2f3eb3SBrian Somers     if (s && p->owner != s) {
1380f2f3eb3SBrian Somers       p->next = NULL;
1390f2f3eb3SBrian Somers       prompt_Destroy(p, 1);
1400f2f3eb3SBrian Somers     }
1410f2f3eb3SBrian Somers     p = pn;
1420f2f3eb3SBrian Somers   }
1430f2f3eb3SBrian Somers }
1440f2f3eb3SBrian Somers 
1450f2f3eb3SBrian Somers void
1460f2f3eb3SBrian Somers log_DisplayPrompts()
1470f2f3eb3SBrian Somers {
1480f2f3eb3SBrian Somers   struct prompt *p;
1490f2f3eb3SBrian Somers 
1500f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1510f2f3eb3SBrian Somers     prompt_Required(p);
1520f2f3eb3SBrian Somers }
1530f2f3eb3SBrian Somers 
1540f2f3eb3SBrian Somers void
1550f2f3eb3SBrian Somers log_WritePrompts(struct datalink *dl, const char *data, int len)
1560f2f3eb3SBrian Somers {
1570f2f3eb3SBrian Somers   struct prompt *p;
1580f2f3eb3SBrian Somers 
1590f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1600f2f3eb3SBrian Somers     if (prompt_IsTermMode(p, dl))
1610f2f3eb3SBrian Somers       prompt_Printf(p, "%.*s", len, data);
1620f2f3eb3SBrian Somers }
1630f2f3eb3SBrian Somers 
1640f2f3eb3SBrian Somers void
1650f2f3eb3SBrian Somers log_SetTtyCommandMode(struct datalink *dl)
1660f2f3eb3SBrian Somers {
1670f2f3eb3SBrian Somers   struct prompt *p;
1680f2f3eb3SBrian Somers 
1690f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1700f2f3eb3SBrian Somers     if (prompt_IsTermMode(p, dl))
1710f2f3eb3SBrian Somers       prompt_TtyCommandMode(p);
1720f2f3eb3SBrian Somers }
1730f2f3eb3SBrian Somers 
174927145beSBrian Somers static int
175927145beSBrian Somers syslogLevel(int lev)
176927145beSBrian Somers {
177927145beSBrian Somers   switch (lev) {
1786f384573SBrian Somers   case LogDEBUG:
1796f384573SBrian Somers   case LogTIMER:
1806f384573SBrian Somers     return LOG_DEBUG;
181944f7098SBrian Somers   case LogWARN:
182944f7098SBrian Somers     return LOG_WARNING;
183944f7098SBrian Somers   case LogERROR:
184944f7098SBrian Somers     return LOG_ERR;
185944f7098SBrian Somers   case LogALERT:
186944f7098SBrian Somers     return LOG_ALERT;
187927145beSBrian Somers   }
188927145beSBrian Somers   return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
189927145beSBrian Somers }
190af57ed9fSAtsushi Murai 
191927145beSBrian Somers const char *
192dd7e2610SBrian Somers log_Name(int id)
193927145beSBrian Somers {
194927145beSBrian Somers   return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
195927145beSBrian Somers }
196af57ed9fSAtsushi Murai 
197af57ed9fSAtsushi Murai void
198dd7e2610SBrian Somers log_Keep(int id)
199af57ed9fSAtsushi Murai {
200927145beSBrian Somers   if (id >= LogMIN && id <= LogMAXCONF)
201927145beSBrian Somers     LogMask |= MSK(id);
202af57ed9fSAtsushi Murai }
203927145beSBrian Somers 
204927145beSBrian Somers void
205dd7e2610SBrian Somers log_KeepLocal(int id, u_long *mask)
206a1e8f937SBrian Somers {
207b6217683SBrian Somers   if (id >= LogMIN && id <= LogMAXCONF) {
208a1e8f937SBrian Somers     LogMaskLocal |= MSK(id);
209b6217683SBrian Somers     *mask |= MSK(id);
210b6217683SBrian Somers   }
211a1e8f937SBrian Somers }
212a1e8f937SBrian Somers 
213a1e8f937SBrian Somers void
214dd7e2610SBrian Somers log_Discard(int id)
215927145beSBrian Somers {
216927145beSBrian Somers   if (id >= LogMIN && id <= LogMAXCONF)
217927145beSBrian Somers     LogMask &= ~MSK(id);
218927145beSBrian Somers }
219927145beSBrian Somers 
220927145beSBrian Somers void
221dd7e2610SBrian Somers log_DiscardLocal(int id, u_long *mask)
222a1e8f937SBrian Somers {
223b6217683SBrian Somers   if (id >= LogMIN && id <= LogMAXCONF) {
224b6217683SBrian Somers     *mask &= ~MSK(id);
22567568487SBrian Somers     LogSetMaskLocal();
226b6217683SBrian Somers   }
227a1e8f937SBrian Somers }
228a1e8f937SBrian Somers 
229a1e8f937SBrian Somers void
230dd7e2610SBrian Somers log_DiscardAll()
231927145beSBrian Somers {
232927145beSBrian Somers   LogMask = 0;
233af57ed9fSAtsushi Murai }
234af57ed9fSAtsushi Murai 
235a1e8f937SBrian Somers void
236dd7e2610SBrian Somers log_DiscardAllLocal(u_long *mask)
237a1e8f937SBrian Somers {
23867568487SBrian Somers   *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
23967568487SBrian Somers   LogSetMaskLocal();
240a1e8f937SBrian Somers }
241a1e8f937SBrian Somers 
242af57ed9fSAtsushi Murai int
243dd7e2610SBrian Somers log_IsKept(int id)
244af57ed9fSAtsushi Murai {
245a1e8f937SBrian Somers   if (id < LogMIN || id > LogMAX)
246927145beSBrian Somers     return 0;
247a1e8f937SBrian Somers   if (id > LogMAXCONF)
248a1e8f937SBrian Somers     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
249a1e8f937SBrian Somers 
250a1e8f937SBrian Somers   return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
251a1e8f937SBrian Somers     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
252af57ed9fSAtsushi Murai }
253af57ed9fSAtsushi Murai 
254b6217683SBrian Somers int
255dd7e2610SBrian Somers log_IsKeptLocal(int id, u_long mask)
256b6217683SBrian Somers {
257b6217683SBrian Somers   if (id < LogMIN || id > LogMAX)
258b6217683SBrian Somers     return 0;
259b6217683SBrian Somers   if (id > LogMAXCONF)
260b6217683SBrian Somers     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
261b6217683SBrian Somers 
262b6217683SBrian Somers   return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
263b6217683SBrian Somers     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
264b6217683SBrian Somers }
265b6217683SBrian Somers 
266af57ed9fSAtsushi Murai void
267dd7e2610SBrian Somers log_Open(const char *Name)
268af57ed9fSAtsushi Murai {
269927145beSBrian Somers   openlog(Name, LOG_PID, LOG_DAEMON);
270af57ed9fSAtsushi Murai }
271af57ed9fSAtsushi Murai 
272af57ed9fSAtsushi Murai void
273dd7e2610SBrian Somers log_SetTun(int tunno)
274af57ed9fSAtsushi Murai {
275927145beSBrian Somers   LogTunno = tunno;
276af57ed9fSAtsushi Murai }
277af57ed9fSAtsushi Murai 
278af57ed9fSAtsushi Murai void
279dd7e2610SBrian Somers log_Close()
280af57ed9fSAtsushi Murai {
281927145beSBrian Somers   closelog();
282927145beSBrian Somers   LogTunno = -1;
2836ed9fb2fSBrian Somers }
284af57ed9fSAtsushi Murai 
285af57ed9fSAtsushi Murai void
286dd7e2610SBrian Somers log_Printf(int lev, const char *fmt,...)
28753c9f6c0SAtsushi Murai {
28853c9f6c0SAtsushi Murai   va_list ap;
289b6217683SBrian Somers   struct prompt *prompt;
290944f7098SBrian Somers 
291927145beSBrian Somers   va_start(ap, fmt);
292dd7e2610SBrian Somers   if (log_IsKept(lev)) {
293927145beSBrian Somers     static char nfmt[200];
29453c9f6c0SAtsushi Murai 
2950f2f3eb3SBrian Somers     if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) {
296dd7e2610SBrian Somers       if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
2971384bd27SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
298dd7e2610SBrian Somers 	         LogTunno, log_Name(lev), fmt);
299927145beSBrian Somers       else
300dd7e2610SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
301b6217683SBrian Somers 
3020f2f3eb3SBrian Somers       for (prompt = promptlist; prompt; prompt = prompt->next)
303b6217683SBrian Somers         if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
304b6217683SBrian Somers           prompt_vPrintf(prompt, nfmt, ap);
305a1e8f937SBrian Somers     }
306a1e8f937SBrian Somers 
3070f2f3eb3SBrian Somers     if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) &&
3080f2f3eb3SBrian Somers         (lev != LogWARN || !promptlist)) {
309dd7e2610SBrian Somers       if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
3101384bd27SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
311dd7e2610SBrian Somers 	         LogTunno, log_Name(lev), fmt);
312a1e8f937SBrian Somers       else
313dd7e2610SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
314927145beSBrian Somers       vsyslog(syslogLevel(lev), nfmt, ap);
315927145beSBrian Somers     }
316a1e8f937SBrian Somers   }
31753c9f6c0SAtsushi Murai   va_end(ap);
31853c9f6c0SAtsushi Murai }
31953c9f6c0SAtsushi Murai 
32053c9f6c0SAtsushi Murai void
321dd7e2610SBrian Somers log_DumpBp(int lev, const char *hdr, const struct mbuf * bp)
322af57ed9fSAtsushi Murai {
323dd7e2610SBrian Somers   if (log_IsKept(lev)) {
324a1e8f937SBrian Somers     char buf[50];
325a9e8f807SBrian Somers     char *b;
326a9e8f807SBrian Somers     u_char *ptr;
327a9e8f807SBrian Somers     int f;
328a9e8f807SBrian Somers 
329a9e8f807SBrian Somers     if (hdr && *hdr)
330dd7e2610SBrian Somers       log_Printf(lev, "%s\n", hdr);
331a9e8f807SBrian Somers 
332a9e8f807SBrian Somers     b = buf;
333a9e8f807SBrian Somers     do {
334a9e8f807SBrian Somers       f = bp->cnt;
335a9e8f807SBrian Somers       ptr = MBUF_CTOP(bp);
336a9e8f807SBrian Somers       while (f--) {
337a9e8f807SBrian Somers 	sprintf(b, " %02x", (int) *ptr++);
338a9e8f807SBrian Somers         b += 3;
339a1e8f937SBrian Somers         if (b == buf + sizeof buf - 2) {
340a1e8f937SBrian Somers           strcpy(b, "\n");
341dd7e2610SBrian Somers           log_Printf(lev, buf);
342a9e8f807SBrian Somers           b = buf;
343a9e8f807SBrian Somers         }
344a9e8f807SBrian Somers       }
345a9e8f807SBrian Somers     } while ((bp = bp->next) != NULL);
346a9e8f807SBrian Somers 
347a1e8f937SBrian Somers     if (b > buf) {
348a1e8f937SBrian Somers       strcpy(b, "\n");
349dd7e2610SBrian Somers       log_Printf(lev, buf);
350a9e8f807SBrian Somers     }
351af57ed9fSAtsushi Murai   }
352a1e8f937SBrian Somers }
353af57ed9fSAtsushi Murai 
354af57ed9fSAtsushi Murai void
355dd7e2610SBrian Somers log_DumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
356af57ed9fSAtsushi Murai {
357dd7e2610SBrian Somers   if (log_IsKept(lev)) {
358a1e8f937SBrian Somers     char buf[50];
359927145beSBrian Somers     char *b;
360af57ed9fSAtsushi Murai 
361927145beSBrian Somers     if (hdr && *hdr)
362dd7e2610SBrian Somers       log_Printf(lev, "%s\n", hdr);
363927145beSBrian Somers     while (n > 0) {
364927145beSBrian Somers       b = buf;
36570ee81ffSBrian Somers       for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3)
366927145beSBrian Somers 	sprintf(b, " %02x", (int) *ptr++);
367a1e8f937SBrian Somers       strcpy(b, "\n");
368dd7e2610SBrian Somers       log_Printf(lev, buf);
369af57ed9fSAtsushi Murai     }
370af57ed9fSAtsushi Murai   }
371c6c740beSBrian Somers }
372b6217683SBrian Somers 
373b6217683SBrian Somers int
374b6217683SBrian Somers log_ShowLevel(struct cmdargs const *arg)
375b6217683SBrian Somers {
376b6217683SBrian Somers   int i;
377b6217683SBrian Somers 
378b6217683SBrian Somers   prompt_Printf(arg->prompt, "Log:  ");
379b6217683SBrian Somers   for (i = LogMIN; i <= LogMAX; i++)
380dd7e2610SBrian Somers     if (log_IsKept(i) & LOG_KEPT_SYSLOG)
381dd7e2610SBrian Somers       prompt_Printf(arg->prompt, " %s", log_Name(i));
382b6217683SBrian Somers 
383b6217683SBrian Somers   prompt_Printf(arg->prompt, "\nLocal:");
384b6217683SBrian Somers   for (i = LogMIN; i <= LogMAX; i++)
385dd7e2610SBrian Somers     if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
386dd7e2610SBrian Somers       prompt_Printf(arg->prompt, " %s", log_Name(i));
387b6217683SBrian Somers 
388b6217683SBrian Somers   prompt_Printf(arg->prompt, "\n");
389b6217683SBrian Somers 
390b6217683SBrian Somers   return 0;
391b6217683SBrian Somers }
392b6217683SBrian Somers 
393b6217683SBrian Somers int
394b6217683SBrian Somers log_SetLevel(struct cmdargs const *arg)
395b6217683SBrian Somers {
396b6217683SBrian Somers   int i, res, argc, local;
397b6217683SBrian Somers   char const *const *argv, *argp;
398b6217683SBrian Somers 
39925092092SBrian Somers   argc = arg->argc - arg->argn;
40025092092SBrian Somers   argv = arg->argv + arg->argn;
401b6217683SBrian Somers   res = 0;
402b6217683SBrian Somers 
403b6217683SBrian Somers   if (argc == 0 || strcasecmp(argv[0], "local"))
404b6217683SBrian Somers     local = 0;
405b6217683SBrian Somers   else {
406b6217683SBrian Somers     if (arg->prompt == NULL) {
407dd7e2610SBrian Somers       log_Printf(LogWARN, "set log local: Only available on the command line\n");
408b6217683SBrian Somers       return 1;
409b6217683SBrian Somers     }
410b6217683SBrian Somers     argc--;
411b6217683SBrian Somers     argv++;
412b6217683SBrian Somers     local = 1;
413b6217683SBrian Somers   }
414b6217683SBrian Somers 
415e43ebac1SBrian Somers   if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
416b6217683SBrian Somers     if (local)
417dd7e2610SBrian Somers       log_DiscardAllLocal(&arg->prompt->logmask);
418b6217683SBrian Somers     else
419dd7e2610SBrian Somers       log_DiscardAll();
420e43ebac1SBrian Somers   }
421b6217683SBrian Somers 
422b6217683SBrian Somers   while (argc--) {
423b6217683SBrian Somers     argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
424b6217683SBrian Somers     for (i = LogMIN; i <= LogMAX; i++)
425dd7e2610SBrian Somers       if (strcasecmp(argp, log_Name(i)) == 0) {
426e43ebac1SBrian Somers 	if (**argv == '-') {
427b6217683SBrian Somers           if (local)
428dd7e2610SBrian Somers             log_DiscardLocal(i, &arg->prompt->logmask);
429b6217683SBrian Somers           else
430dd7e2610SBrian Somers 	    log_Discard(i);
431e43ebac1SBrian Somers 	} else if (local)
432dd7e2610SBrian Somers           log_KeepLocal(i, &arg->prompt->logmask);
433b6217683SBrian Somers         else
434dd7e2610SBrian Somers           log_Keep(i);
435b6217683SBrian Somers 	break;
436b6217683SBrian Somers       }
437b6217683SBrian Somers     if (i > LogMAX) {
438dd7e2610SBrian Somers       log_Printf(LogWARN, "%s: Invalid log value\n", argp);
439b6217683SBrian Somers       res = -1;
440b6217683SBrian Somers     }
441b6217683SBrian Somers     argv++;
442b6217683SBrian Somers   }
443b6217683SBrian Somers   return res;
444b6217683SBrian Somers }
445b6217683SBrian Somers 
446b6217683SBrian Somers int
447b6217683SBrian Somers log_ShowWho(struct cmdargs const *arg)
448b6217683SBrian Somers {
449b6217683SBrian Somers   struct prompt *p;
450b6217683SBrian Somers 
4510f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next) {
452565e35e5SBrian Somers     prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
453f91ad6b0SBrian Somers     if (p == arg->prompt)
454f91ad6b0SBrian Somers       prompt_Printf(arg->prompt, " *");
455f91ad6b0SBrian Somers     if (!p->active)
456f91ad6b0SBrian Somers       prompt_Printf(arg->prompt, " ^Z");
457f91ad6b0SBrian Somers     prompt_Printf(arg->prompt, "\n");
458f91ad6b0SBrian Somers   }
459b6217683SBrian Somers 
460b6217683SBrian Somers   return 0;
461b6217683SBrian Somers }
462