Exemplo n.º 1
0
struct ax_routes *find_mheard(char *dest_call)
{
  FILE *fp;
  static struct ax_routes a;
  struct mheard_struct mh;
  char call[12];
  char *cp;
  int k;

  if ((fp = fopen(DATA_MHEARD_FILE, "r")) == NULL) {
    return NULL;
  }
  
  safe_strncpy(call,dest_call,9);
  cp=strchr(call, '-');
  if (cp==NULL) strcat(call,"-0");

  while (fread(&mh, sizeof(struct mheard_struct), 1, fp) == 1) {
    if (strcasecmp(call, ax25_ntoa(&mh.from_call))==0) {
      fclose(fp);
      safe_strncpy(a.dest_call, ax25_ntoa(&mh.from_call), 9);
      safe_strncpy(a.dev, mh.portname, 13);
      for(k=0;k<AX25_MAX_DIGIS;k++) {
	if (k<=mh.ndigis) safe_strncpy(a.digis[k],ax25_ntoa(&mh.digis[k]),9);
	else strcpy(a.digis[k],"\0");
      }
      return &a;
    }
  }
  fclose(fp);

  return NULL;
}
Exemplo n.º 2
0
/* is_heard : from awznode */
int is_heard(char **av)
{
	FILE *fp;
	static char port[14];
	static char dest[10];
	static char digi[10][AX25_MAX_DIGIS];
	struct mheard_struct mh;
	char call[12];
	char *cp;
	int k;

	if ((fp = fopen(DATA_MHEARD_FILE, "r")) == NULL) {
		printf("Error : file %s not found\n", DATA_MHEARD_FILE);
		return 0;
	}

	safe_strncpy(call, av[0], 9);
	cp = strchr(call, '-');
	if (cp == NULL)
		strcat(call, "-0");

	while (fread(&mh, sizeof(struct mheard_struct), 1, fp) == 1)
	{
		if (strcasecmp(call, ax25_ntoa(&mh.from_call)) == 0)
		{
			fclose(fp);

			safe_strncpy(port, mh.portname, 13);
			safe_strncpy(dest, ax25_ntoa(&mh.from_call), 9);

			av[0] = port;
			av[1] = dest;

			for (k = 0; k < AX25_MAX_DIGIS; k++)
			{
				if (k <= mh.ndigis)
				{
					safe_strncpy(digi[k], ax25_ntoa(&mh.digis[k]), 9);
					av[2 + k] = digi[k];
				}
				else
				{
					av[2 + k] = NULL;
					break;
				}
			}
			return 1;
		}
	}

	fclose(fp);

	return 0;
}
Exemplo n.º 3
0
static PyObject *
ax25_address_str(ax25_address_object* self)
{
    const char* ret;

    ret = ax25_ntoa(&self->field);
    return PyUnicode_FromStringAndSize(ret, strlen(ret));
}
Exemplo n.º 4
0
Arquivo: libwp.c Projeto: ve7fet/fpac
void dump_rose(char *title, struct full_sockaddr_rose *rose)
{
	int i;

	printf("%s\n", title);
	printf("\tFamily   = %d\n", rose->srose_family);
	printf("\tCallsign = %s\n", ax25_ntoa(&rose->srose_call));
	printf("\tAddress  = %s\n", rose_ntoa(&rose->srose_addr));
	printf("\tndigis   = %d\n", rose->srose_ndigis);

	for (i = 0; i < rose->srose_ndigis ; i++)
	{
		if (i == 6)
		{
			printf("Error : Nb digis = %d\n", rose->srose_ndigis);
			break;
		}
		printf("\tdigi %d   = %s\n", i+1, ax25_ntoa(&rose->srose_digis[i]));
	}
	printf("\n");
}
Exemplo n.º 5
0
Arquivo: libwp.c Projeto: ve7fet/fpac
void dump_ax25(char *title, struct full_sockaddr_ax25 *ax25)
{
	int i;

	printf("%s\n", title);
	printf("\tFamily   = %d\n", ax25->fsa_ax25.sax25_family);
	printf("\tCallsign = %s\n", ax25_ntoa(&ax25->fsa_ax25.sax25_call));
	printf("\tndigis   = %d\n", ax25->fsa_ax25.sax25_ndigis);

	for (i = 0; i < ax25->fsa_ax25.sax25_ndigis ; i++)
	{
		if (i == 6)
		{
			printf("Error : Nb digis = %d\n", ax25->fsa_ax25.sax25_ndigis);
			break;
		}
		printf("\tdigi %d   = %s%c\n",
			i+1, 
			ax25_ntoa(&ax25->fsa_digipeater[i]),
			(ax25->fsa_digipeater[i].ax25_call[6] & AX25_HBIT) ? '*' : ' ');
	}
	printf("\n");
}
Exemplo n.º 6
0
static void PrintPortEntry(struct PortRecord *pr, int portnr, int c_index)
{
	char lh[30], fh[30], *call, *s, data[255];
	int i;
	
	strcpy(lh, ctime(&pr->entry.last_heard));
	lh[19] = 0;
	strcpy(fh, ctime(&pr->entry.first_heard));
	fh[19] = 0;
	call = ax25_ntoa(&pr->entry.from_call);
	if ((s = strstr(call, "-0")) != NULL)
		*s = '\0';
	sprintf(data,"%s %s %s ", call, fh, lh);
	for (i=strlen(data);i<sizeof(data);i++)
	    data[i]=0;
	send_frame('H',connection[c_index].fd,portlist[portnr].dev,data,strlen(data)+33,"","");
	
}
Exemplo n.º 7
0
Arquivo: libwp.c Projeto: ve7fet/fpac
int wp_update_addr(struct full_sockaddr_rose *addr)
{
	wp_t wp;
	char *ptr;

	/* Only valid callsigns ! */
	ptr = ax25_ntoa(&addr->srose_call);
	if ((ptr == NULL) || (wp_check_call(ptr) != 0)) {
		syslog(LOG_INFO, "wp_update_addr() invalid callsign '%s'\n", ptr);
		return -1;
	}
	memset(&wp, 0, sizeof(wp_t));		
	if (wp_get(&addr->srose_call, &wp) != 0) {
		syslog(LOG_INFO, "wp_update_addr() callsign '%s' not found\n", ptr);
	/*	return -1; */
	}
	wp.is_deleted = 0;
	wp.address = *addr;
	return wp_set(&wp);
}
Exemplo n.º 8
0
int main(int ac, char **av)
{
	FILE *fptr;
	old_wp_t old_wp;
	wp_t new_wp;
	wp_header wph;
	char dnic[5];
	char *add, *call;
	char buf[20];

	if (ac < 2)
	{
		fprintf(stderr, "format : wpconv database\n");
		return 1;
	}
	
	fptr = fopen(av[1], "r");
	if (fptr == NULL)
	{
		fprintf(stderr, "Cannot open %s\n", av[1]);
		return 2;
	}

	if (fread(&wph, sizeof(wph), 1, fptr) == 0)
	{
		fclose(fptr);
		fprintf(stderr, "database %s is empty\n", av[1]);
		return 3;
	}

	/* Check the first record for compatibility */
	if (strcmp(wph.signature,OLD_FILE_SIGNATURE) != 0)
	{
		fprintf(stderr, "database %s is not compatible\n", av[1]);
		fclose(fptr);
		return 4;
	}

	printf("%u callsigns in database\n", wph.nb_record);

	if (wp_open("WPCNVT")) {
		perror("Cannot open WP service");
		exit(1);
	}
	
	while (fread(&old_wp, sizeof(old_wp_t), 1, fptr))
	{
			
		if (old_wp.date == 0)
			continue;
			
		add = rose_ntoa(&old_wp.address.srose_addr);
		call = ax25_ntoa(&old_wp.address.srose_call);

		if (wp_check_call(call) != 0)
			continue;

		strncpy(dnic, add, 4); dnic[4] = '\0';

		my_date(buf, old_wp.date),
		
		printf("%-9s %s => %s %-7s ", 
				call,
				buf,
				dnic, 
				add+4);
			
		if (old_wp.address.srose_ndigis)
			printf("%s ", ax25_ntoa(&old_wp.address.srose_digi));
						
		printf("%s %s\n", old_wp.name, old_wp.city);
		
		/* Add to the running database */
		
		memset(&new_wp, 0, sizeof(wp_t));
		
		new_wp.date = old_wp.date;
		new_wp.address.srose_addr     = old_wp.address.srose_addr;
		new_wp.address.srose_call     = old_wp.address.srose_call;
		new_wp.address.srose_digis[0] = old_wp.address.srose_digi;
		new_wp.address.srose_ndigis   = old_wp.address.srose_ndigis;

		wp_set(&new_wp);
	}

	wp_close();

	return(0);
}
Exemplo n.º 9
0
static void PrintPortEntry(struct PortRecord *pr, int data)
{
	char lh[30], fh[30], *call, *s;
	char buffer[80];
	int i;

	switch (data) {
		case 0:
			strcpy(lh, ctime(&pr->entry.last_heard));
			lh[19] = 0;
			call =  ax25_ntoa(&pr->entry.from_call);
			if ((s = strstr(call, "-0")) != NULL)
				*s = '\0';
			printf("%-10s %-5s %5d   %s\n",
				call, pr->entry.portname, pr->entry.count, lh);
			break;
		case 1:
			buffer[0] = '\0';
			call = ax25_ntoa(&pr->entry.from_call);
			if ((s = strstr(call, "-0")) != NULL)
				*s = '\0';
			strcat(buffer, call);
			call = ax25_ntoa(&pr->entry.to_call);
			if ((s = strstr(call, "-0")) != NULL)
				*s = '\0';
			strcat(buffer, ">");
			strcat(buffer, call);
			for (i = 0; i < pr->entry.ndigis && i < 4; i++) {
				strcat(buffer, ",");
				call = ax25_ntoa(&pr->entry.digis[i]);
				if ((s = strstr(call, "-0")) != NULL)
					*s = '\0';
				strcat(buffer, call);
			}
			if (pr->entry.ndigis >= 4)
				strcat(buffer, ",...");
			printf("%-70s %-5s\n",
				buffer, pr->entry.portname);
			break;
		case 2:
			strcpy(lh, ctime(&pr->entry.last_heard));
			lh[19] = 0;
			strcpy(fh, ctime(&pr->entry.first_heard));
			fh[19] = 0;
			call = ax25_ntoa(&pr->entry.from_call);
			if ((s = strstr(call, "-0")) != NULL)
				*s = '\0';
			printf("%-10s %-5s %5d %5d %5d  %s  %s\n",
				call, pr->entry.portname, pr->entry.iframes, pr->entry.sframes, pr->entry.uframes, fh, lh);
			break;
		case 3:
			call = ax25_ntoa(&pr->entry.from_call);
			if ((s = strstr(call, "-0")) != NULL)
				*s = '\0';
			printf("%-10s %-5s %5d %5s ",
				call, pr->entry.portname, pr->entry.count, types[pr->entry.type]);
			if (pr->entry.mode & MHEARD_MODE_ARP)
				printf(" ARP");
			if (pr->entry.mode & MHEARD_MODE_FLEXNET)
				printf(" FlexNet");
			if (pr->entry.mode & MHEARD_MODE_IP_DG)
				printf(" IP-DG");
			if (pr->entry.mode & MHEARD_MODE_IP_VC)
				printf(" IP-VC");
			if (pr->entry.mode & MHEARD_MODE_NETROM)
				printf(" NET/ROM");
			if (pr->entry.mode & MHEARD_MODE_ROSE)
				printf(" Rose");
			if (pr->entry.mode & MHEARD_MODE_SEGMENT)
				printf(" Segment");
			if (pr->entry.mode & MHEARD_MODE_TEXNET)
				printf(" TexNet");
			if (pr->entry.mode & MHEARD_MODE_TEXT)
				printf(" Text");
			if (pr->entry.mode & MHEARD_MODE_PSATFT)
				printf(" PacsatFT");
			if (pr->entry.mode & MHEARD_MODE_PSATPB)
				printf(" PacsatPB");
			if (pr->entry.mode & MHEARD_MODE_UNKNOWN)
				printf(" Unknown");
			printf("\n");
			break;
	}
}
Exemplo n.º 10
0
int main(int argc, char **argv)
{
	unsigned char buffer[512], *addr, *p;
	char rose_address[11];
	fd_set read_fd;
	int n, s, dnicindex = -1, addrindex = -1;
	int yes = 1, verbose = 1;
	socklen_t addrlen;
	struct sockaddr_rose rosebind, roseconnect;
	struct full_sockaddr_ax25 ax25sock, ax25peer;

	openlog("rsuplnk", LOG_PID, LOG_DAEMON);

	/*
	 * Arguments should be "rsuplnk [-q] roseport"
	 */
	if (argc > 2 && strcmp(argv[1], "-q") == 0) {
		verbose = 0;
		--argc;
		++argv;
	}

	if (argc != 2) {
		syslog(LOG_ERR, "invalid number of parameters\n");
		closelog();
		return 1;
	}

	if (rs_config_load_ports() == 0) {
		syslog(LOG_ERR, "problem with rsports file\n");
		closelog();
		return 1;
	}

	addrlen = sizeof(struct full_sockaddr_ax25);

	if (getsockname(STDIN_FILENO, (struct sockaddr *)&ax25sock, &addrlen) == -1) {
		syslog(LOG_ERR, "cannot getsockname, %s\n", strerror(errno));
		closelog();
		return 1;
	}

	addrlen = sizeof(struct full_sockaddr_ax25);

	if (getpeername(STDIN_FILENO, (struct sockaddr *)&ax25peer, &addrlen) == -1) {
		syslog(LOG_ERR, "cannot getpeername, %s\n", strerror(errno));
		closelog();
		return 1;
	}
#ifdef HAVE_AX25_PIDINCL
	if (setsockopt(STDIN_FILENO, SOL_AX25, AX25_PIDINCL, &yes, sizeof(yes)) == -1) {
		syslog(LOG_ERR, "cannot setsockopt(AX25_PIDINCL) - %s\n", strerror(errno));
		closelog();
		return 1;
	}
#endif /* HAVE_AX25_PIDINCL */
	roseconnect.srose_family = rosebind.srose_family = AF_ROSE;
	roseconnect.srose_ndigis = rosebind.srose_ndigis = 0;
	addrlen = sizeof(struct sockaddr_rose);

	if ((addr = rs_config_get_addr(argv[1])) == NULL) {
		syslog(LOG_ERR, "invalid Rose port name - %s\n", argv[1]);
		closelog();
		return 1;
	}

	if (rose_aton(addr, rosebind.srose_addr.rose_addr) == -1) {
		syslog(LOG_ERR, "invalid ROSE port address - %s\n", argv[1]);
		closelog();
		return 1;
	}

	/*
	 *	Copy our DNIC in as default.
	 */
	memset(rose_address, 0x00, 11);
	memcpy(rose_address, addr, 4);

	for (n = 0; n < ax25peer.fsa_ax25.sax25_ndigis; n++) {
		addr = ax25_ntoa(&ax25peer.fsa_digipeater[n]);
		
		if (strspn(addr, "0123456789-") == strlen(addr)) {
			if ((p = strchr(addr, '-')) != NULL)
				*p = '\0';
			switch (strlen(addr)) {
				case 4:
					memcpy(rose_address + 0, addr, 4);
					dnicindex = n;
					break;
				case 6:
					memcpy(rose_address + 4, addr, 6);
					addrindex = n;
					break;
				default:
					break;
			}
		}
	}

	/*
	 *	The user didn't give an address.
	 */
	if (addrindex == -1) {
		strcpy(buffer, "*** No ROSE address given\r");
		write(STDOUT_FILENO, buffer, strlen(buffer));
		sleep(20);
		closelog();
		return 1;
	}

	if (rose_aton(rose_address, roseconnect.srose_addr.rose_addr) == -1) {
		syslog(LOG_ERR, "invalid Rose address - %s\n", argv[4]);
		closelog();
		return 1;
	}

	rosebind.srose_call    = ax25peer.fsa_ax25.sax25_call;

	roseconnect.srose_call = ax25sock.fsa_ax25.sax25_call;

	/*
	 *	A far end digipeater was specified.
	 */
	if (addrindex > 0) {
		roseconnect.srose_ndigis = 1;
		roseconnect.srose_digi   = ax25peer.fsa_digipeater[addrindex - 1];
	}

	/*
	 *	Check for a local digipeater.
	 */
	if (dnicindex != -1) {
		if (ax25peer.fsa_ax25.sax25_ndigis - dnicindex > 2) {
			rosebind.srose_ndigis = 1;
			rosebind.srose_digi   = ax25peer.fsa_digipeater[dnicindex + 2];
		}
	} else {
		if (ax25peer.fsa_ax25.sax25_ndigis - addrindex > 2) {
			rosebind.srose_ndigis = 1;
			rosebind.srose_digi   = ax25peer.fsa_digipeater[addrindex + 2];
		}
	}

	/*
	 * Open the socket into the kernel.
	 */
	if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) {
		syslog(LOG_ERR, "cannot open ROSE socket, %s\n", strerror(errno));
		closelog();
		return 1;
	}

	/*
	 * Set our AX.25 callsign and Rose address accordingly.
	 */
	if (bind(s, (struct sockaddr *)&rosebind, addrlen) != 0) {
		syslog(LOG_ERR, "cannot bind ROSE socket, %s\n", strerror(errno));
		closelog();
		close(s);
		return 1;
	}

	if (setsockopt(s, SOL_ROSE, ROSE_QBITINCL, &yes, sizeof(yes)) == -1) {
		syslog(LOG_ERR, "cannot setsockopt(ROSE_QBITINCL) - %s\n", strerror(errno));
		closelog();
		close(s);
		return 1;
	}

	if (verbose) {
		strcpy(buffer, "*** Connection in progress\r");
		write(STDOUT_FILENO, buffer, strlen(buffer));
	}

	/*
	 * If no response in 5 minutes, go away.
	 */
	alarm(300);

	signal(SIGALRM, alarm_handler);

	/*
	 * Lets try and connect to the far end.
	 */
	if (connect(s, (struct sockaddr *)&roseconnect, addrlen) != 0) {
		switch (errno) {
			case ECONNREFUSED:
				strcpy(buffer, "*** Disconnected - 0100 - Number Busy\r");
				break;
			case ENETUNREACH:
				strcpy(buffer, "*** Disconnected - 0D00 - Not Obtainable\r");
				break;
			case EINTR:
				strcpy(buffer, "*** Disconnected - 3900 - Ship Absent\r");
				break;
			default:
				sprintf(buffer, "*** Disconnected - %d - %s\r", errno, strerror(errno));
				break;
		}

		close(s);

		if (verbose) {
			write(STDOUT_FILENO, buffer, strlen(buffer));
			sleep(20);
		}

		return 0;
	}

	/*
	 * We got there.
	 */
	alarm(0);

	if (verbose) {
		strcpy(buffer, "*** Connected\r");
		write(STDOUT_FILENO, buffer, strlen(buffer));
	}

	/*
	 * Loop until one end of the connection goes away.
	 */
	for (;;) {
		FD_ZERO(&read_fd);
		FD_SET(STDIN_FILENO, &read_fd);
		FD_SET(s, &read_fd);
		
		select(s + 1, &read_fd, NULL, NULL, NULL);

		if (FD_ISSET(s, &read_fd)) {
			if ((n = read(s, buffer, 512)) == -1) {
				strcpy(buffer, "\r*** Disconnected - 0000 - DTE Originated\r");
				write(STDOUT_FILENO, buffer, strlen(buffer));
				break;
			}
			if (buffer[0] == 0) {		/* Q Bit not set */
				buffer[0] = 0xF0;
				write(STDOUT_FILENO, buffer, n);
			} else {
				/* Lose the leading 0x7F */
				write(STDOUT_FILENO, buffer + 2, n - 2);
			}
		}

		if (FD_ISSET(STDIN_FILENO, &read_fd)) {
			if ((n = read(STDIN_FILENO, buffer + 2, sizeof(buffer)-2)) == -1) {
				close(s);
				break;
			}
			if (buffer[2] == 0xF0) {
				buffer[2] = 0;
				write(s, buffer + 2, n);
			} else {
				buffer[0] = 1;		/* Set Q bit on */
				buffer[1] = 0x7F;	/* PID Escape   */
				write(s, buffer, n + 2);
			}
		}
	}

	closelog();

	return 0;
}
Exemplo n.º 11
0
int nr_config_load_ports(void)
{
	FILE *fp = NULL;
	char buffer[256], *s;
	int fd = -1, lineno = 1, n = 0, i;
	const char **calllist = NULL;
	const char **devlist  = NULL;
	const char **pp;
	int callcount = 0;
	struct ifreq ifr;

	/* Reliable listing of all network ports on Linux
	   is only available via reading  /proc/net/dev ...  */


	if ((fd = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) {
	  fprintf(stderr, "nrconfig: unable to open socket (%s)\n", strerror(errno));
	  goto cleanup;
	}

	if ((fp = fopen("/proc/net/dev", "r"))) {
	  /* Two header lines.. */
	  s = fgets(buffer, sizeof(buffer), fp);
	  s = fgets(buffer, sizeof(buffer), fp);
	  /* .. then network interface names */
	  while (!feof(fp)) {
	    if (!fgets(buffer, sizeof(buffer), fp))
	      break;
	    s = strchr(buffer, ':');
	    if (s) *s = 0;
	    s = buffer;
	    while (isspace(*s & 0xff)) ++s;

	    memset(&ifr, 0, sizeof(ifr));
	    strncpy(ifr.ifr_name, s, IFNAMSIZ-1);        
	    ifr.ifr_name[IFNAMSIZ-1] = 0;

	    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
	      fprintf(stderr, "nrconfig: SIOCGIFHWADDR: %s\n", strerror(errno));
	      return FALSE;
	    }

	    if (ifr.ifr_hwaddr.sa_family != ARPHRD_NETROM)
	      continue;

	    /* store found interface callsigns */
	    /* ax25_ntoa() returns pointer to static buffer */
	    s = ax25_ntoa((void*)ifr.ifr_hwaddr.sa_data);

	    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
	      fprintf(stderr, "nrconfig: SIOCGIFFLAGS: %s\n", strerror(errno));
	      return FALSE;
	    }

	    if (!(ifr.ifr_flags & IFF_UP))
	      continue;


            if ((pp = realloc(calllist, sizeof(char *) * (callcount+2))) == 0)
              break;
            calllist = pp;
            if ((pp = realloc(devlist,  sizeof(char *) * (callcount+2))) == 0)
              break;
            devlist  = pp;
            if ((calllist[callcount] = strdup(s)) != NULL) {
              if ((devlist[callcount] = strdup(ifr.ifr_name)) != NULL) {
                ++callcount;
                calllist[callcount] = NULL;
                devlist [callcount] = NULL;
              } else {
                free((void*)calllist[callcount]);
                calllist[callcount] = NULL;
		devlist[callcount] = NULL;
              }
            }
	  }
	  fclose(fp);
	  fp = NULL;
	}


	if ((fp = fopen(CONF_NRPORTS_FILE, "r")) == NULL) {
	  fprintf(stderr, "nrconfig: unable to open nrports file %s (%s)\n", CONF_NRPORTS_FILE, strerror(errno));
	  goto cleanup;
	}

	while (fp && fgets(buffer, 255, fp)) {
	  if ((s = strchr(buffer, '\n')))
	    *s = '\0';

	  if (strlen(buffer) > 0 && *buffer != '#')
	    if (nr_config_init_port(fd, lineno, buffer, calllist, devlist))
	      n++;

	  lineno++;
	}

 cleanup:;
	if (fd >= 0) close(fd);
	if (fp) fclose(fp);

	for(i = 0; calllist && calllist[i]; ++i) {
	  free((void*)calllist[i]);
	  if (devlist[i] != NULL)
	    free((void*)devlist[i]);
	}
	if (calllist) free(calllist);
	if (devlist) free(devlist);

	if (nr_ports == NULL)
		return 0;

	return n;
}
Exemplo n.º 12
0
int main (int argc, char **argv)
{
	char call[20];
	char buf[2048];
	int i, k, cnt, digits, letters, invalid, ssid, ssidcnt;
	unsigned int addrlen;
	int fdmaster;
	int identify = TRUE;
	pid_t pid = -1;
	fd_set fds_read;
	int chargc;
	char *chargv[20];
	int envc;
	char *envp[20];
	struct winsize win = {24, 80, 0, 0};
	union
	{
		struct full_sockaddr_ax25 fsax25;
		struct full_sockaddr_rose rose;
	}
	sockaddr;
	char *protocol;
	cfg_t cfg;

	if ((argc > 1) && (strcmp(argv[1], "-n") == 0))
	{
		identify = FALSE;
		--argc;
		++argv;
	}
		
	digits = letters = invalid = ssid = ssidcnt = 0;

	openlog ("fpacshell", LOG_PID, LOG_DAEMON);

	addrlen = sizeof (struct full_sockaddr_ax25);

	memset(&sockaddr.rose, 0x00, sizeof(struct full_sockaddr_rose));

	k = getpeername (0, (struct sockaddr *) &sockaddr, &addrlen);

	if (k == 0)
	{
	switch (sockaddr.fsax25.fsa_ax25.sax25_family)
	{
	case AF_AX25:
		strcpy (call, ax25_ntoa (&sockaddr.fsax25.fsa_ax25.sax25_call));
		protocol = "AX.25";
		paclen = AX_PACLEN;
		break;

	case AF_NETROM:
		strcpy (call, ax25_ntoa (&sockaddr.fsax25.fsa_ax25.sax25_call));
		protocol = "NET/ROM";
		paclen = NETROM_PACLEN;
		break;

	case AF_ROSE:
		strcpy (call, ax25_ntoa (&sockaddr.rose.srose_call));
		protocol = "Rose";
		paclen = ROSE_PACLEN;
		break;

	default:
/*		syslog (LOG_NOTICE, "peer is not an AX.25, NET/ROM or Rose socket\n"); */
		strcpy (call, "UNKNOWN");
		protocol = "SHELL";
		crlf = 0;
		paclen = AX_PACLEN;
		break;
	}
	}
	else
	{
		strcpy (call, "UNKNOWN");
		protocol = "SHELL";
		crlf = 0;
		paclen = AX_PACLEN;
	}

	/* Get FPAC configuration */
	if (cfg_open (&cfg) != 0)
	{
		write_ax25 (MSG_NOCFG, sizeof (MSG_NOCFG));
		syslog (LOG_NOTICE, "FPAC configuration file not found\n");
		sleep (EXITDELAY);
		return 1;
	}

	/* Check for MD password */
	if ((identify) && (!md_check (&cfg)))
		return 2;

	if (argc == 1)
	{
		chargc = 0;
		chargv[chargc++] = user_shell;
	}
	else
	{
/*		int i;*/
		for (i = 0 ; i < (argc-1) ; i++)
		{
			if (i == 20)
				break;
			chargv[i] = argv[i+1];
		}
		chargc = argc-1;
	}
	chargv[chargc] = NULL;

	envc = 0;
	envp[envc] = (char *) malloc (30);
	sprintf (envp[envc++], "AXCALL=%s", call);
	envp[envc] = (char *) malloc (30);
	sprintf (envp[envc++], "PROTOCOL=%s", protocol);
		/* envp[envc] = (char *) malloc (30);
		sprintf (envp[envc++], "TERM=linux"); */
	envp[envc] = NULL;

	fdmaster = pty_open(&pid, &win, chargv, envp);

	if (fdmaster == -1)
		return 4;
		
	if (pid != -1)
	{
		child_pid = 0;
		signal (SIGHUP, signal_handler);
		signal (SIGTERM, signal_handler);
		signal (SIGINT, signal_handler);
		signal (SIGQUIT, signal_handler);

		while (1)
		{
			FD_ZERO (&fds_read);
			FD_SET (0, &fds_read);
			FD_SET (fdmaster, &fds_read);

			k = select (fdmaster + 1, &fds_read, NULL, NULL, NULL);

			if (k > 0)
			{
				if (FD_ISSET (0, &fds_read))
				{
					cnt = read_ax25 (buf, sizeof (buf));
					if (cnt < 0)	/* Connection died */
					{
						break;
					}
					else
						write (fdmaster, buf, cnt);
				}

				if (FD_ISSET (fdmaster, &fds_read))
				{
					cnt = read (fdmaster, buf, sizeof (buf));
					if (cnt < 0)
					{
						break;
					}
					write_ax25 (buf, cnt);
				}
			}
			else if (k < 0 && errno != EINTR)
			{
				break;
			}
		}
	}
	else
	{
		syslog (LOG_ERR, "cannot fork %m, closing connection to %s\n", call);
		write_ax25 (MSG_CANNOTFORK, sizeof (MSG_CANNOTFORK));
		sleep (EXITDELAY);
		return 1;
	}

	sleep (EXITDELAY);

	return 0;
}