xref: /freebsd/usr.sbin/ppp/log.c (revision 9773f8c0c8061d3f39aa7f05fe06874f9193cfee)
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  *
269773f8c0SBrian Somers  *	$Id: log.c,v 1.34 1998/08/09 15:34:11 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 
37c9e11a11SBrian Somers #include "defs.h"
38b6e82f33SBrian Somers #include "command.h"
39927145beSBrian Somers #include "mbuf.h"
40927145beSBrian Somers #include "log.h"
4185b542cfSBrian Somers #include "descriptor.h"
4285b542cfSBrian Somers #include "prompt.h"
43af57ed9fSAtsushi Murai 
44b6e82f33SBrian Somers static const char *LogNames[] = {
45927145beSBrian Somers   "Async",
4692b09558SBrian Somers   "CBCP",
47cb611434SBrian Somers   "CCP",
48927145beSBrian Somers   "Chat",
49927145beSBrian Somers   "Command",
50927145beSBrian Somers   "Connect",
51927145beSBrian Somers   "Debug",
52927145beSBrian Somers   "HDLC",
535106c671SBrian Somers   "ID0",
54cb611434SBrian Somers   "IPCP",
55927145beSBrian Somers   "LCP",
56927145beSBrian Somers   "LQM",
57927145beSBrian Somers   "Phase",
58927145beSBrian Somers   "TCP/IP",
59b1ac9332SBrian Somers   "Timer",
60927145beSBrian Somers   "Tun",
61927145beSBrian Somers   "Warning",
62927145beSBrian Somers   "Error",
63927145beSBrian Somers   "Alert"
64927145beSBrian Somers };
65af57ed9fSAtsushi Murai 
66927145beSBrian Somers #define MSK(n) (1<<((n)-1))
67af57ed9fSAtsushi Murai 
68d47dceb8SBrian Somers static u_long LogMask = MSK(LogPHASE);
69a1e8f937SBrian Somers static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
70927145beSBrian Somers static int LogTunno = -1;
710f2f3eb3SBrian Somers static struct prompt *promptlist;	/* Where to log local stuff */
720bdcbcbeSBrian Somers int log_PromptListChanged;
730f2f3eb3SBrian Somers 
740f2f3eb3SBrian Somers struct prompt *
750f2f3eb3SBrian Somers log_PromptList()
760f2f3eb3SBrian Somers {
770f2f3eb3SBrian Somers   return promptlist;
780f2f3eb3SBrian Somers }
79b6217683SBrian Somers 
80b6217683SBrian Somers void
81b6217683SBrian Somers log_RegisterPrompt(struct prompt *prompt)
82b6217683SBrian Somers {
830f2f3eb3SBrian Somers   prompt->next = promptlist;
840f2f3eb3SBrian Somers   promptlist = prompt;
850f2f3eb3SBrian Somers   prompt->active = 1;
860f2f3eb3SBrian Somers   log_DiscardAllLocal(&prompt->logmask);
87b6217683SBrian Somers }
880f2f3eb3SBrian Somers 
890f2f3eb3SBrian Somers void
900f2f3eb3SBrian Somers log_ActivatePrompt(struct prompt *prompt)
910f2f3eb3SBrian Somers {
920f2f3eb3SBrian Somers   prompt->active = 1;
930f2f3eb3SBrian Somers   LogMaskLocal |= prompt->logmask;
94b6217683SBrian Somers }
95b6217683SBrian Somers 
9667568487SBrian Somers static void
9767568487SBrian Somers LogSetMaskLocal(void)
9867568487SBrian Somers {
9967568487SBrian Somers   struct prompt *p;
10067568487SBrian Somers 
10167568487SBrian Somers   LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
1020f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
10367568487SBrian Somers     LogMaskLocal |= p->logmask;
10467568487SBrian Somers }
10567568487SBrian Somers 
106b6217683SBrian Somers void
1070f2f3eb3SBrian Somers log_DeactivatePrompt(struct prompt *prompt)
1080f2f3eb3SBrian Somers {
1090f2f3eb3SBrian Somers   if (prompt->active) {
1100f2f3eb3SBrian Somers     prompt->active = 0;
1110f2f3eb3SBrian Somers     LogSetMaskLocal();
1120f2f3eb3SBrian Somers   }
1130f2f3eb3SBrian Somers }
1140f2f3eb3SBrian Somers 
1150f2f3eb3SBrian Somers void
116b6217683SBrian Somers log_UnRegisterPrompt(struct prompt *prompt)
117b6217683SBrian Somers {
118b6217683SBrian Somers   if (prompt) {
119b6217683SBrian Somers     struct prompt **p;
120b6217683SBrian Somers 
1210f2f3eb3SBrian Somers     for (p = &promptlist; *p; p = &(*p)->next)
122b6217683SBrian Somers       if (*p == prompt) {
1230f2f3eb3SBrian Somers         *p = prompt->next;
1240f2f3eb3SBrian Somers         prompt->next = NULL;
125b6217683SBrian Somers         break;
126b6217683SBrian Somers       }
12767568487SBrian Somers     LogSetMaskLocal();
1280bdcbcbeSBrian Somers     log_PromptListChanged++;
129b6217683SBrian Somers   }
130b6217683SBrian Somers }
131af57ed9fSAtsushi Murai 
1320f2f3eb3SBrian Somers void
1330f2f3eb3SBrian Somers log_DestroyPrompts(struct server *s)
1340f2f3eb3SBrian Somers {
1350f2f3eb3SBrian Somers   struct prompt *p, *pn;
1360f2f3eb3SBrian Somers 
1370f2f3eb3SBrian Somers   p = promptlist;
1380f2f3eb3SBrian Somers   while (p) {
1390f2f3eb3SBrian Somers     pn = p->next;
1400f2f3eb3SBrian Somers     if (s && p->owner != s) {
1410f2f3eb3SBrian Somers       p->next = NULL;
1420f2f3eb3SBrian Somers       prompt_Destroy(p, 1);
1430f2f3eb3SBrian Somers     }
1440f2f3eb3SBrian Somers     p = pn;
1450f2f3eb3SBrian Somers   }
1460f2f3eb3SBrian Somers }
1470f2f3eb3SBrian Somers 
1480f2f3eb3SBrian Somers void
1490f2f3eb3SBrian Somers log_DisplayPrompts()
1500f2f3eb3SBrian Somers {
1510f2f3eb3SBrian Somers   struct prompt *p;
1520f2f3eb3SBrian Somers 
1530f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1540f2f3eb3SBrian Somers     prompt_Required(p);
1550f2f3eb3SBrian Somers }
1560f2f3eb3SBrian Somers 
1570f2f3eb3SBrian Somers void
158bf1d3ff6SBrian Somers log_WritePrompts(struct datalink *dl, const char *fmt,...)
1590f2f3eb3SBrian Somers {
160bf1d3ff6SBrian Somers   va_list ap;
1610f2f3eb3SBrian Somers   struct prompt *p;
1620f2f3eb3SBrian Somers 
163bf1d3ff6SBrian Somers   va_start(ap, fmt);
1640f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1650f2f3eb3SBrian Somers     if (prompt_IsTermMode(p, dl))
166bf1d3ff6SBrian Somers       prompt_vPrintf(p, fmt, ap);
167bf1d3ff6SBrian Somers   va_end(ap);
1680f2f3eb3SBrian Somers }
1690f2f3eb3SBrian Somers 
1700f2f3eb3SBrian Somers void
1710f2f3eb3SBrian Somers log_SetTtyCommandMode(struct datalink *dl)
1720f2f3eb3SBrian Somers {
1730f2f3eb3SBrian Somers   struct prompt *p;
1740f2f3eb3SBrian Somers 
1750f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next)
1760f2f3eb3SBrian Somers     if (prompt_IsTermMode(p, dl))
1770f2f3eb3SBrian Somers       prompt_TtyCommandMode(p);
1780f2f3eb3SBrian Somers }
1790f2f3eb3SBrian Somers 
180927145beSBrian Somers static int
181927145beSBrian Somers syslogLevel(int lev)
182927145beSBrian Somers {
183927145beSBrian Somers   switch (lev) {
1846f384573SBrian Somers   case LogDEBUG:
1856f384573SBrian Somers   case LogTIMER:
1866f384573SBrian Somers     return LOG_DEBUG;
187944f7098SBrian Somers   case LogWARN:
188944f7098SBrian Somers     return LOG_WARNING;
189944f7098SBrian Somers   case LogERROR:
190944f7098SBrian Somers     return LOG_ERR;
191944f7098SBrian Somers   case LogALERT:
192944f7098SBrian Somers     return LOG_ALERT;
193927145beSBrian Somers   }
194927145beSBrian Somers   return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
195927145beSBrian Somers }
196af57ed9fSAtsushi Murai 
197927145beSBrian Somers const char *
198dd7e2610SBrian Somers log_Name(int id)
199927145beSBrian Somers {
200927145beSBrian Somers   return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
201927145beSBrian Somers }
202af57ed9fSAtsushi Murai 
203af57ed9fSAtsushi Murai void
204dd7e2610SBrian Somers log_Keep(int id)
205af57ed9fSAtsushi Murai {
206927145beSBrian Somers   if (id >= LogMIN && id <= LogMAXCONF)
207927145beSBrian Somers     LogMask |= MSK(id);
208af57ed9fSAtsushi Murai }
209927145beSBrian Somers 
210927145beSBrian Somers void
211dd7e2610SBrian Somers log_KeepLocal(int id, u_long *mask)
212a1e8f937SBrian Somers {
213b6217683SBrian Somers   if (id >= LogMIN && id <= LogMAXCONF) {
214a1e8f937SBrian Somers     LogMaskLocal |= MSK(id);
215b6217683SBrian Somers     *mask |= MSK(id);
216b6217683SBrian Somers   }
217a1e8f937SBrian Somers }
218a1e8f937SBrian Somers 
219a1e8f937SBrian Somers void
220dd7e2610SBrian Somers log_Discard(int id)
221927145beSBrian Somers {
222927145beSBrian Somers   if (id >= LogMIN && id <= LogMAXCONF)
223927145beSBrian Somers     LogMask &= ~MSK(id);
224927145beSBrian Somers }
225927145beSBrian Somers 
226927145beSBrian Somers void
227dd7e2610SBrian Somers log_DiscardLocal(int id, u_long *mask)
228a1e8f937SBrian Somers {
229b6217683SBrian Somers   if (id >= LogMIN && id <= LogMAXCONF) {
230b6217683SBrian Somers     *mask &= ~MSK(id);
23167568487SBrian Somers     LogSetMaskLocal();
232b6217683SBrian Somers   }
233a1e8f937SBrian Somers }
234a1e8f937SBrian Somers 
235a1e8f937SBrian Somers void
236dd7e2610SBrian Somers log_DiscardAll()
237927145beSBrian Somers {
238927145beSBrian Somers   LogMask = 0;
239af57ed9fSAtsushi Murai }
240af57ed9fSAtsushi Murai 
241a1e8f937SBrian Somers void
242dd7e2610SBrian Somers log_DiscardAllLocal(u_long *mask)
243a1e8f937SBrian Somers {
24467568487SBrian Somers   *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
24567568487SBrian Somers   LogSetMaskLocal();
246a1e8f937SBrian Somers }
247a1e8f937SBrian Somers 
248af57ed9fSAtsushi Murai int
249dd7e2610SBrian Somers log_IsKept(int id)
250af57ed9fSAtsushi Murai {
251a1e8f937SBrian Somers   if (id < LogMIN || id > LogMAX)
252927145beSBrian Somers     return 0;
253a1e8f937SBrian Somers   if (id > LogMAXCONF)
254a1e8f937SBrian Somers     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
255a1e8f937SBrian Somers 
256a1e8f937SBrian Somers   return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
257a1e8f937SBrian Somers     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
258af57ed9fSAtsushi Murai }
259af57ed9fSAtsushi Murai 
260b6217683SBrian Somers int
261dd7e2610SBrian Somers log_IsKeptLocal(int id, u_long mask)
262b6217683SBrian Somers {
263b6217683SBrian Somers   if (id < LogMIN || id > LogMAX)
264b6217683SBrian Somers     return 0;
265b6217683SBrian Somers   if (id > LogMAXCONF)
266b6217683SBrian Somers     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
267b6217683SBrian Somers 
268b6217683SBrian Somers   return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
269b6217683SBrian Somers     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
270b6217683SBrian Somers }
271b6217683SBrian Somers 
272af57ed9fSAtsushi Murai void
273dd7e2610SBrian Somers log_Open(const char *Name)
274af57ed9fSAtsushi Murai {
275927145beSBrian Somers   openlog(Name, LOG_PID, LOG_DAEMON);
276af57ed9fSAtsushi Murai }
277af57ed9fSAtsushi Murai 
278af57ed9fSAtsushi Murai void
279dd7e2610SBrian Somers log_SetTun(int tunno)
280af57ed9fSAtsushi Murai {
281927145beSBrian Somers   LogTunno = tunno;
282af57ed9fSAtsushi Murai }
283af57ed9fSAtsushi Murai 
284af57ed9fSAtsushi Murai void
285dd7e2610SBrian Somers log_Close()
286af57ed9fSAtsushi Murai {
287927145beSBrian Somers   closelog();
288927145beSBrian Somers   LogTunno = -1;
2896ed9fb2fSBrian Somers }
290af57ed9fSAtsushi Murai 
291af57ed9fSAtsushi Murai void
292dd7e2610SBrian Somers log_Printf(int lev, const char *fmt,...)
29353c9f6c0SAtsushi Murai {
29453c9f6c0SAtsushi Murai   va_list ap;
295b6217683SBrian Somers   struct prompt *prompt;
296944f7098SBrian Somers 
297927145beSBrian Somers   va_start(ap, fmt);
298dd7e2610SBrian Somers   if (log_IsKept(lev)) {
299d93d3a9cSBrian Somers     char nfmt[200];
30053c9f6c0SAtsushi Murai 
3010f2f3eb3SBrian Somers     if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) {
302dd7e2610SBrian Somers       if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
3031384bd27SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
304dd7e2610SBrian Somers 	         LogTunno, log_Name(lev), fmt);
305927145beSBrian Somers       else
306dd7e2610SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
307b6217683SBrian Somers 
3080f2f3eb3SBrian Somers       for (prompt = promptlist; prompt; prompt = prompt->next)
309b6217683SBrian Somers         if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
310b6217683SBrian Somers           prompt_vPrintf(prompt, nfmt, ap);
311a1e8f937SBrian Somers     }
312a1e8f937SBrian Somers 
3130f2f3eb3SBrian Somers     if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) &&
3140f2f3eb3SBrian Somers         (lev != LogWARN || !promptlist)) {
315dd7e2610SBrian Somers       if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
3161384bd27SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
317dd7e2610SBrian Somers 	         LogTunno, log_Name(lev), fmt);
318a1e8f937SBrian Somers       else
319dd7e2610SBrian Somers         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
320927145beSBrian Somers       vsyslog(syslogLevel(lev), nfmt, ap);
321927145beSBrian Somers     }
322a1e8f937SBrian Somers   }
32353c9f6c0SAtsushi Murai   va_end(ap);
32453c9f6c0SAtsushi Murai }
32553c9f6c0SAtsushi Murai 
32653c9f6c0SAtsushi Murai void
327dd7e2610SBrian Somers log_DumpBp(int lev, const char *hdr, const struct mbuf *bp)
328af57ed9fSAtsushi Murai {
329dd7e2610SBrian Somers   if (log_IsKept(lev)) {
330a1e8f937SBrian Somers     char buf[50];
331a9e8f807SBrian Somers     char *b;
3329773f8c0SBrian Somers     const u_char *ptr;
333a9e8f807SBrian Somers     int f;
334a9e8f807SBrian Somers 
335a9e8f807SBrian Somers     if (hdr && *hdr)
336dd7e2610SBrian Somers       log_Printf(lev, "%s\n", hdr);
337a9e8f807SBrian Somers 
338a9e8f807SBrian Somers     b = buf;
339a9e8f807SBrian Somers     do {
340a9e8f807SBrian Somers       f = bp->cnt;
3419773f8c0SBrian Somers       ptr = CONST_MBUF_CTOP(bp);
342a9e8f807SBrian Somers       while (f--) {
343a9e8f807SBrian Somers 	sprintf(b, " %02x", (int) *ptr++);
344a9e8f807SBrian Somers         b += 3;
345a1e8f937SBrian Somers         if (b == buf + sizeof buf - 2) {
346a1e8f937SBrian Somers           strcpy(b, "\n");
347dd7e2610SBrian Somers           log_Printf(lev, buf);
348a9e8f807SBrian Somers           b = buf;
349a9e8f807SBrian Somers         }
350a9e8f807SBrian Somers       }
351a9e8f807SBrian Somers     } while ((bp = bp->next) != NULL);
352a9e8f807SBrian Somers 
353a1e8f937SBrian Somers     if (b > buf) {
354a1e8f937SBrian Somers       strcpy(b, "\n");
355dd7e2610SBrian Somers       log_Printf(lev, buf);
356a9e8f807SBrian Somers     }
357af57ed9fSAtsushi Murai   }
358a1e8f937SBrian Somers }
359af57ed9fSAtsushi Murai 
360af57ed9fSAtsushi Murai void
361dd7e2610SBrian Somers log_DumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
362af57ed9fSAtsushi Murai {
363dd7e2610SBrian Somers   if (log_IsKept(lev)) {
364a1e8f937SBrian Somers     char buf[50];
365927145beSBrian Somers     char *b;
366af57ed9fSAtsushi Murai 
367927145beSBrian Somers     if (hdr && *hdr)
368dd7e2610SBrian Somers       log_Printf(lev, "%s\n", hdr);
369927145beSBrian Somers     while (n > 0) {
370927145beSBrian Somers       b = buf;
37170ee81ffSBrian Somers       for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3)
372927145beSBrian Somers 	sprintf(b, " %02x", (int) *ptr++);
373a1e8f937SBrian Somers       strcpy(b, "\n");
374dd7e2610SBrian Somers       log_Printf(lev, buf);
375af57ed9fSAtsushi Murai     }
376af57ed9fSAtsushi Murai   }
377c6c740beSBrian Somers }
378b6217683SBrian Somers 
379b6217683SBrian Somers int
380b6217683SBrian Somers log_ShowLevel(struct cmdargs const *arg)
381b6217683SBrian Somers {
382b6217683SBrian Somers   int i;
383b6217683SBrian Somers 
384b6217683SBrian Somers   prompt_Printf(arg->prompt, "Log:  ");
385b6217683SBrian Somers   for (i = LogMIN; i <= LogMAX; i++)
386dd7e2610SBrian Somers     if (log_IsKept(i) & LOG_KEPT_SYSLOG)
387dd7e2610SBrian Somers       prompt_Printf(arg->prompt, " %s", log_Name(i));
388b6217683SBrian Somers 
389b6217683SBrian Somers   prompt_Printf(arg->prompt, "\nLocal:");
390b6217683SBrian Somers   for (i = LogMIN; i <= LogMAX; i++)
391dd7e2610SBrian Somers     if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
392dd7e2610SBrian Somers       prompt_Printf(arg->prompt, " %s", log_Name(i));
393b6217683SBrian Somers 
394b6217683SBrian Somers   prompt_Printf(arg->prompt, "\n");
395b6217683SBrian Somers 
396b6217683SBrian Somers   return 0;
397b6217683SBrian Somers }
398b6217683SBrian Somers 
399b6217683SBrian Somers int
400b6217683SBrian Somers log_SetLevel(struct cmdargs const *arg)
401b6217683SBrian Somers {
402b6217683SBrian Somers   int i, res, argc, local;
403b6217683SBrian Somers   char const *const *argv, *argp;
404b6217683SBrian Somers 
40525092092SBrian Somers   argc = arg->argc - arg->argn;
40625092092SBrian Somers   argv = arg->argv + arg->argn;
407b6217683SBrian Somers   res = 0;
408b6217683SBrian Somers 
409b6217683SBrian Somers   if (argc == 0 || strcasecmp(argv[0], "local"))
410b6217683SBrian Somers     local = 0;
411b6217683SBrian Somers   else {
412b6217683SBrian Somers     if (arg->prompt == NULL) {
413dd7e2610SBrian Somers       log_Printf(LogWARN, "set log local: Only available on the command line\n");
414b6217683SBrian Somers       return 1;
415b6217683SBrian Somers     }
416b6217683SBrian Somers     argc--;
417b6217683SBrian Somers     argv++;
418b6217683SBrian Somers     local = 1;
419b6217683SBrian Somers   }
420b6217683SBrian Somers 
421e43ebac1SBrian Somers   if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
422b6217683SBrian Somers     if (local)
423dd7e2610SBrian Somers       log_DiscardAllLocal(&arg->prompt->logmask);
424b6217683SBrian Somers     else
425dd7e2610SBrian Somers       log_DiscardAll();
426e43ebac1SBrian Somers   }
427b6217683SBrian Somers 
428b6217683SBrian Somers   while (argc--) {
429b6217683SBrian Somers     argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
430b6217683SBrian Somers     for (i = LogMIN; i <= LogMAX; i++)
431dd7e2610SBrian Somers       if (strcasecmp(argp, log_Name(i)) == 0) {
432e43ebac1SBrian Somers 	if (**argv == '-') {
433b6217683SBrian Somers           if (local)
434dd7e2610SBrian Somers             log_DiscardLocal(i, &arg->prompt->logmask);
435b6217683SBrian Somers           else
436dd7e2610SBrian Somers 	    log_Discard(i);
437e43ebac1SBrian Somers 	} else if (local)
438dd7e2610SBrian Somers           log_KeepLocal(i, &arg->prompt->logmask);
439b6217683SBrian Somers         else
440dd7e2610SBrian Somers           log_Keep(i);
441b6217683SBrian Somers 	break;
442b6217683SBrian Somers       }
443b6217683SBrian Somers     if (i > LogMAX) {
444dd7e2610SBrian Somers       log_Printf(LogWARN, "%s: Invalid log value\n", argp);
445b6217683SBrian Somers       res = -1;
446b6217683SBrian Somers     }
447b6217683SBrian Somers     argv++;
448b6217683SBrian Somers   }
449b6217683SBrian Somers   return res;
450b6217683SBrian Somers }
451b6217683SBrian Somers 
452b6217683SBrian Somers int
453b6217683SBrian Somers log_ShowWho(struct cmdargs const *arg)
454b6217683SBrian Somers {
455b6217683SBrian Somers   struct prompt *p;
456b6217683SBrian Somers 
4570f2f3eb3SBrian Somers   for (p = promptlist; p; p = p->next) {
458565e35e5SBrian Somers     prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
459f91ad6b0SBrian Somers     if (p == arg->prompt)
460f91ad6b0SBrian Somers       prompt_Printf(arg->prompt, " *");
461f91ad6b0SBrian Somers     if (!p->active)
462f91ad6b0SBrian Somers       prompt_Printf(arg->prompt, " ^Z");
463f91ad6b0SBrian Somers     prompt_Printf(arg->prompt, "\n");
464f91ad6b0SBrian Somers   }
465b6217683SBrian Somers 
466b6217683SBrian Somers   return 0;
467b6217683SBrian Somers }
468