~dannf/ubuntu/saucy/screen/lp1213278-from-debian

« back to all changes in this revision

Viewing changes to misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathaniel McCallum
  • Date: 2004-09-03 15:15:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040903151533-px02yqlrchs4fv2t
Tags: upstream-4.0.2
ImportĀ upstreamĀ versionĀ 4.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
20
 *
 
21
 ****************************************************************
 
22
 */
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>   /* mkdir() declaration */
 
26
#include <signal.h>
 
27
 
 
28
#include "config.h"
 
29
#include "screen.h"
 
30
#include "extern.h"
 
31
 
 
32
#ifdef SVR4
 
33
# include <sys/resource.h>
 
34
#endif
 
35
 
 
36
extern struct layer *flayer;
 
37
 
 
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;
 
43
 
 
44
#ifdef HAVE_FDWALK
 
45
static int close_func __P((void *, int));
 
46
#endif
 
47
 
 
48
char *
 
49
SaveStr(str)
 
50
register const char *str;
 
51
{
 
52
  register char *cp;
 
53
 
 
54
  if ((cp = malloc(strlen(str) + 1)) == NULL)
 
55
    Panic(0, strnomem);
 
56
  else
 
57
    strcpy(cp, str);
 
58
  return cp;
 
59
}
 
60
 
 
61
char *
 
62
SaveStrn(str, n)
 
63
register const char *str;
 
64
int n;
 
65
{
 
66
  register char *cp;
 
67
 
 
68
  if ((cp = malloc(n + 1)) == NULL)
 
69
    Panic(0, strnomem);
 
70
  else
 
71
    {
 
72
      bcopy((char *)str, cp, n);
 
73
      cp[n] = 0;
 
74
    }
 
75
  return cp;
 
76
}
 
77
 
 
78
/* cheap strstr replacement */
 
79
char *
 
80
InStr(str, pat)
 
81
char *str;
 
82
const char *pat;
 
83
{
 
84
  int npat = strlen(pat);
 
85
  for (;*str; str++)
 
86
    if (!strncmp(str, pat, npat))
 
87
      return str;
 
88
  return 0;
 
89
}
 
90
 
 
91
#ifndef HAVE_STRERROR
 
92
char *
 
93
strerror(err)
 
94
int err;
 
95
{
 
96
  extern int sys_nerr;
 
97
  extern char *sys_errlist[];
 
98
 
 
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;
 
104
}
 
105
#endif
 
106
 
 
107
void
 
108
centerline(str, y)
 
109
char *str;
 
110
int y;
 
111
{
 
112
  int l, n;
 
113
 
 
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);
 
120
}
 
121
 
 
122
void
 
123
leftline(str, y)
 
124
char *str;
 
125
int y;
 
126
{
 
127
  int l, n;
 
128
  struct mchar mchar_dol;
 
129
 
 
130
  mchar_dol = mchar_blank;
 
131
  mchar_dol.image = '$';
 
132
 
 
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);
 
140
}
 
141
 
 
142
 
 
143
char *
 
144
Filename(s)
 
145
char *s;
 
146
{
 
147
  register char *p = s;
 
148
 
 
149
  if (p)
 
150
    while (*p)
 
151
      if (*p++ == '/')
 
152
        s = p;
 
153
  return s;
 
154
}
 
155
 
 
156
char *
 
157
stripdev(nam)
 
158
char *nam;
 
159
{
 
160
#ifdef apollo
 
161
  char *p;
 
162
  
 
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')
 
168
    {
 
169
      static char b[13];
 
170
      sprintf(b, "pts/%d", atoi(nam + 8));
 
171
      return b;
 
172
    }
 
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;
 
183
}
 
184
 
 
185
 
 
186
/*
 
187
 *    Signal handling
 
188
 */
 
189
 
 
190
#ifdef POSIX
 
191
sigret_t (*xsignal(sig, func))
 
192
# ifndef __APPLE__
 
193
 __P(SIGPROTOARG)
 
194
# else
 
195
()
 
196
# endif
 
197
int sig;
 
198
sigret_t (*func) __P(SIGPROTOARG);
 
199
{
 
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;
 
211
}
 
212
 
 
213
#else
 
214
# ifdef hpux
 
215
/*
 
216
 * hpux has berkeley signal semantics if we use sigvector,
 
217
 * but not, if we use signal, so we define our own signal() routine.
 
218
 */
 
219
void (*xsignal(sig, func)) __P(SIGPROTOARG)
 
220
int sig;
 
221
void (*func) __P(SIGPROTOARG);
 
222
{
 
223
  struct sigvec osv, sv;
 
224
 
 
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;
 
231
}
 
232
# endif /* hpux */
 
233
#endif  /* POSIX */
 
234
 
 
235
 
 
236
/*
 
237
 *    uid/gid handling
 
238
 */
 
239
 
 
240
#ifdef HAVE_SETEUID
 
241
 
 
242
void
 
243
xseteuid(euid)
 
244
int euid;
 
245
{
 
246
  if (seteuid(euid) == 0)
 
247
    return;
 
248
  seteuid(0);
 
249
  if (seteuid(euid))
 
250
    Panic(errno, "seteuid");
 
251
}
 
252
 
 
253
void
 
254
xsetegid(egid)
 
255
int egid;
 
256
{
 
257
  if (setegid(egid))
 
258
    Panic(errno, "setegid");
 
259
}
 
260
 
 
261
#else /* HAVE_SETEUID */
 
262
# ifdef HAVE_SETREUID
 
263
 
 
264
void
 
265
xseteuid(euid)
 
266
int euid;
 
267
{
 
268
  int oeuid;
 
269
 
 
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");
 
277
}
 
278
 
 
279
void
 
280
xsetegid(egid)
 
281
int egid;
 
282
{
 
283
  int oegid;
 
284
 
 
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");
 
292
}
 
293
 
 
294
# endif /* HAVE_SETREUID */
 
295
#endif /* HAVE_SETEUID */
 
296
 
 
297
 
 
298
 
 
299
#ifdef NEED_OWN_BCOPY
 
300
void
 
301
xbcopy(s1, s2, len)
 
302
register char *s1, *s2;
 
303
register int len;
 
304
{
 
305
  if (s1 < s2 && s2 < s1 + len)
 
306
    {
 
307
      s1 += len;
 
308
      s2 += len;
 
309
      while (len-- > 0)
 
310
        *--s2 = *--s1;
 
311
    }
 
312
  else
 
313
    while (len-- > 0)
 
314
      *s2++ = *s1++;
 
315
}
 
316
#endif  /* NEED_OWN_BCOPY */
 
317
 
 
318
void
 
319
bclear(p, n)
 
320
char *p;
 
321
int n;
 
322
{
 
323
  bcopy((char *)blank, p, n);
 
324
}
 
325
 
 
326
 
 
327
void
 
328
Kill(pid, sig)
 
329
int pid, sig;
 
330
{
 
331
  if (pid < 2)
 
332
    return;
 
333
  (void) kill(pid, sig);
 
334
}
 
335
 
 
336
#ifdef HAVE_FDWALK
 
337
/*
 
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.
 
341
 */
 
342
static int
 
343
close_func(cb_data, fd)
 
344
void *cb_data;
 
345
int fd;
 
346
{
 
347
  int except = *(int *)cb_data;
 
348
  if (fd > 2 && fd != except)
 
349
    (void)close(fd);
 
350
  return (0);
 
351
}
 
352
 
 
353
void
 
354
closeallfiles(except)
 
355
int except;
 
356
{
 
357
  (void)fdwalk(close_func, &except);
 
358
}
 
359
 
 
360
#else /* HAVE_FDWALK */
 
361
 
 
362
void
 
363
closeallfiles(except)
 
364
int except;
 
365
{
 
366
  int f;
 
367
#ifdef SVR4
 
368
  struct rlimit rl;
 
369
  
 
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);
 
382
}
 
383
 
 
384
#endif /* HAVE_FDWALK */
 
385
 
 
386
 
 
387
/*
 
388
 *  Security - switch to real uid
 
389
 */
 
390
 
 
391
#ifndef USE_SETEUID
 
392
static int UserPID;
 
393
static sigret_t (*Usersigcld)__P(SIGPROTOARG);
 
394
#endif
 
395
static int UserSTAT;
 
396
 
 
397
int
 
398
UserContext()
 
399
{
 
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())
 
406
    {
 
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;
 
424
    }
 
425
#else
 
426
  xseteuid(real_uid);
 
427
  xsetegid(real_gid);
 
428
  return 1;
 
429
#endif
 
430
}
 
431
 
 
432
void
 
433
UserReturn(val)
 
434
int val;
 
435
{
 
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
 
446
}
 
447
 
 
448
int
 
449
UserStatus()
 
450
{
 
451
#ifndef USE_SETEUID
 
452
  int i;
 
453
# ifdef BSDWAIT
 
454
  union wait wstat;
 
455
# else
 
456
  int wstat;
 
457
# endif
 
458
 
 
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
 
473
}
 
474
 
 
475
#ifndef HAVE_RENAME
 
476
int
 
477
rename (old, new)
 
478
char *old;
 
479
char *new;
 
480
{
 
481
  if (link(old, new) < 0)
 
482
    return -1;
 
483
  return unlink(old);
 
484
}
 
485
#endif
 
486
 
 
487
 
 
488
int
 
489
AddXChar(buf, ch)
 
490
char *buf;
 
491
int ch;
 
492
{
 
493
  char *p = buf;
 
494
 
 
495
  if (ch < ' ' || ch == 0x7f)
 
496
    {
 
497
      *p++ = '^';
 
498
      *p++ = ch ^ 0x40;
 
499
    }
 
500
  else if (ch >= 0x80)
 
501
    {
 
502
      *p++ = '\\';
 
503
      *p++ = (ch >> 6 & 7) + '0';
 
504
      *p++ = (ch >> 3 & 7) + '0';
 
505
      *p++ = (ch >> 0 & 7) + '0';
 
506
    }
 
507
  else
 
508
    *p++ = ch;
 
509
  return p - buf;
 
510
}
 
511
 
 
512
int
 
513
AddXChars(buf, len, str)
 
514
char *buf, *str;
 
515
int len;
 
516
{
 
517
  char *p;
 
518
 
 
519
  if (str == 0)
 
520
    {
 
521
      *buf = 0;
 
522
      return 0;
 
523
    }
 
524
  len -= 4;     /* longest sequence produced by AddXChar() */
 
525
  for (p = buf; p < buf + len && *str; str++)
 
526
    {
 
527
      if (*str == ' ')
 
528
        *p++ = *str;
 
529
      else
 
530
        p += AddXChar(p, *str);
 
531
    }
 
532
  *p = 0;
 
533
  return p - buf;
 
534
}
 
535
 
 
536
 
 
537
#ifdef DEBUG
 
538
void
 
539
opendebug(new, shout)
 
540
int new, shout;
 
541
{
 
542
  char buf[256];
 
543
 
 
544
#ifdef _MODE_T
 
545
  mode_t oumask = umask(0);
 
546
#else
 
547
  int oumask = umask(0);
 
548
#endif
 
549
 
 
550
  ASSERT(!dfp);
 
551
 
 
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);
 
558
 
 
559
  (void)umask(oumask);
 
560
  debug("opendebug: done.\n");
 
561
}
 
562
#endif /* DEBUG */
 
563
 
 
564
void
 
565
sleep1000(msec)
 
566
int msec;
 
567
 
 
568
{
 
569
  struct timeval t;
 
570
 
 
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);
 
574
}
 
575
 
 
576
 
 
577
/*
 
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
 
580
 */
 
581
void
 
582
xsetenv(var, value)
 
583
char *var;
 
584
char *value;
 
585
{
 
586
#ifndef USESETENV
 
587
  char *buf;
 
588
  int l;
 
589
 
 
590
  if ((buf = (char *)malloc((l = strlen(var)) +
 
591
                            strlen(value) + 2)) == NULL)
 
592
    {
 
593
      Msg(0, strnomem);
 
594
      return;
 
595
    }
 
596
  strcpy(buf, var);
 
597
  buf[l] = '=';
 
598
  strcpy(buf + l + 1, value);
 
599
  putenv(buf);
 
600
# ifdef NEEDPUTENV
 
601
  /*
 
602
   * we use our own putenv(), knowing that it does a malloc()
 
603
   * the string space, we can free our buf now.
 
604
   */
 
605
  free(buf);
 
606
# else /* NEEDSETENV */
 
607
  /*
 
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.
 
613
   */
 
614
# endif /* NEEDSETENV */
 
615
#else /* USESETENV */
 
616
# if defined(linux) || defined(__convex__) || (BSD >= 199103)
 
617
  setenv(var, value, 1);
 
618
# else
 
619
  setenv(var, value);
 
620
# endif /* linux || convex || BSD >= 199103 */
 
621
#endif /* USESETENV */
 
622
}
 
623
 
 
624
#ifdef TERMINFO
 
625
/*
 
626
 * This is a replacement for the buggy _delay function from the termcap
 
627
 * emulation of libcurses, which ignores ospeed.
 
628
 */
 
629
int
 
630
_delay(delay, outc)
 
631
register int delay;
 
632
int (*outc) __P((int));
 
633
{
 
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
 
638
  };
 
639
 
 
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;
 
647
}
 
648
 
 
649
# ifdef linux
 
650
 
 
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...
 
655
 */
 
656
 
 
657
int (*save_outc) __P((int));
 
658
 
 
659
#  undef tputs
 
660
 
 
661
void
 
662
xtputs(str, affcnt, outc)
 
663
char *str;
 
664
int affcnt;
 
665
int (*outc) __P((int));
 
666
{
 
667
  extern int tputs __P((const char *, int, int (*)(int)));
 
668
  save_outc = outc;
 
669
  tputs(str, affcnt, outc);
 
670
}
 
671
 
 
672
int
 
673
_nc_timed_wait(mode, ms, tlp)
 
674
int mode, ms, *tlp;
 
675
{
 
676
  _delay(ms * 10, save_outc);
 
677
  return 0;
 
678
}
 
679
 
 
680
# endif /* linux */
 
681
 
 
682
#endif /* TERMINFO */
 
683
 
 
684
 
 
685
 
 
686
#ifndef USEVARARGS
 
687
 
 
688
# define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0)))
 
689
# define xva_list char *
 
690
 
 
691
static int
 
692
xsnoff(a, b, c)
 
693
int a;
 
694
char *b;
 
695
int c;
 
696
{
 
697
  return a ? (char *)&c  - (char *)&b : (char *)&b - (char *)&a;
 
698
}
 
699
 
 
700
int
 
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;
 
706
{
 
707
  int xvsnprintf __P((char *, int, char *, xva_list));
 
708
  return xvsnprintf(s, n, fmt, (char *)&fmt + xsnoff(1, 0, 0));
 
709
}
 
710
 
 
711
#else
 
712
 
 
713
# define xva_arg(s, t, tn) va_arg(s, t)
 
714
# define xva_list va_list
 
715
 
 
716
#endif
 
717
 
 
718
 
 
719
#if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF)
 
720
 
 
721
int
 
722
xvsnprintf(s, n, fmt, stack)
 
723
char *s;
 
724
int n;
 
725
char *fmt;
 
726
xva_list stack;
 
727
{
 
728
  char *f, *sf = 0;
 
729
  int i, on, argl = 0;
 
730
  char myf[10], buf[20];
 
731
  char *arg, *myfp;
 
732
 
 
733
  on = n;
 
734
  f = fmt;
 
735
  arg = 0;
 
736
  while(arg || (sf = index(f, '%')) || (sf = f + strlen(f)))
 
737
    {
 
738
      if (arg == 0)
 
739
        {
 
740
          arg = f;
 
741
          argl = sf - f;
 
742
        }
 
743
      if (argl)
 
744
        {
 
745
          i = argl > n - 1 ? n - 1 : argl;
 
746
          strncpy(s, arg, i);
 
747
          s += i;
 
748
          n -= i;
 
749
          if (i < argl)
 
750
            {
 
751
              *s = 0;
 
752
              return on;
 
753
            }
 
754
        }
 
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])
 
771
        {
 
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;
 
791
        }
 
792
      argl = strlen(arg);
 
793
    }
 
794
  *s = 0;
 
795
  return on - n;
 
796
}
 
797
 
 
798
#endif