Fix some more windowlist glitches
[screen-lua.git] / src / misc.c
blob0de4016c8617fe5e8c6b027f10abe754df54e77c
1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
24 #include <sys/types.h>
25 #include <sys/stat.h> /* mkdir() declaration */
26 #include <signal.h>
28 #include "config.h"
29 #include "screen.h"
30 #include "extern.h"
32 #ifdef SVR4
33 # include <sys/resource.h>
34 #endif
36 extern struct layer *flayer;
38 extern int eff_uid, real_uid;
39 extern int eff_gid, real_gid;
40 extern struct mline mline_old;
41 extern struct mchar mchar_blank;
42 extern unsigned char *null, *blank;
44 #ifdef HAVE_FDWALK
45 static int close_func __P((void *, int));
46 #endif
48 char *
49 SaveStr(str)
50 register const char *str;
52 register char *cp;
54 if ((cp = malloc(strlen(str) + 1)) == NULL)
55 Panic(0, strnomem);
56 else
57 strcpy(cp, str);
58 return cp;
61 char *
62 SaveStrn(str, n)
63 register const char *str;
64 int n;
66 register char *cp;
68 if ((cp = malloc(n + 1)) == NULL)
69 Panic(0, strnomem);
70 else
72 bcopy((char *)str, cp, n);
73 cp[n] = 0;
75 return cp;
78 /* cheap strstr replacement */
79 char *
80 InStr(str, pat)
81 char *str;
82 const char *pat;
84 int npat = strlen(pat);
85 for (;*str; str++)
86 if (!strncmp(str, pat, npat))
87 return str;
88 return 0;
91 #ifndef HAVE_STRERROR
92 char *
93 strerror(err)
94 int err;
96 extern int sys_nerr;
97 extern char *sys_errlist[];
99 static char er[20];
100 if (err > 0 && err < sys_nerr)
101 return sys_errlist[err];
102 sprintf(er, "Error %d", err);
103 return er;
105 #endif
107 void
108 centerline(str, y)
109 char *str;
110 int y;
112 int l, n;
114 ASSERT(flayer);
115 n = strlen(str);
116 if (n > flayer->l_width - 1)
117 n = flayer->l_width - 1;
118 l = (flayer->l_width - 1 - n) / 2;
119 LPutStr(flayer, str, n, &mchar_blank, l, y);
122 void
123 leftline(str, y)
124 char *str;
125 int y;
127 int l, n;
128 struct mchar mchar_dol;
130 mchar_dol = mchar_blank;
131 mchar_dol.image = '$';
133 ASSERT(flayer);
134 l = n = strlen(str);
135 if (n > flayer->l_width - 1)
136 n = flayer->l_width - 1;
137 LPutStr(flayer, str, n, &mchar_blank, 0, y);
138 if (n != l)
139 LPutChar(flayer, &mchar_dol, n, y);
143 char *
144 Filename(s)
145 char *s;
147 register char *p = s;
149 if (p)
150 while (*p)
151 if (*p++ == '/')
152 s = p;
153 return s;
156 char *
157 stripdev(nam)
158 char *nam;
160 #ifdef apollo
161 char *p;
163 if (nam == NULL)
164 return NULL;
165 # ifdef SVR4
166 /* unixware has /dev/pts012 as synonym for /dev/pts/12 */
167 if (!strncmp(nam, "/dev/pts", 8) && nam[8] >= '0' && nam[8] <= '9')
169 static char b[13];
170 sprintf(b, "pts/%d", atoi(nam + 8));
171 return b;
173 # endif /* SVR4 */
174 if (p = strstr(nam,"/dev/"))
175 return p + 5;
176 #else /* apollo */
177 if (nam == NULL)
178 return NULL;
179 if (strncmp(nam, "/dev/", 5) == 0)
180 return nam + 5;
181 #endif /* apollo */
182 return nam;
187 * Signal handling
190 #ifdef POSIX
191 sigret_t (*xsignal(sig, func))
192 # ifndef __APPLE__
193 __P(SIGPROTOARG)
194 # else
196 # endif
197 int sig;
198 sigret_t (*func) __P(SIGPROTOARG);
200 struct sigaction osa, sa;
201 sa.sa_handler = func;
202 (void)sigemptyset(&sa.sa_mask);
203 #ifdef SA_RESTART
204 sa.sa_flags = (sig == SIGCHLD ? SA_RESTART : 0);
205 #else
206 sa.sa_flags = 0;
207 #endif
208 if (sigaction(sig, &sa, &osa))
209 return (sigret_t (*)__P(SIGPROTOARG))-1;
210 return osa.sa_handler;
213 #else
214 # ifdef hpux
216 * hpux has berkeley signal semantics if we use sigvector,
217 * but not, if we use signal, so we define our own signal() routine.
219 void (*xsignal(sig, func)) __P(SIGPROTOARG)
220 int sig;
221 void (*func) __P(SIGPROTOARG);
223 struct sigvec osv, sv;
225 sv.sv_handler = func;
226 sv.sv_mask = sigmask(sig);
227 sv.sv_flags = SV_BSDSIG;
228 if (sigvector(sig, &sv, &osv) < 0)
229 return (void (*)__P(SIGPROTOARG))(BADSIG);
230 return osv.sv_handler;
232 # endif /* hpux */
233 #endif /* POSIX */
237 * uid/gid handling
240 #ifdef HAVE_SETEUID
242 void
243 xseteuid(euid)
244 int euid;
246 if (seteuid(euid) == 0)
247 return;
248 seteuid(0);
249 if (seteuid(euid))
250 Panic(errno, "seteuid");
253 void
254 xsetegid(egid)
255 int egid;
257 if (setegid(egid))
258 Panic(errno, "setegid");
261 #else /* HAVE_SETEUID */
262 # ifdef HAVE_SETREUID
264 void
265 xseteuid(euid)
266 int euid;
268 int oeuid;
270 oeuid = geteuid();
271 if (oeuid == euid)
272 return;
273 if ((int)getuid() != euid)
274 oeuid = getuid();
275 if (setreuid(oeuid, euid))
276 Panic(errno, "setreuid");
279 void
280 xsetegid(egid)
281 int egid;
283 int oegid;
285 oegid = getegid();
286 if (oegid == egid)
287 return;
288 if ((int)getgid() != egid)
289 oegid = getgid();
290 if (setregid(oegid, egid))
291 Panic(errno, "setregid");
294 # endif /* HAVE_SETREUID */
295 #endif /* HAVE_SETEUID */
299 #ifdef NEED_OWN_BCOPY
300 void
301 xbcopy(s1, s2, len)
302 register char *s1, *s2;
303 register int len;
305 if (s1 < s2 && s2 < s1 + len)
307 s1 += len;
308 s2 += len;
309 while (len-- > 0)
310 *--s2 = *--s1;
312 else
313 while (len-- > 0)
314 *s2++ = *s1++;
316 #endif /* NEED_OWN_BCOPY */
318 void
319 bclear(p, n)
320 char *p;
321 int n;
323 bcopy((char *)blank, p, n);
327 void
328 Kill(pid, sig)
329 int pid, sig;
331 if (pid < 2)
332 return;
333 (void) kill(pid, sig);
336 #ifdef HAVE_FDWALK
338 * Modern versions of Solaris include fdwalk(3c) which allows efficient
339 * implementation of closing open descriptors; this is helpful because
340 * the default file descriptor limit has risen to 65k.
342 static int
343 close_func(cb_data, fd)
344 void *cb_data;
345 int fd;
347 int except = *(int *)cb_data;
348 if (fd > 2 && fd != except)
349 (void)close(fd);
350 return (0);
353 void
354 closeallfiles(except)
355 int except;
357 (void)fdwalk(close_func, &except);
360 #else /* HAVE_FDWALK */
362 void
363 closeallfiles(except)
364 int except;
366 int f;
367 #ifdef SVR4
368 struct rlimit rl;
370 if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && rl.rlim_max != RLIM_INFINITY)
371 f = rl.rlim_max;
372 else
373 #endif /* SVR4 */
374 #if defined(SYSV) && defined(NOFILE) && !defined(ISC)
375 f = NOFILE;
376 #else /* SYSV && !ISC */
377 f = getdtablesize();
378 #endif /* SYSV && !ISC */
379 while (--f > 2)
380 if (f != except)
381 close(f);
384 #endif /* HAVE_FDWALK */
388 * Security - switch to real uid
391 #ifndef USE_SETEUID
392 static int UserPID;
393 static sigret_t (*Usersigcld)__P(SIGPROTOARG);
394 #endif
395 static int UserSTAT;
398 UserContext()
400 #ifndef USE_SETEUID
401 if (eff_uid == real_uid && eff_gid == real_gid)
402 return 1;
403 Usersigcld = signal(SIGCHLD, SIG_DFL);
404 debug("UserContext: forking.\n");
405 switch (UserPID = fork())
407 case -1:
408 Msg(errno, "fork");
409 return -1;
410 case 0:
411 signal(SIGHUP, SIG_DFL);
412 signal(SIGINT, SIG_IGN);
413 signal(SIGQUIT, SIG_DFL);
414 signal(SIGTERM, SIG_DFL);
415 # ifdef BSDJOBS
416 signal(SIGTTIN, SIG_DFL);
417 signal(SIGTTOU, SIG_DFL);
418 # endif
419 setuid(real_uid);
420 setgid(real_gid);
421 return 1;
422 default:
423 return 0;
425 #else
426 xseteuid(real_uid);
427 xsetegid(real_gid);
428 return 1;
429 #endif
432 void
433 UserReturn(val)
434 int val;
436 #ifndef USE_SETEUID
437 if (eff_uid == real_uid && eff_gid == real_gid)
438 UserSTAT = val;
439 else
440 _exit(val);
441 #else
442 xseteuid(eff_uid);
443 xsetegid(eff_gid);
444 UserSTAT = val;
445 #endif
449 UserStatus()
451 #ifndef USE_SETEUID
452 int i;
453 # ifdef BSDWAIT
454 union wait wstat;
455 # else
456 int wstat;
457 # endif
459 if (eff_uid == real_uid && eff_gid == real_gid)
460 return UserSTAT;
461 if (UserPID < 0)
462 return -1;
463 while ((errno = 0, i = wait(&wstat)) != UserPID)
464 if (i < 0 && errno != EINTR)
465 break;
466 (void) signal(SIGCHLD, Usersigcld);
467 if (i == -1)
468 return -1;
469 return WEXITSTATUS(wstat);
470 #else
471 return UserSTAT;
472 #endif
475 #ifndef HAVE_RENAME
477 rename (old, new)
478 char *old;
479 char *new;
481 if (link(old, new) < 0)
482 return -1;
483 return unlink(old);
485 #endif
489 AddXChar(buf, ch)
490 char *buf;
491 int ch;
493 char *p = buf;
495 if (ch < ' ' || ch == 0x7f)
497 *p++ = '^';
498 *p++ = ch ^ 0x40;
500 else if (ch >= 0x80)
502 *p++ = '\\';
503 *p++ = (ch >> 6 & 7) + '0';
504 *p++ = (ch >> 3 & 7) + '0';
505 *p++ = (ch >> 0 & 7) + '0';
507 else
508 *p++ = ch;
509 return p - buf;
513 AddXChars(buf, len, str)
514 char *buf, *str;
515 int len;
517 char *p;
519 if (str == 0)
521 *buf = 0;
522 return 0;
524 len -= 4; /* longest sequence produced by AddXChar() */
525 for (p = buf; p < buf + len && *str; str++)
527 if (*str == ' ')
528 *p++ = *str;
529 else
530 p += AddXChar(p, *str);
532 *p = 0;
533 return p - buf;
537 #ifdef DEBUG
538 void
539 opendebug(new, shout)
540 int new, shout;
542 char buf[256];
544 #ifdef _MODE_T
545 mode_t oumask = umask(0);
546 #else
547 int oumask = umask(0);
548 #endif
550 ASSERT(!dfp);
552 (void) mkdir(DEBUGDIR, 0777);
553 sprintf(buf, shout ? "%s/SCREEN.%d" : "%s/screen.%d", DEBUGDIR, getpid());
554 if (!(dfp = fopen(buf, new ? "w" : "a")))
555 dfp = stderr;
556 else
557 (void)chmod(buf, 0666);
559 (void)umask(oumask);
560 debug("opendebug: done.\n");
562 #endif /* DEBUG */
564 void
565 sleep1000(msec)
566 int msec;
569 struct timeval t;
571 t.tv_sec = (long) (msec / 1000);
572 t.tv_usec = (long) ((msec % 1000) * 1000);
573 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
578 * This uses either setenv() or putenv(). If it is putenv() we cannot dare
579 * to free the buffer after putenv(), unless it it the one found in putenv.c
581 void
582 xsetenv(var, value)
583 char *var;
584 char *value;
586 #ifndef USESETENV
587 char *buf;
588 int l;
590 if ((buf = (char *)malloc((l = strlen(var)) +
591 strlen(value) + 2)) == NULL)
593 Msg(0, strnomem);
594 return;
596 strcpy(buf, var);
597 buf[l] = '=';
598 strcpy(buf + l + 1, value);
599 putenv(buf);
600 # ifdef NEEDPUTENV
602 * we use our own putenv(), knowing that it does a malloc()
603 * the string space, we can free our buf now.
605 free(buf);
606 # else /* NEEDSETENV */
608 * For all sysv-ish systems that link a standard putenv()
609 * the string-space buf is added to the environment and must not
610 * be freed, or modified.
611 * We are sorry to say that memory is lost here, when setting
612 * the same variable again and again.
614 # endif /* NEEDSETENV */
615 #else /* USESETENV */
616 # if HAVE_SETENV_3
617 setenv(var, value, 1);
618 # else
619 setenv(var, value);
620 # endif /* HAVE_SETENV_3 */
621 #endif /* USESETENV */
624 #ifdef TERMINFO
626 * This is a replacement for the buggy _delay function from the termcap
627 * emulation of libcurses, which ignores ospeed.
630 _delay(delay, outc)
631 register int delay;
632 int (*outc) __P((int));
634 int pad;
635 extern short ospeed;
636 static short osp2pad[] = {
637 0,2000,1333,909,743,666,500,333,166,83,55,41,20,10,5,2,1,1
640 if (ospeed <= 0 || ospeed >= (int)(sizeof(osp2pad)/sizeof(*osp2pad)))
641 return 0;
642 pad =osp2pad[ospeed];
643 delay = (delay + pad / 2) / pad;
644 while (delay-- > 0)
645 (*outc)(0);
646 return 0;
649 # ifdef linux
651 /* stupid stupid linux ncurses! It won't to padding with
652 * zeros but sleeps instead. This breaks CalcCost, of course.
653 * Also, the ncurses wait functions use a global variable
654 * to store the current outc function. Oh well...
657 int (*save_outc) __P((int));
659 # undef tputs
661 void
662 xtputs(str, affcnt, outc)
663 char *str;
664 int affcnt;
665 int (*outc) __P((int));
667 extern int tputs __P((const char *, int, int (*)(int)));
668 save_outc = outc;
669 tputs(str, affcnt, outc);
673 _nc_timed_wait(mode, ms, tlp)
674 int mode, ms, *tlp;
676 _delay(ms * 10, save_outc);
677 return 0;
680 # endif /* linux */
682 #endif /* TERMINFO */
686 #ifndef USEVARARGS
688 # define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0)))
689 # define xva_list char *
691 static int
692 xsnoff(a, b, c)
693 int a;
694 char *b;
695 int c;
697 return a ? (char *)&c - (char *)&b : (char *)&b - (char *)&a;
701 xsnprintf(s, n, fmt, p1, p2, p3, p4, p5, p6)
702 char *s;
703 int n;
704 char *fmt;
705 unsigned long p1, p2, p3, p4, p5, p6;
707 int xvsnprintf __P((char *, int, char *, xva_list));
708 return xvsnprintf(s, n, fmt, (char *)&fmt + xsnoff(1, 0, 0));
711 #else
713 # define xva_arg(s, t, tn) va_arg(s, t)
714 # define xva_list va_list
716 #endif
719 #if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF)
722 xvsnprintf(s, n, fmt, stack)
723 char *s;
724 int n;
725 char *fmt;
726 xva_list stack;
728 char *f, *sf = 0;
729 int i, on, argl = 0;
730 char myf[10], buf[20];
731 char *arg, *myfp;
733 on = n;
734 f = fmt;
735 arg = 0;
736 while(arg || (sf = index(f, '%')) || (sf = f + strlen(f)))
738 if (arg == 0)
740 arg = f;
741 argl = sf - f;
743 if (argl)
745 i = argl > n - 1 ? n - 1 : argl;
746 strncpy(s, arg, i);
747 s += i;
748 n -= i;
749 if (i < argl)
751 *s = 0;
752 return on;
755 arg = 0;
756 if (sf == 0)
757 continue;
758 f = sf;
759 sf = 0;
760 if (!*f)
761 break;
762 myfp = myf;
763 *myfp++ = *f++;
764 while (((*f >= '0' && *f <='9') || *f == '#') && myfp - myf < 8)
765 *myfp++ = *f++;
766 *myfp++ = *f;
767 *myfp = 0;
768 if (!*f++)
769 break;
770 switch(f[-1])
772 case '%':
773 arg = "%";
774 break;
775 case 'c':
776 case 'o':
777 case 'd':
778 case 'x':
779 i = xva_arg(stack, int, 0);
780 sprintf(buf, myf, i);
781 arg = buf;
782 break;
783 case 's':
784 arg = xva_arg(stack, char *, 1);
785 if (arg == 0)
786 arg = "NULL";
787 break;
788 default:
789 arg = "";
790 break;
792 argl = strlen(arg);
794 *s = 0;
795 return on - n;
798 #endif