static int get_num( int *nump, int min_val, int max_val, const char *s, char stop_char ) { const char *func = "get_num" ; int i = 0; for ( *nump = 0 ; isdigit( s[i] ) ; i++ ) { *nump *= 10 ; *nump += s[i] - '0' ; } if ( s[i] != stop_char ) { parsemsg( LOG_ERR, func, "incorrect time interval" ) ; return( -1 ); } if ( ! IN_RANGE( *nump, min_val, max_val ) ) { parsemsg( LOG_ERR, func, "invalid time interval" ) ; return( -1 ) ; } return( i ) ; }
/* * Input: * a line of the form * name [SPACE] OP [SPACE] value [SPACE] value ... * * Recognize the attribute name and operator and place them in *attrp, *opp * * Currently, we allow any non-space character to be used in the * attribute name. * * Return value: a pointer to the character after OP. */ static char *get_attr_op( char *line, char **attrp, enum assign_op *opp ) { char *p ; char *attr ; enum assign_op op ; const char *func = "get_attr_op" ; /* * First get the attribute name */ for ( p = line ; isspace( *p ) ; p++ ) ; /* skip spaces */ if ( *p == NUL ) { parsemsg( LOG_ERR, func, "Empty line" ) ; return( NULL ) ; } attr = p ; for ( ; ! isspace( *p ) && (*p != '='); p++ ) ; /* skip attribute name */ if ( *p == NUL ) { parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ; return( NULL ) ; } if( *p == '=' ) { *p = NUL ; /* now attribute name is NUL terminated */ parsemsg( LOG_ERR, func, "Attribute %s needs a space before operator", attr); return( NULL ) ; } *p++ = NUL ; /* now attribute name is NUL terminated */ while ( isspace( *p ) ) p++ ; /* skip spaces */ switch ( *p ) { case NUL: parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ; return( NULL ) ; case '=': op = SET_EQ ; break ; case '+': case '-': op = ( *p++ == '+' ) ? PLUS_EQ : MINUS_EQ ; if ( *p == '=' ) break ; /* FALL THROUGH if there is no '=' after the '+' or '-' */ default: parsemsg( LOG_ERR, func, "Bad operator for attribute: %s", attr ) ; return( NULL ) ; } *attrp = attr ; *opp = op ; return( ++p ) ; /* skip the '=' */ }
terpmes () { char mess[128]; register char *m, *mend, *s = screen[0], *t; int i; /* Set 't' to the tail of the message, skip backward over blank & dot */ for (t=s+79; *t==' ' || *t=='.'; t--) ; /* Find last non-blank */ t++; /* t -> beyond string */ /* * Loop through each message, finding the beginning and end, and * copying it to mess, lower-casing it as we go. Then call parsemsg. */ while (s<t) /* While more chars in msg */ { while (*s==' ' && s<t) s++; /* Skip leading blanks */ for (m = mess; /* Copy text */ s<t && (version < RV53A || *s != '.' || s[1] != ' '); s++) *m++ = isupper (*s) ? tolower (*s) : *s; /* Lower case the char */ s++; /* Skip the period, if any */ *(mend = m) = '\0'; /* Add trailing null */ if (mess != mend) parsemsg (mess, mend); /* Parse it */ } }
/* * Find the attribute with the specified name */ static const struct attribute *attr_lookup( const struct attribute attr_array[], const char *attr_name ) { const struct attribute *ap ; const char *func = "attr_lookup" ; for ( ap = &attr_array[ 0 ] ; ap->a_name ; ap++ ) if ( EQ( attr_name, ap->a_name ) ) return ap; if ( attr_array == service_attributes ) parsemsg( LOG_WARNING, func, "bad service attribute: %s", attr_name ) ; else parsemsg( LOG_WARNING, func, "attribute: %s should not be in default section", attr_name ) ; return NULL; }
/* * Each interval should have the form: * hour:min-hour:min * Example: 2:30-4:15 */ status_e ti_add( pset_h iset, const char *interval_str ) { struct time_interval *tip ; int hours ; int minutes ; int min_start ; int min_end ; int p, r = 0 ; const char *func = "add_interval" ; while (interval_str[r] == ' ') r++; /* Eat white space */ if ( ( p = get_num( &hours, 0, 23, interval_str+r, ':' ) ) == -1 ) return( FAILED ) ; r += p; r++; /* Get past : */ if ( ( p = get_num( &minutes, 0, 59, interval_str+r, '-' ) ) == -1 ) return( FAILED ) ; min_start = hours * 60 + minutes ; r += p; r++; /* Get past - */ if ( ( p = get_num( &hours, 0, 23, interval_str+r, ':' ) ) == -1 ) return( FAILED ) ; r += p; r++; /* Get past : */ if ( get_num( &minutes, 0, 59, interval_str+r, NUL ) == -1 ) return( FAILED ) ; min_end = hours * 60 + minutes ; if ( min_start >= min_end ) { parsemsg( LOG_ERR, func, "invalid time interval: %s", interval_str ) ; return( FAILED ) ; } tip = NEW_TI() ; if ( tip == NULL ) { out_of_memory( func ) ; return( FAILED ) ; } tip->min_start = min_start ; tip->min_end = min_end ; if ( pset_add( iset, tip ) == NULL ) { FREE_TI( tip ) ; out_of_memory( func ) ; return( FAILED ) ; } return( OK ) ; }
/* * Parse a line of the form: * name OP value value value ... * where each value is a string and OP can be '=', '+=', '-=' * * NOTE: We do not allocate space for the name and values. Instead we keep * pointers to the line. */ status_e parse_line( char *line, char **namep, enum assign_op *opp, pset_h values ) { char *value ; char *values_string ; char *attribute ; str_h strp ; const char *func = "parse_line" ; if ( ( values_string = get_attr_op( line, &attribute, opp ) ) == NULL ) return( FAILED ) ; /* * Now grab the values */ strp = str_parse( values_string, " \t", STR_RETURN_ERROR, (int *)0 ) ; if ( strp == NULL ) { parsemsg( LOG_CRIT, func, ES_NOMEM ) ; return( FAILED ) ; } while ( (value = str_component( strp )) ) { if ( pset_add( values, value ) == NULL ) { parsemsg( LOG_CRIT, func, ES_NOMEM ) ; str_endparse( strp ) ; return( FAILED ) ; } } str_endparse( strp ) ; *namep = attribute ; return( OK ) ; }
/* * Read the entry line-by-line and add the information in scp * Use defaults to initialize modifiable entry fields. */ static status_e parse_entry( entry_e entry_type, int fd, struct service_config *scp ) { static pset_h attr_values = NULL; char *line ; char *attr_name ; enum assign_op op ; const char *func = "parse_entry" ; if ( ! attr_values && ( attr_values = pset_create( 10, 10 ) ) == NULL ) { out_of_memory( func ) ; return( FAILED ) ; } for ( ;; ) { line = next_line( fd ) ; if ( line == CHAR_NULL ) { parsemsg( LOG_ERR, func, "incomplete entry" ) ; return( FAILED ) ; } if ( line_has_only_1_char( line, ENTRY_END ) ) return( OK ) ; if ( parse_line( line, &attr_name, &op, attr_values ) == FAILED ) { pset_clear( attr_values ) ; return( FAILED ) ; } if (identify_attribute( entry_type, scp, attr_name, op, attr_values ) == FAILED ) { /* * An error was detected in the default section. We will terminate * since whatever attribute being specified cannot be propagated. */ msg(LOG_ERR, func, "A fatal error was encountered while parsing the default section." " xinetd will exit."); Sclose( fd ); terminate_program(); } pset_clear( attr_values ) ; } }
void skip_entry( int fd ) { for ( ;; ) { char *line = next_line( fd ) ; if ( line == NULL ) /* reached EOF ? */ { parsemsg( LOG_WARNING, "skip_entry", "missing %c in last service entry", ENTRY_END ) ; break ; } if ( line_has_only_1_char( line, ENTRY_END ) ) break ; } }
int main (int argc, char *argv[]) { char *l = NULL; message_t *cmsg = NULL; command_t *ccmd = NULL; settings_t global_settings; settings = &global_settings; settings->execname = argv[0]; settings->action_trigger = '`'; /* default trigger char */ settings->verbose = false; settings->socket = NULL; logstr ("Radroach here\n"); register_signals (); if (configure (argc, argv)) exit (EXIT_FAILURE); logstr ("trusted users are: %s\n", settings->trusted); if (settings->aj_list) logstr ("channels to join: %s\n", settings->aj_list); server_connect (settings->host); setup (); plugins_load ("./plugins/"); while ((l = sogetline ()) != NULL) { if (p_response (l)) continue; cmsg = parsemsg (l); if (cmsg != NULL) { ccmd = parsecmd (cmsg->msg); if (ccmd != NULL) execute (cmsg, ccmd); } else free (l); } return EXIT_SUCCESS; }
/* * Identify the attribute in <attr_name>. * * Check if * 1) the attribute has been defined already * 2) the value count is correct * 3) the assign op is appropriate * * Invoke appropriate parser. * * This function will return FAILED only if its in the default section * and an attribute cannot be ID'd. Otherwise, it returns OK. */ static status_e identify_attribute( entry_e entry_type, struct service_config *scp, const char *attr_name, enum assign_op op, pset_h attr_values ) { const struct attribute *ap ; const char *func = "identify_attribute" ; if ( entry_type == SERVICE_ENTRY ) ap = attr_lookup( service_attributes, attr_name ) ; else ap = attr_lookup( default_attributes, attr_name ) ; if ( ap == NULL ) return OK; /* We simply ignore keywords not on the list */ if ( ! MODIFIABLE( ap ) ) { if ( SC_SPECIFIED( scp, ap->a_id ) ) { parsemsg( LOG_WARNING, func, "Service %s: attribute already set: %s", SC_NAME(scp), attr_name ) ; return OK; } if ( op != SET_EQ ) { parsemsg( LOG_WARNING, func, "Service %s: operator '%s' cannot be used for attribute '%s'", SC_NAME(scp), ( op == PLUS_EQ ) ? "+=" : "-=", attr_name ) ; return OK; } } else /* modifiable attribute */ { /* * For the defaults entry, '=' and '+=' have the same meaning */ if ( entry_type == DEFAULTS_ENTRY && op == SET_EQ ) op = PLUS_EQ ; } if ( FIXED_VALUES( ap ) && (unsigned)ap->a_nvalues != pset_count( attr_values ) ) { parsemsg( LOG_WARNING, func, "attribute %s expects %d values and %d values were specified", attr_name, ap->a_nvalues, pset_count( attr_values ) ) ; return OK; } if ( (*ap->a_parser)( attr_values, scp, op ) == OK ) { /* This is the normal path. */ SC_SPECIFY( scp, ap->a_id ) ; } else if ( entry_type == SERVICE_ENTRY ) { parsemsg( LOG_ERR, func, "Error parsing attribute %s - DISABLING SERVICE", attr_name ) ; SC_DISABLE( scp ); } /* * We are in the default section and an error was detected. At * this point, we should terminate since whatever attribute * was trying to be specified cannot be propagated. */ else if ( !debug.on ) return FAILED; return OK; }
/* * Find the next service entry. * Look for a line of the form: * * <white-space> service <white-space> <service_name> * * followed by a line containing only the ENTRY_BEGIN character */ static entry_e find_next_entry( int fd, char **snamep ) { char *p ; str_h strp ; char *sname = NULL; entry_e entry_type=0; char *line = next_line( fd ) ; const char *func = "find_next_entry" ; if ( line == CHAR_NULL ) return( NO_ENTRY ) ; strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ; if ( strp == NULL ) { parsemsg( LOG_CRIT, func, "str_parse failed" ) ; return( BAD_ENTRY ) ; } if ( ( p = str_component( strp ) ) == CHAR_NULL ) { /* * This shouldn't happen since it implies that there is a bug * in next_line */ parsemsg( LOG_WARNING, func, "empty line" ) ; str_endparse( strp ) ; return( BAD_ENTRY ) ; } /* * Look for a keyword */ if ( EQ( p, KW_SERVICE ) || EQ( p, KW_INCLUDE ) || EQ(p, KW_INCLUDEDIR)) { if ( EQ( p, KW_INCLUDE )) entry_type = INCLUDE_ENTRY; else if ( EQ( p, KW_INCLUDEDIR )) entry_type = INCLUDEDIR_ENTRY; /* * Now get the service name */ if ( ( p = str_component( strp ) ) == CHAR_NULL ) { parsemsg( LOG_ERR, func, "service name missing" ) ; str_endparse( strp ) ; return( BAD_ENTRY ) ; } sname = new_string( p ) ; if ( sname == CHAR_NULL ) { out_of_memory( func ) ; str_endparse( strp ) ; return( BAD_ENTRY ) ; } str_endparse( strp ) ; if( (entry_type == INCLUDE_ENTRY) || (entry_type == INCLUDEDIR_ENTRY)) { *snamep = sname ; return( entry_type ) ; } else entry_type = SERVICE_ENTRY ; } else if ( EQ( p, KW_DEFAULTS ) ) { str_endparse( strp ) ; entry_type = DEFAULTS_ENTRY ; } else { parsemsg( LOG_ERR, func, "missing service keyword" ) ; str_endparse( strp ) ; return( BAD_ENTRY ) ; } /* * Now look for ENTRY_BEGIN */ line = next_line( fd ) ; if ( line == NULL || ! line_has_only_1_char( line, ENTRY_BEGIN ) ) { parsemsg( LOG_ERR, func, "Service %s: missing '%c'", sname, ENTRY_BEGIN ) ; if ( entry_type == SERVICE_ENTRY ) free( sname ) ; return( BAD_ENTRY ) ; } *snamep = sname ; return( entry_type ) ; }
/* * Read the configuration file (descriptor fd) and place all * services found there in the configuration. */ void parse_conf_file( int fd, struct configuration *confp, const char *filename) { pset_h sconfs = CNF_SERVICE_CONFS( confp ) ; struct service_config *default_config = CNF_DEFAULTS( confp ) ; boolean_e found_defaults = NO ; struct service_config default_default_config ; const char *func = "parse_conf_file" ; int incfd; line_count = 0 ; current_file = filename; CLEAR( default_default_config ) ; for ( ;; ) { entry_e entry_type ; char *service_name = NULL; /* * if find_next_entry is successful, service_name * will point to malloc'ed memory */ entry_type = find_next_entry( fd, &service_name ) ; switch ( entry_type ) { case INCLUDE_ENTRY: { int saved_line_count = line_count; incfd = open(service_name, O_RDONLY); if( incfd < 0 ) { parsemsg( LOG_ERR, func, "Unable to open included configuration file: %s", service_name); break; } parsemsg( LOG_DEBUG,func, "Reading included configuration file: %s",service_name); parse_conf_file(incfd, confp, service_name); /* * parse_conf_file eventually calls Srdline, try Sclosing it * to unmmap memory. */ Sclose(incfd); /* Restore since we've returned from included file */ current_file = filename; line_count = saved_line_count; } break; case INCLUDEDIR_ENTRY: { int saved_line_count = line_count; handle_includedir(service_name, confp); current_file = filename; line_count = saved_line_count; } break; case SERVICE_ENTRY: get_service_entry( fd, sconfs, service_name, default_config ) ; break ; case DEFAULTS_ENTRY: if ( found_defaults == YES ) { parsemsg( LOG_ERR, func, "only 1 defaults entry is allowed. This entry will be ignored" ) ; skip_entry( fd ) ; } else if ( parse_entry( DEFAULTS_ENTRY, fd, default_config ) == OK ) { found_defaults = YES ; /* * We must check bind_address to see if it was deferred. */ if (SC_SPECIFIED( default_config, A_BIND) && SC_BIND_ADDR(default_config) == NULL) M_CLEAR( default_config->sc_specified_attributes, A_BIND ) ; } break ; case BAD_ENTRY: skip_entry( fd ) ; break ; case NO_ENTRY: return ; } if (service_name) free(service_name); } }
int main(int argc, char *argv[]){ int sockfd, numbytes, childproc; int y, x , i , L, index; char *msg, *user, *buffer = (char*) malloc((USERNAMESIZE + MAXDATASIZE + 4)*sizeof(char)); char *addr = NULL; if(argc >= 2){ addr=argv[1]; } sockfd=socksetup(addr); user=startscreen(); L=strlen(user); // SETTING UP ncurses WINDOWS WINDOW *in, *out; initscr(); cbreak(); echo(); in = newwin(4, 0, LINES-4, 0); out = newwin(LINES-4, 0, 0, 0); scrollok(in, TRUE); scrollok(out, TRUE); childproc = fork(); if(childproc >= 0){ if(childproc > 0){ //RECEIVING MESSAGES while((numbytes = recv(sockfd, buffer, (USERNAMESIZE + MAXDATASIZE + 4), 0)) >0) { if(0 < strlen(buffer)){ index=getuser(buffer); wattron(out, A_BOLD); for(i=0;i<index;i++) wprintw(out, "%c", buffer[i]); wattroff(out, A_BOLD); wprintw(out, "%s\n", buffer + index); } wrefresh(out); wrefresh(in); wmove(in, 0, 0); } } else //SENDING MESSAGES while(1){ mvwgetstr(in,0, 0, buffer); wmove(in, 0, 0); werase(in); wrefresh(in); msg=parsemsg(user, buffer, L); if (send(sockfd, msg, MAXDATASIZE + USERNAMESIZE + 4, 0) == -1) close(sockfd); } } wgetch(in); delwin(in); delwin(out); endwin(); close(sockfd); free(buffer); return 0; }
static int get_next_inet_entry( int fd, pset_h sconfs, struct service_config *defaults) { char *p; str_h strp; char *line = next_line(fd); struct service_config *scp; unsigned u, i; const char *func = "get_next_inet_entry"; char *name = NULL, *rpcvers = NULL, *rpcproto = NULL; char *group, *proto, *stype; const struct name_value *nvp; struct protoent *pep ; struct passwd *pw ; struct group *grp ; const char *dot = "."; const char *slash = "/"; pset_h args; if( line == CHAR_NULL ) return -2; strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ; if( strp == NULL ) { parsemsg( LOG_CRIT, func, "inetd.conf - str_parse failed" ) ; return( -1 ) ; } if( (args = pset_create(10,10)) == NULL ) { out_of_memory(func); return -1; } /* Break the line into components, based on spaces */ while( (p = str_component( strp )) ) { if( pset_add(args, p) == NULL ) { parsemsg( LOG_CRIT, func, ES_NOMEM ); pset_destroy(args); return -1; } } str_endparse( strp ); /* get the service name */ name = new_string((char *)pset_pointer( args, 0 )); if( name == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Invalid service name" ); pset_destroy(args); return -1; } /* Check to find the '/' for specifying RPC version numbers */ if( (rpcvers = strstr(name, slash)) != NULL ) { *rpcvers = '\0'; rpcvers++; } scp = sc_alloc( name ); if( scp == NULL ) { pset_destroy(args); free( name ); return -1; } /* * sc_alloc makes its own copy of name. At this point, sc_alloc worked * so we will free our copy to avoid leaks. */ free( name ); /* Replicate inetd behavior in this regard. Also makes sure the * service actually works on system where setgroups(0,NULL) doesn't * work. */ SC_GROUPS(scp) = YES; SC_SPECIFY( scp, A_GROUPS ); /* Get the socket type (stream dgram) */ stype = (char *)pset_pointer(args, 1); if( stype == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Invalid socket type" ); pset_destroy(args); sc_free(scp); return -1; } nvp = nv_find_value( socket_types, stype ); if( nvp == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Bad socket type: %s", p); pset_destroy(args); sc_free(scp); return -1; } SC_SOCKET_TYPE(scp) = nvp->value; /* Get the protocol type */ proto = (char *)pset_pointer(args,2); if( strstr(proto, "rpc") != NULL ) { int rpcmin, rpcmax; struct rpc_data *rdp = SC_RPCDATA( scp ) ; if( rpcvers == NULL ) { pset_destroy(args); sc_free(scp); return -1; /* uh oh */ } p = strchr(rpcvers, '-'); if( p && parse_int(rpcvers, 10, '-', &rpcmin) == 0 ) { if( parse_base10(p + 1, &rpcmax) || rpcmin > rpcmax ) { pset_destroy(args); sc_free(scp); return -1; } } else { if( parse_base10(rpcvers, &rpcmin) ) { pset_destroy(args); sc_free(scp); return -1; } rpcmax = rpcmin; } /* now have min and max rpc versions */ rdp->rd_min_version = rpcmin; rdp->rd_max_version = rpcmax; rpcproto = strstr(proto, slash); if( rpcproto == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - bad rpc version numbers" ); pset_destroy(args); sc_free(scp); return -1; } *rpcproto = '\0'; rpcproto++; proto = rpcproto; /* Set the RPC type field */ nvp = nv_find_value( service_types, "RPC" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_TYPE(scp), nvp->value); } if ( ( pep = getprotobyname( proto ) ) == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Protocol %s not in /etc/protocols", proto ) ; pset_destroy(args); sc_free(scp); return -1; } SC_PROTONAME(scp) = new_string( proto ) ; if ( SC_PROTONAME(scp) == NULL ) { out_of_memory( func ) ; pset_destroy(args); sc_free(scp); return -1; } SC_PROTOVAL(scp) = pep->p_proto; SC_SPECIFY(scp, A_PROTOCOL); /* Get the wait attribute */ p = (char *)pset_pointer(args, 3); if ( p == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - No value specified for wait" ); sc_free(scp); return -1; } if ( EQ( p, "wait" ) ) SC_WAIT(scp) = YES ; else if ( EQ( p, "nowait" ) ) SC_WAIT(scp) = NO ; else parsemsg( LOG_ERR, func, "inetd.conf - Bad value for wait: %s", p ) ; /* Get the user to run as */ p = (char *)pset_pointer(args, 4); if ( p == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" ); sc_free(scp); return -1; } if( (group = strstr(p, dot)) ) { *group = '\0'; group++; grp = (struct group *)getgrnam( (char *)group ) ; if ( grp == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Unknown group: %s", group ) ; pset_destroy(args); sc_free(scp); return -1; } SC_GID(scp) = ((struct group *)grp)->gr_gid; SC_SPECIFY( scp, A_GROUP ); } pw = getpwnam( p ); if ( pw == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Unknown user: %s", p ) ; pset_destroy(args); sc_free(scp); return -1; } str_fill( pw->pw_passwd, ' ' ); SC_UID(scp) = pw->pw_uid; SC_USER_GID(scp) = pw->pw_gid; /* Get server name, or flag as internal */ p = (char *)pset_pointer(args, 5); if ( p == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" ); sc_free(scp); return -1; } if( EQ( p, "internal" ) ) { nvp = nv_find_value( service_types, "INTERNAL" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_TYPE(scp), nvp->value); if( EQ( SC_NAME(scp), "time" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("time-stream"); else SC_ID(scp) = new_string("time-dgram"); } if( EQ( SC_NAME(scp), "daytime" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("daytime-stream"); else SC_ID(scp) = new_string("daytime-dgram"); } if( EQ( SC_NAME(scp), "chargen" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("chargen-stream"); else SC_ID(scp) = new_string("chargen-dgram"); } if( EQ( SC_NAME(scp), "echo" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("echo-stream"); else SC_ID(scp) = new_string("echo-dgram"); } if( EQ( SC_NAME(scp), "discard" ) ) { parsemsg(LOG_WARNING, func, "inetd.conf - service discard not supported"); pset_destroy(args); sc_free(scp); return -1; } } else { SC_SERVER(scp) = new_string( p ); if ( SC_SERVER(scp) == NULL ) { out_of_memory( func ) ; pset_destroy(args); sc_free(scp); return -1; } SC_SPECIFY( scp, A_SERVER); /* Get argv */ SC_SERVER_ARGV(scp) = (char **)argv_alloc(pset_count(args)+1); for( u = 0; u < pset_count(args)-6 ; u++ ) { p = new_string((char *)pset_pointer(args, u+6)); if( p == NULL ) { for ( i = 1 ; i < u ; i++ ) free( SC_SERVER_ARGV(scp)[i] ); free( SC_SERVER_ARGV(scp) ); pset_destroy(args); sc_free(scp); return -1; } SC_SERVER_ARGV(scp)[u] = p; } /* Set the reuse flag, as this is the default for inetd */ nvp = nv_find_value( service_flags, "REUSE" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_XFLAGS(scp), nvp->value); /* Set the NOLIBWRAP flag, since inetd doesn't have libwrap built in */ nvp = nv_find_value( service_flags, "NOLIBWRAP" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_XFLAGS(scp), nvp->value); /* Set the NAMEINARGS flag, as that's the default for inetd */ nvp = nv_find_value( service_flags, "NAMEINARGS" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return (-1); } M_SET(SC_XFLAGS(scp), nvp->value); SC_SPECIFY( scp, A_SERVER_ARGS ); if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) ) SC_PRESENT( scp, A_ID ) ; else { out_of_memory( func ) ; pset_destroy(args); sc_free(scp); return -1; } } SC_SPECIFY( scp, A_PROTOCOL ); SC_SPECIFY( scp, A_USER ); SC_SPECIFY( scp, A_SOCKET_TYPE ); SC_SPECIFY( scp, A_WAIT ); if( ! pset_add(sconfs, scp) ) { out_of_memory( func ); pset_destroy(args); sc_free(scp); return -1; } pset_destroy(args); parsemsg( LOG_DEBUG, func, "added service %s", SC_NAME(scp)); return 0; }