1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
30 #include <sys/stat.h> /* mkdir() declaration */
38 # include <sys/resource.h>
41 extern struct layer
*flayer
;
43 extern int eff_uid
, real_uid
;
44 extern int eff_gid
, real_gid
;
45 extern struct mline mline_old
;
46 extern struct mchar mchar_blank
;
47 extern unsigned char *null
, *blank
;
50 static int close_func
__P((void *, int));
55 register const char *str
;
59 if ((cp
= malloc(strlen(str
) + 1)) == NULL
)
60 Panic(0, "%s", strnomem
);
68 register const char *str
;
73 if ((cp
= malloc(n
+ 1)) == NULL
)
74 Panic(0, "%s", strnomem
);
77 bcopy((char *)str
, cp
, n
);
83 /* cheap strstr replacement */
89 int npat
= strlen(pat
);
91 if (!strncmp(str
, pat
, npat
))
102 extern char *sys_errlist
[];
105 if (err
> 0 && err
< sys_nerr
)
106 return sys_errlist
[err
];
107 sprintf(er
, "Error %d", err
);
121 if (n
> flayer
->l_width
- 1)
122 n
= flayer
->l_width
- 1;
123 l
= (flayer
->l_width
- 1 - n
) / 2;
124 LPutStr(flayer
, str
, n
, &mchar_blank
, l
, y
);
128 leftline(str
, y
, rend
)
134 struct mchar mchar_dol
;
136 mchar_dol
= mchar_blank
;
137 mchar_dol
.image
= '$';
141 if (n
> flayer
->l_width
- 1)
142 n
= flayer
->l_width
- 1;
143 LPutStr(flayer
, str
, n
, rend
? rend
: &mchar_blank
, 0, y
);
145 LPutChar(flayer
, &mchar_dol
, n
, y
);
153 register char *p
= s
;
172 /* unixware has /dev/pts012 as synonym for /dev/pts/12 */
173 if (!strncmp(nam
, "/dev/pts", 8) && nam
[8] >= '0' && nam
[8] <= '9')
176 sprintf(b
, "pts/%d", atoi(nam
+ 8));
180 if (p
= strstr(nam
,"/dev/"))
185 if (strncmp(nam
, "/dev/", 5) == 0)
197 sigret_t (*xsignal(sig
, func
))
204 sigret_t (*func
) __P(SIGPROTOARG
);
206 struct sigaction osa
, sa
;
207 sa
.sa_handler
= func
;
208 (void)sigemptyset(&sa
.sa_mask
);
210 sa
.sa_flags
= (sig
== SIGCHLD
? SA_RESTART
: 0);
214 if (sigaction(sig
, &sa
, &osa
))
215 return (sigret_t (*)__P(SIGPROTOARG
))-1;
216 return osa
.sa_handler
;
222 * hpux has berkeley signal semantics if we use sigvector,
223 * but not, if we use signal, so we define our own signal() routine.
225 void (*xsignal(sig
, func
)) __P(SIGPROTOARG
)
227 void (*func
) __P(SIGPROTOARG
);
229 struct sigvec osv
, sv
;
231 sv
.sv_handler
= func
;
232 sv
.sv_mask
= sigmask(sig
);
233 sv
.sv_flags
= SV_BSDSIG
;
234 if (sigvector(sig
, &sv
, &osv
) < 0)
235 return (void (*)__P(SIGPROTOARG
))(BADSIG
);
236 return osv
.sv_handler
;
252 if (seteuid(euid
) == 0)
256 Panic(errno
, "seteuid");
264 Panic(errno
, "setegid");
267 #else /* HAVE_SETEUID */
268 # ifdef HAVE_SETREUID
279 if ((int)getuid() != euid
)
281 if (setreuid(oeuid
, euid
))
282 Panic(errno
, "setreuid");
294 if ((int)getgid() != egid
)
296 if (setregid(oegid
, egid
))
297 Panic(errno
, "setregid");
300 # endif /* HAVE_SETREUID */
301 #endif /* HAVE_SETEUID */
305 #ifdef NEED_OWN_BCOPY
308 register char *s1
, *s2
;
311 if (s1
< s2
&& s2
< s1
+ len
)
322 #endif /* NEED_OWN_BCOPY */
329 bcopy((char *)blank
, p
, n
);
339 (void) kill(pid
, sig
);
344 * Modern versions of Solaris include fdwalk(3c) which allows efficient
345 * implementation of closing open descriptors; this is helpful because
346 * the default file descriptor limit has risen to 65k.
349 close_func(cb_data
, fd
)
353 int except
= *(int *)cb_data
;
354 if (fd
> 2 && fd
!= except
)
360 closeallfiles(except
)
363 (void)fdwalk(close_func
, &except
);
366 #else /* HAVE_FDWALK */
369 closeallfiles(except
)
376 if ((getrlimit(RLIMIT_NOFILE
, &rl
) == 0) && rl
.rlim_max
!= RLIM_INFINITY
)
380 #if defined(SYSV) && defined(NOFILE) && !defined(ISC)
382 #else /* SYSV && !ISC */
384 #endif /* SYSV && !ISC */
390 #endif /* HAVE_FDWALK */
394 * Security - switch to real uid
399 static sigret_t (*Usersigcld
)__P(SIGPROTOARG
);
407 if (eff_uid
== real_uid
&& eff_gid
== real_gid
)
409 Usersigcld
= signal(SIGCHLD
, SIG_DFL
);
410 debug("UserContext: forking.\n");
411 switch (UserPID
= fork())
417 signal(SIGHUP
, SIG_DFL
);
418 signal(SIGINT
, SIG_IGN
);
419 signal(SIGQUIT
, SIG_DFL
);
420 signal(SIGTERM
, SIG_DFL
);
422 signal(SIGTTIN
, SIG_DFL
);
423 signal(SIGTTOU
, SIG_DFL
);
443 if (eff_uid
== real_uid
&& eff_gid
== real_gid
)
465 if (eff_uid
== real_uid
&& eff_gid
== real_gid
)
469 while ((errno
= 0, i
= wait(&wstat
)) != UserPID
)
470 if (i
< 0 && errno
!= EINTR
)
472 (void) signal(SIGCHLD
, Usersigcld
);
475 return WEXITSTATUS(wstat
);
487 if (link(old
, new) < 0)
501 if (ch
< ' ' || ch
== 0x7f)
509 *p
++ = (ch
>> 6 & 7) + '0';
510 *p
++ = (ch
>> 3 & 7) + '0';
511 *p
++ = (ch
>> 0 & 7) + '0';
519 AddXChars(buf
, len
, str
)
530 len
-= 4; /* longest sequence produced by AddXChar() */
531 for (p
= buf
; p
< buf
+ len
&& *str
; str
++)
536 p
+= AddXChar(p
, *str
);
545 opendebug(new, shout
)
551 mode_t oumask
= umask(0);
553 int oumask
= umask(0);
558 (void) mkdir(DEBUGDIR
, 0777);
559 sprintf(buf
, shout
? "%s/SCREEN.%d" : "%s/screen.%d", DEBUGDIR
, getpid());
560 if (!(dfp
= fopen(buf
, new ? "w" : "a")))
563 (void)chmod(buf
, 0666);
566 debug("opendebug: done.\n");
577 t
.tv_sec
= (long) (msec
/ 1000);
578 t
.tv_usec
= (long) ((msec
% 1000) * 1000);
579 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
584 * This uses either setenv() or putenv(). If it is putenv() we cannot dare
585 * to free the buffer after putenv(), unless it it the one found in putenv.c
596 if ((buf
= (char *)malloc((l
= strlen(var
)) +
597 strlen(value
) + 2)) == NULL
)
604 strcpy(buf
+ l
+ 1, value
);
608 * we use our own putenv(), knowing that it does a malloc()
609 * the string space, we can free our buf now.
612 # else /* NEEDSETENV */
614 * For all sysv-ish systems that link a standard putenv()
615 * the string-space buf is added to the environment and must not
616 * be freed, or modified.
617 * We are sorry to say that memory is lost here, when setting
618 * the same variable again and again.
620 # endif /* NEEDSETENV */
621 #else /* USESETENV */
623 setenv(var
, value
, 1);
626 # endif /* HAVE_SETENV_3 */
627 #endif /* USESETENV */
632 * This is a replacement for the buggy _delay function from the termcap
633 * emulation of libcurses, which ignores ospeed.
638 int (*outc
) __P((int));
642 static short osp2pad
[] = {
643 0,2000,1333,909,743,666,500,333,166,83,55,41,20,10,5,2,1,1
646 if (ospeed
<= 0 || ospeed
>= (int)(sizeof(osp2pad
)/sizeof(*osp2pad
)))
648 pad
=osp2pad
[ospeed
];
649 delay
= (delay
+ pad
/ 2) / pad
;
655 #endif /* TERMINFO */
661 # define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0)))
662 # define xva_list char *
670 return a
? (char *)&c
- (char *)&b
: (char *)&b
- (char *)&a
;
674 xsnprintf(s
, n
, fmt
, p1
, p2
, p3
, p4
, p5
, p6
)
678 unsigned long p1
, p2
, p3
, p4
, p5
, p6
;
680 int xvsnprintf
__P((char *, int, char *, xva_list
));
681 return xvsnprintf(s
, n
, fmt
, (char *)&fmt
+ xsnoff(1, 0, 0));
686 # define xva_arg(s, t, tn) va_arg(s, t)
687 # define xva_list va_list
692 #if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF)
695 xvsnprintf(s
, n
, fmt
, stack
)
703 char myf
[10], buf
[20];
709 while(arg
|| (sf
= index(f
, '%')) || (sf
= f
+ strlen(f
)))
718 i
= argl
> n
- 1 ? n
- 1 : argl
;
737 while (((*f
>= '0' && *f
<='9') || *f
== '#') && myfp
- myf
< 8)
752 i
= xva_arg(stack
, int, 0);
753 sprintf(buf
, myf
, i
);
757 arg
= xva_arg(stack
, char *, 1);