source: rtems/cpukit/pppd/chat.c @ a6abd67

4.104.114.84.95
Last change on this file since a6abd67 was a6abd67, checked in by Joel Sherrill <joel.sherrill@…>, on 11/25/00 at 19:42:21

2000-11-25 Antti P Miettinen <antti.p.miettinen@…>

  • wrapup/Makefile.am: Added modem subdir.
  • configure.in, Makefile.am: Added modem subdir.
  • net/Makefile.am: Added if_pppvar.h, pppcompress.h.
  • pppd/Makefile.am: Added pppmain.c (which needs work).
  • pppd/chat.c, pppd/fsm.c, pppd/fsm.h, pppd/ipxcp.c, pppd/main.c, pppd/ppp_tty.c, pppd/upap.c: Changes from Thomas Doerfler <Thomas.Doerfler@…> and cosmetic changes by me. Actually main.c and ppp_tty.c should be scratched. The modem subdir has the real ppp_tty.c and the real pppd main is in pppmain.c.
  • Property mode set to 100644
File size: 18.5 KB
Line 
1/*
2 *      Chat -- a program for automatic session establishment (i.e. dial
3 *              the phone and log in).
4 *
5 * Standard termination codes:
6 *  0 - successful completion of the script
7 *  1 - invalid argument, expect string too large, etc.
8 *  2 - error on an I/O operation or fatal error condition.
9 *  3 - timeout waiting for a simple string.
10 *  4 - the first string declared as "ABORT"
11 *  5 - the second string declared as "ABORT"
12 *  6 - ... and so on for successive ABORT strings.
13 *
14 *      This software is in the public domain.
15 *
16 * -----------------
17 *      added -T and -U option and \T and \U substitution to pass a phone
18 *      number into chat script. Two are needed for some ISDN TA applications.
19 *      Keith Dart <kdart@cisco.com>
20 *     
21 *
22 *      Added SAY keyword to send output to stderr.
23 *      This allows to turn ECHO OFF and to output specific, user selected,
24 *      text to give progress messages. This best works when stderr
25 *      exists (i.e.: pppd in nodetach mode).
26 *
27 *      Added HANGUP directives to allow for us to be called
28 *      back. When HANGUP is set to NO, chat will not hangup at HUP signal.
29 *      We rely on timeouts in that case.
30 *
31 *      Added CLR_ABORT to clear previously set ABORT string. This has been
32 *      dictated by the HANGUP above as "NO CARRIER" (for example) must be
33 *      an ABORT condition until we know the other host is going to close
34 *      the connection for call back. As soon as we have completed the
35 *      first stage of the call back sequence, "NO CARRIER" is a valid, non
36 *      fatal string. As soon as we got called back (probably get "CONNECT"),
37 *      we should re-arm the ABORT "NO CARRIER". Hence the CLR_ABORT command.
38 *      Note that CLR_ABORT packs the abort_strings[] array so that we do not
39 *      have unused entries not being reclaimed.
40 *
41 *      In the same vein as above, added CLR_REPORT keyword.
42 *
43 *      Allow for comments. Line starting with '#' are comments and are
44 *      ignored. If a '#' is to be expected as the first character, the
45 *      expect string must be quoted.
46 *
47 *
48 *              Francis Demierre <Francis@SwissMail.Com>
49 *              Thu May 15 17:15:40 MET DST 1997
50 *
51 *
52 *      Added -r "report file" switch & REPORT keyword.
53 *              Robert Geer <bgeer@xmission.com>
54 *
55 *      Added -s "use stderr" and -S "don't use syslog" switches.
56 *              June 18, 1997
57 *              Karl O. Pinc <kop@meme.com>
58 *
59 *
60 *      Added -e "echo" switch & ECHO keyword
61 *              Dick Streefland <dicks@tasking.nl>
62 *
63 *
64 *      Considerable updates and modifications by
65 *              Al Longyear <longyear@pobox.com>
66 *              Paul Mackerras <paulus@cs.anu.edu.au>
67 *
68 *
69 *      The original author is:
70 *
71 *              Karl Fox <karl@MorningStar.Com>
72 *              Morning Star Technologies, Inc.
73 *              1760 Zollinger Road
74 *              Columbus, OH  43221
75 *              (614)451-1883
76 *
77 *
78 */
79
80#ifndef lint
81/* static char rcsid[] = ""; */
82#endif
83
84#include <stdio.h>
85#include <ctype.h>
86#include <time.h>
87#include <fcntl.h>
88#include <signal.h>
89#include <errno.h>
90#include <string.h>
91#include <stdlib.h>
92#include <unistd.h>
93#include <sys/types.h>
94#include <sys/stat.h>
95#include <syslog.h>
96
97#undef  TERMIOS
98#define TERMIOS
99
100
101#include <termios.h>
102
103#define STR_LEN 1024
104char temp2[STR_LEN];
105
106#ifndef SIGTYPE
107#define SIGTYPE void
108#endif
109
110#undef __P
111#undef __V
112
113#ifdef __STDC__
114#include <stdarg.h>
115#define __V(x)  x
116#define __P(x)  x
117#else
118#include <varargs.h>
119#define __V(x)  (va_alist) va_dcl
120#define __P(x)  ()
121#define const
122#endif
123
124#ifndef O_NONBLOCK
125#define O_NONBLOCK      O_NDELAY
126#endif
127
128
129/*************** Micro getopt() *********************************************/
130#define OPTION(c,v)     (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
131                                (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
132                                &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
133#define OPTARG(c,v)     (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
134                                (_O=4,(char*)0):(char*)0)
135#define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
136#define ARG(c,v)        (c?(--c,*v++):(char*)0)
137
138#if 0
139static int _O = 0;              /* Internal state */
140#endif
141/*************** Micro getopt() *********************************************/
142
143char *program_name;
144
145#define MAX_ABORTS              5
146#define MAX_REPORTS             5
147#define DEFAULT_CHAT_TIMEOUT    45
148#define fcntl(a, b,c ) 0
149#define MAX_TIMEOUTS 10
150
151int echo          = 0;
152int verbose       = 0;
153int to_log        = 1;
154int to_stderr     = 0;
155int Verbose       = 0;
156int quiet         = 0;
157int report        = 0;
158int exit_code     = 0;
159static int speed=0;
160char *report_file = (char *) 0;
161char *chat_file   = (char *) 0;
162char *phone_num   = (char *) 0;
163char *phone_num2  = (char *) 0;
164int chat_timeout       = DEFAULT_CHAT_TIMEOUT;
165static int timeout       = DEFAULT_CHAT_TIMEOUT;
166int have_tty_parameters = 0;
167
168#ifdef TERMIOS
169#define term_parms struct termios
170#define get_term_param(param) tcgetattr(modem_fd, param)
171#define set_term_param(param) tcsetattr(modem_fd, TCSANOW, param)
172struct termios saved_tty_parameters;
173#endif
174
175char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ASWER","RINGING\r\n\r\nRINGING"};
176char *fail_reason = (char *)0,
177        fail_buffer[50];
178int n_aborts = MAX_ABORTS, abort_next = 0, timeout_next = 0, echo_next = 0;
179int clear_abort_next = 0;
180
181char *report_string[MAX_REPORTS] ;
182char  report_buffer[50] ;
183int n_reports = 0, report_next = 0, report_gathering = 0 ;
184int clear_report_next = 0;
185
186int say_next = 0, hup_next = 0;
187
188void *dup_mem __P((void *b, size_t c));
189void *copy_of __P((char *s));
190/*
191SIGTYPE sigalrm __P((int signo));
192SIGTYPE sigint __P((int signo));
193SIGTYPE sigterm __P((int signo));
194SIGTYPE sighup __P((int signo));
195*/
196void unalarm __P((void));
197void init __P((void));
198void set_tty_parameters __P((void));
199void echo_stderr __P((int));
200void break_sequence __P((void));
201void terminate __P((int status));
202void do_file __P((char *chat_file));
203int  get_string __P((register char *string));
204int  put_string __P((register char *s));
205int  write_char __P((int c));
206int  put_char __P((int c));
207int  get_char __P((void));
208void chat_send __P((register char *s));
209char *character __P((int c));
210void chat_expect __P((register char *s));
211char *clean __P((register char *s, int sending));
212void break_sequence __P((void));
213void terminate __P((int status));
214void pack_array __P((char **array, int end));
215char *expect_strtok __P((char *, char *));
216int vfmtmsg __P((char *, int, const char *, va_list));  /* vsprintf++ */
217
218#if 0
219int usleep( long usec );                                  /* returns 0 if ok, else -1 */
220#endif
221   
222extern int input_fd,output_fd;
223
224int main __P((int, char *[]));
225
226void *dup_mem(b, c)
227void *b;
228size_t c;
229{
230    void *ans = malloc (c);
231    if (!ans)
232                return NULL;
233
234    memcpy (ans, b, c);
235    return ans;
236}
237
238void *copy_of (s)
239char *s;
240{
241    return dup_mem (s, strlen (s) + 1);
242}
243
244/*
245 * chat [ -v ] [-T number] [-U number] [ -t timeout ] [ -f chat-file ] \
246 * [ -r report-file ] \
247 *              [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
248 *
249 *      Perform a UUCP-dialer-like chat script on stdin and stdout.
250 */
251char *getnextcommand(char **string)
252{
253        char *buf=*string,*res;
254        res=strchr(buf,'@');
255        if (res==NULL)
256                return NULL;
257        *res='\0';
258        *string=res+1;
259        return buf;
260}
261
262 
263extern int modem_fd;
264int
265        chatmain(argv)
266     char *argv;
267{
268    char *arg;
269        int i;
270        char *t;
271        exit_code=0;
272        speed=0;
273/*
274 * Default the report file to the stderr location
275 */
276/*    if (report_fp == NULL)
277        report_fp = stderr;
278*/
279    init();
280        while ( (arg = getnextcommand(&argv)) != NULL) {
281            chat_expect(arg);
282                if (exit_code>0) break;
283            t=temp2;
284
285                while(*t)
286                {
287                        if (strncmp("CARRIER",t,7)==0)
288                        {/* parse speed information */
289                                i=0;
290                                while(!isdigit(t[i]))
291                                        i++;
292                                t=&t[i];
293                                i=0;
294                                while(isdigit(t[i]))
295                                        i++;
296                                t[i]=0;
297                                sscanf(t,"%d",&speed);
298                                break;                         
299                        }
300                        t++;
301                }
302            if ((arg = getnextcommand(&argv)) != NULL)
303                chat_send(arg);
304                if (exit_code>0) break;
305        }
306
307    if (exit_code) return exit_code;
308    return -speed;
309}
310
311
312
313/*
314 *      Print an error message and terminate.
315 */
316
317void init()
318{
319    set_tty_parameters();
320        speed=0;
321}
322
323void set_tty_parameters()
324{
325    term_parms t;
326
327        if (get_term_param (&t) < 0)
328                syslog(LOG_NOTICE,"Can't get terminal parameters:")
329                ;
330       
331    saved_tty_parameters = t;
332    have_tty_parameters  = 1;
333    t.c_iflag     |= IGNBRK | ISTRIP | IGNPAR;
334    t.c_oflag      = 0;
335    t.c_lflag      = 0;
336    t.c_cc[VERASE] =
337    t.c_cc[VKILL]  = 0;
338    t.c_cc[VMIN]   = 0;
339    t.c_cc[VTIME]  = 1;
340    if (set_term_param (&t) < 0)
341                syslog(LOG_NOTICE,"Can't set terminal parameters:")
342                ;
343}
344
345void break_sequence()
346{
347
348/*    tcsendbreak (0, 0);*/
349}
350
351/*void terminate(status)
352int status;
353{
354    echo_stderr(-1);
355
356    if (have_tty_parameters) {
357        if (set_term_param (&saved_tty_parameters) < 0)
358            fatal(2, "Can't restore terminal parameters: %m");
359    }
360}
361*/
362/*
363 *      'Clean up' this string.
364 */
365char *clean(s, sending)
366register char *s;
367int sending;  /* set to 1 when sending (putting) this string. */
368{
369    char temp[STR_LEN], cur_chr;
370    register char *s1, *phchar;
371    int add_return = sending;
372#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
373
374    s1 = temp;
375    while (*s) {
376        cur_chr = *s++;
377        if (cur_chr == '^') {
378            cur_chr = *s++;
379            if (cur_chr == '\0') {
380                *s1++ = '^';
381                break;
382            }
383            cur_chr &= 0x1F;
384            if (cur_chr != 0) {
385                *s1++ = cur_chr;
386            }
387            continue;
388        }
389
390        if (cur_chr != '\\') {
391            *s1++ = cur_chr;
392            continue;
393        }
394
395        cur_chr = *s++;
396        if (cur_chr == '\0') {
397            if (sending) {
398                *s1++ = '\\';
399                *s1++ = '\\';
400            }
401            break;
402        }
403
404        switch (cur_chr) {
405        case 'b':
406            *s1++ = '\b';
407            break;
408
409        case 'c':
410            if (sending && *s == '\0')
411                add_return = 0;
412            else
413                *s1++ = cur_chr;
414            break;
415
416        case '\\':
417        case 'K':
418        case 'p':
419        case 'd':
420            if (sending)
421                *s1++ = '\\';
422
423            *s1++ = cur_chr;
424            break;
425
426        case 'T':
427            if (sending && phone_num) {
428                for ( phchar = phone_num; *phchar != '\0'; phchar++)
429                    *s1++ = *phchar;
430            }
431            else {
432                *s1++ = '\\';
433                *s1++ = 'T';
434            }
435            break;
436
437        case 'U':
438            if (sending && phone_num2) {
439                for ( phchar = phone_num2; *phchar != '\0'; phchar++)
440                    *s1++ = *phchar;
441            }
442            else {
443                *s1++ = '\\';
444                *s1++ = 'U';
445            }
446            break;
447
448        case 'q':
449            quiet = 1;
450            break;
451
452        case 'r':
453            *s1++ = '\r';
454            break;
455
456        case 'n':
457            *s1++ = '\n';
458            break;
459
460        case 's':
461            *s1++ = ' ';
462            break;
463
464        case 't':
465            *s1++ = '\t';
466            break;
467
468        case 'N':
469            if (sending) {
470                *s1++ = '\\';
471                *s1++ = '\0';
472            }
473            else
474                *s1++ = 'N';
475            break;
476           
477        default:
478            if (isoctal (cur_chr)) {
479                cur_chr &= 0x07;
480                if (isoctal (*s)) {
481                    cur_chr <<= 3;
482                    cur_chr |= *s++ - '0';
483                    if (isoctal (*s)) {
484                        cur_chr <<= 3;
485                        cur_chr |= *s++ - '0';
486                    }
487                }
488
489                if (cur_chr != 0 || sending) {
490                    if (sending && (cur_chr == '\\' || cur_chr == 0))
491                        *s1++ = '\\';
492                    *s1++ = cur_chr;
493                }
494                break;
495            }
496
497            if (sending)
498                *s1++ = '\\';
499            *s1++ = cur_chr;
500            break;
501        }
502    }
503
504    if (add_return)
505        *s1++ = '\r';
506
507    *s1++ = '\0'; /* guarantee closure */
508    *s1++ = '\0'; /* terminate the string */
509    return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
510}
511
512/*
513 * A modified version of 'strtok'. This version skips \ sequences.
514 */
515
516char *expect_strtok (s, term)
517     char *s, *term;
518{
519    static  char *str   = "";
520    int     escape_flag = 0;
521    char   *result;
522
523/*
524 * If a string was specified then do initial processing.
525 */
526    if (s)
527        str = s;
528
529/*
530 * If this is the escape flag then reset it and ignore the character.
531 */
532    if (*str)
533        result = str;
534    else
535        result = (char *) 0;
536
537    while (*str) {
538        if (escape_flag) {
539            escape_flag = 0;
540            ++str;
541            continue;
542        }
543
544        if (*str == '\\') {
545            ++str;
546            escape_flag = 1;
547            continue;
548        }
549
550/*
551 * If this is not in the termination string, continue.
552 */
553        if (strchr (term, *str) == (char *) 0) {
554            ++str;
555            continue;
556        }
557
558/*
559 * This is the terminator. Mark the end of the string and stop.
560 */
561        *str++ = '\0';
562        break;
563    }
564    return (result);
565}
566
567/*
568 * Process the expect string
569 */
570
571void   chat_expect (s)
572char *s;
573{
574    char *expect;
575    char *reply;
576
577    if (strcmp(s, "HANGUP") == 0) {
578        ++hup_next;
579        return ;
580    }
581 
582    if (strcmp(s, "ABORT") == 0) {
583        ++abort_next;
584        return ;
585    }
586
587    if (strcmp(s, "CLR_ABORT") == 0) {
588        ++clear_abort_next;
589        return ;
590    }
591
592    if (strcmp(s, "REPORT") == 0) {
593        ++report_next;
594        return ;
595    }
596
597    if (strcmp(s, "CLR_REPORT") == 0) {
598        ++clear_report_next;
599        return ;
600    }
601
602    if (strcmp(s, "TIMEOUT") == 0) {
603        ++timeout_next;
604        return ;
605    }
606
607    if (strcmp(s, "ECHO") == 0) {
608        ++echo_next;
609        return ;
610    }
611
612    if (strcmp(s, "SAY") == 0) {
613        ++say_next;
614        return ;
615    }
616
617/*
618 * Fetch the expect and reply string.
619 */
620    for (;;) {
621        expect = expect_strtok (s, "-");
622        s      = (char *)0 ;
623
624        if (expect == (char *) 0)
625            return ;
626
627        reply = expect_strtok (s, "-");
628
629/*
630 * Handle the expect string. If successful then exit.
631 */
632        if (get_string (expect))
633            return;
634
635/*
636 * If there is a sub-reply string then send it. Otherwise any condition
637 * is terminal.
638 */
639        if (reply == (char *) 0 || exit_code != 3)
640            break;
641
642        chat_send (reply);
643    }
644
645/*
646 * The expectation did not occur. This is terminal.
647 */
648    return ;
649}
650
651/*
652 *  process the reply string
653 */
654void chat_send (s)
655register char *s;
656{
657    if (say_next) {
658        say_next = 0;
659        s = clean(s,0);
660        write(modem_fd, s, strlen(s));
661        free(s);
662        return;
663    }
664
665    if (hup_next) {
666        hup_next = 0;
667    }
668
669    if (echo_next) {
670        echo_next = 0;
671        echo = (strcmp(s, "ON") == 0);
672        return;
673    }
674
675    if (abort_next) {
676        /* char *s1; */
677       
678       
679           ;
680       
681
682        return;
683    }
684
685
686/*    if (report_next) {
687        char *s1;
688       
689        report_next = 0;
690        if (n_reports >= MAX_REPORTS)
691            {
692              exit_code=2;
693              return;
694            }
695       
696        s1 = clean(s, 0);
697       
698        if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1)
699            {
700              exit_code=1;
701              return;
702            }
703       
704        report_string[n_reports++] = s1;
705       
706        return;
707    }
708*/
709/*    if (clear_report_next) {
710        char *s1;
711        int   i;
712        int   old_max;
713        int   pack = 0;
714       
715        clear_report_next = 0;
716       
717        s1 = clean(s, 0);
718       
719        if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1)
720            {
721              exit_code=1;
722              return;
723            }
724
725        old_max = n_reports;
726        for (i=0; i < n_reports; i++) {
727            if ( strcmp(s1,report_string[i]) == 0 ) {
728                free(report_string[i]);
729                report_string[i] = NULL;
730                pack++;
731                n_reports--;
732            }
733        }
734        free(s1);
735        if (pack)
736            pack_array(report_string,old_max);
737       
738        return;
739    }
740*/
741
742    if (timeout_next) {
743        timeout=atoi(s);
744        timeout_next = 0;
745        chat_timeout = atoi(s);
746       
747        if (chat_timeout <= 0)
748            chat_timeout = DEFAULT_CHAT_TIMEOUT;
749
750
751        return;
752    }
753    if (strcmp(s, "EOT") == 0)
754        s = "^D\\c";
755    else if (strcmp(s, "BREAK") == 0)
756        s = "\\K\\c";
757
758    if (!put_string(s))
759            {
760              exit_code=1;
761              return;
762            }
763}
764
765int get_char()
766{
767    int status;
768    char c;
769    int tries=MAX_TIMEOUTS;
770
771        while(tries)
772        {
773            status = read(modem_fd, &c, 1);
774            switch (status) {
775                   case 1:
776                                return ((int)c & 0x7F);
777                    default:
778                                tries--;                       
779            }
780    }
781        return -1;                                             
782}
783
784int put_char(c)
785int c;
786{
787    int status;
788    char ch = c;
789
790        /* inter-character typing delay (?) */
791
792    status = write(modem_fd, &ch, 1);
793
794    switch (status) {
795    case 1:
796        return (0);
797       
798    default:
799       
800       
801    }
802  return 0;
803}
804
805int write_char (c)
806int c;
807{
808    if (put_char(c) < 0) {
809        return (0);
810    }
811    return (1);
812}
813
814int put_string (s)
815register char *s;
816{
817
818
819    quiet = 0;
820    s = clean(s, 1);
821    while (*s) {
822        register char c = *s++;
823
824        if (c != '\\') {
825            if (!write_char (c))
826                return 0;
827            continue;
828        }
829
830        c = *s++;
831        switch (c) {
832        case 'd':
833            sleep(1);
834            break;
835
836        case 'K':
837            break_sequence();
838            break;
839
840        case 'p':
841#if 0 /* FIXME!!! */
842            usleep(10000);      /* 1/100th of a second (arg is microseconds) */
843#else
844            sleep(1);
845#endif
846            break;
847
848        default:
849            if (!write_char (c))
850                return 0;
851            break;
852        }
853    }
854
855   /* alarm(0);*/
856    return (1);
857}
858
859/*
860 *      Echo a character to stderr.
861 *      When called with -1, a '\n' character is generated when
862 *      the cursor is not at the beginning of a line.
863 */
864void echo_stderr(n)
865int n;
866{
867/*    static int need_lf;
868    char *s;
869
870    switch (n) {
871    case '\r':           
872        break;
873    case -1:
874        if (need_lf == 0)
875            break;
876 
877    case '\n':
878        write(2, "\n", 1);
879        need_lf = 0;
880        break;
881    default:
882        s = character(n);
883        write(2, s, strlen(s));
884        need_lf = 1;
885        break;
886    }*/
887}
888
889/*
890 *      'Wait for' this string to appear on this file descriptor.
891 */
892
893int get_string(string)
894register char *string;
895{
896    int c, len, minlen;
897    register char *s = temp2, *end = s + STR_LEN;
898    char *logged = temp2;
899    struct termios tios;
900
901    tcgetattr(modem_fd, &tios);
902    tios.c_cc[VMIN] = 0;
903    tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
904    tcsetattr(modem_fd, TCSANOW, &tios);
905               
906    string = clean(string, 0);
907    len = strlen(string);
908    minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
909       
910    if (len > STR_LEN) {
911        exit_code = 1;
912        return 0;
913    }
914
915    if (len == 0) {
916                        return (1);
917    }
918
919
920   while ( (c = get_char()) >= 0) {
921                int n, abort_len;
922
923        *s++ = c;
924        *s=0;
925       
926        if (s - temp2 >= len &&
927            c == string[len - 1] &&
928            strncmp(s - len, string, len) == 0) {
929            return (1);
930        }
931
932        for (n = 0; n < n_aborts; ++n) {
933            if (s - temp2 >= (abort_len = strlen(abort_string[n])) &&
934                strncmp(s - abort_len, abort_string[n], abort_len) == 0) {
935
936                exit_code = n + 4;
937                strcpy(fail_reason = fail_buffer, abort_string[n]);
938                return (0);
939            }
940        }
941
942        if (s >= end) {
943            if (logged < s - minlen) {
944                logged = s;
945            }
946            s -= minlen;
947            memmove(temp2, s, minlen);
948            logged = temp2 + (logged - s);
949            s = temp2 + minlen;
950        }
951    }
952    exit_code = 3;
953    return (0);
954}
955
956/*
957 * Gross kludge to handle Solaris versions >= 2.6 having usleep.
958 */
959
960/*
961  usleep -- support routine for 4.2BSD system call emulations
962  last edit:  29-Oct-1984     D A Gwyn
963  */
964
965
966#if 0
967int
968usleep( usec )                            /* returns 0 if ok, else -1 */
969    long                usec;           /* delay in microseconds */
970{
971  rtems_status_code status;
972  rtems_interval    ticks_per_second;
973  rtems_interval    ticks;
974  status = rtems_clock_get(
975    RTEMS_CLOCK_GET_TICKS_PER_SECOND,
976    &ticks_per_second);
977    ticks = (usec * (ticks_per_second/1000))/1000;
978    status = rtems_task_wake_after( ticks );
979  return 0;
980}
981#endif
982
983void pack_array (array, end)
984    char **array; /* The address of the array of string pointers */
985    int    end;   /* The index of the next free entry before CLR_ */
986{
987    int i, j;
988
989    for (i = 0; i < end; i++) {
990        if (array[i] == NULL) {
991            for (j = i+1; j < end; ++j)
992                if (array[j] != NULL)
993                    array[i++] = array[j];
994            for (; i < end; ++i)
995                array[i] = NULL;
996            break;
997        }
998    }
999}
1000
1001/*
1002 * vfmtmsg - format a message into a buffer.  Like vsprintf except we
1003 * also specify the length of the output buffer, and we handle the
1004 * %m (error message) format.
1005 * Doesn't do floating-point formats.
1006 * Returns the number of chars put into buf.
1007 */
1008#define OUTCHAR(c)      (buflen > 0? (--buflen, *buf++ = (c)): 0)
Note: See TracBrowser for help on using the repository browser.