From 9efe64fc3380544cc1665753c85cd27031474224 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Fri, 26 Jun 2020 18:15:07 +0800 Subject: [PATCH] Add comport program --- apue/5.Comport/comport.h | 106 ++++++ apue/5.Comport/comport_main.c | 269 +++++++++++++++ apue/5.Comport/comport.c | 578 ++++++++++++++++++++++++++++++++++ apue/5.Comport/makefile | 13 4 files changed, 966 insertions(+), 0 deletions(-) diff --git a/apue/5.Comport/comport.c b/apue/5.Comport/comport.c new file mode 100644 index 0000000..b541f04 --- /dev/null +++ b/apue/5.Comport/comport.c @@ -0,0 +1,578 @@ +/* ******************************************************************************** + * Copyright: (C) 2018 LingYun IoT System Studio + * All rights reserved. + * + * Filename: cp_comport.c + * Description: It's the comport operate library. + * + * Version: 2.0.0(10/17/2018~) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "10/17/2018 03:33:25 PM" + * + ********************************************************************************/ + +#include "comport.h" + +#ifdef COM_DEBUG +void disp_settings(comport_t *comport); +#endif + +void set_settings(comport_t * comport, const char *settings); + +/************************************************************************************** + * Description: Set the comport structure + * Input Args: dev_name: The comport device name path, such as '/dev/ttyS3' + * baudrate: The baudrate, such as 115200 + * settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N' + * Output Args: NONE + * Return Value: The comport_t structure pointer. + *************************************************************************************/ +comport_t *comport_init(const char *dev_name, int baudrate, const char *settings) +{ + comport_t *comport = NULL; + if (NULL == (comport = (comport_t *) malloc(sizeof(comport_t)))) + { + return NULL; + } + memset(comport, 0, sizeof(comport_t)); + comport->frag_size = 128; + + strncpy(comport->dev_name, dev_name, DEVNAME_LEN); + comport->baudrate = baudrate; + + set_settings(comport, settings); +#ifdef COM_DEBUG + disp_settings(comport); +#endif + + return comport; +} + +#ifdef COM_DEBUG +void disp_settings(comport_t *comport) +{ + COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name); + COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate); + COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit); + + switch (comport->parity) + { + case 0: + COM_PRINT("Parity:\t\t\t\'N\'\n"); + break; + case 1: + COM_PRINT("Parity:\t\t\t\'O\'\n"); + break; + case 2: + COM_PRINT("Parity:\t\t\t\'E\'\n"); + break; + case 3: + COM_PRINT("Parity:\t\t\t\'S\'\n"); + break; + } + COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit); + switch (comport->flowctrl) + { + case 0: + COM_PRINT("FlowCtrl:\t\t\'N\'\n"); + break; + case 1: + COM_PRINT("FlowCtrl:\t\t\'S\'\n"); + break; + case 2: + COM_PRINT("FlowCtrl:\t\t\'H\'\n"); + break; + case 3: + COM_PRINT("FlowCtrl:\t\t\'B\'\n"); + break; + } + COM_PRINT("\n"); + return; +} +#endif + +/************************************************************************************** + * Description: Set the comport databit,parity,stopbit,flowctrl into the comport structure + * Input Args: comport: the comport_t pointer + * settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" + * Output Args: NONE + * Return Value: NONE + *************************************************************************************/ +void set_settings(comport_t * comport, const char *settings) +{ + if(NULL==settings || NULL==comport) + return ; + + switch (settings[0]) /* data bit */ + { + case '7': + comport->databit = 7; + break; + case '8': + default: + comport->databit = 8; + break; + } + + switch (settings[1]) /* parity */ + { + case 'O': + case 'o': + comport->parity = 1; + break; + case 'E': + case 'e': + comport->parity = 2; + break; + case 'S': + case 's': + comport->parity = 3; + break; + case 'N': + case 'n': + default: + comport->parity = 0; + break; + } + + switch (settings[2]) /* stop bit */ + { + case '0': + comport->stopbit = 0; + break; + case '1': + default: + comport->stopbit = 1; + break; + } + + switch (settings[3]) /* flow control */ + { + case 'S': + case 's': + comport->flowctrl = 1; + break; + case 'H': + case 'h': + comport->flowctrl = 2; + break; + case 'B': + case 'b': + comport->flowctrl = 3; + break; + case 'N': + case 'n': + default: + comport->flowctrl = 0; + break; + } +} + +void comport_close(comport_t * comport) +{ + if (0 != comport->fd) + { + COM_PRINT("Close device \"%s\"\n", comport->dev_name); + close(comport->fd); + } + + comport->fd = -1; +} + +void comport_term(comport_t * comport) +{ + if(NULL == comport) + return; + + if ( comport->fd > 0 ) + { + comport_close(comport); + } + + memset(comport, 0x00, sizeof(comport_t)); + free(comport); + + return; +} + +int comport_open(comport_t * comport) +{ + int retval = -1; + struct termios old_cfg, new_cfg; + int old_flags; + long tmp; + + if(NULL==comport) + return -1; + + comport_close(comport); + + /* Not a TTY device */ + if( !strstr(comport->dev_name, "tty")) + { + COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name); + comport->fd = open(comport->dev_name, O_RDWR); + retval = comport->fd<0 ? -2 : comport->fd; + goto CleanUp; + } + + comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (comport->fd < 0) + { + retval = -3; + goto CleanUp; + } + COM_PRINT("Open device \"%s\"\n", comport->dev_name); + + if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0))) + && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK))) + { + // Flush input and output + if (-1 == tcflush(comport->fd, TCIOFLUSH)) + { + retval = -4; + goto CleanUp; + } + } + else // Failure + { + retval = -5; + goto CleanUp; + } + + if (0 != tcgetattr(comport->fd, &old_cfg)) + { + retval = -6; // Failed to get Com settings + goto CleanUp; + } + + memset(&new_cfg, 0, sizeof(new_cfg)); + + /*=====================================*/ + /* Configure comport */ + /*=====================================*/ + + new_cfg.c_cflag &= ~CSIZE; + new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + new_cfg.c_oflag &= ~(OPOST); + + /* Set the data bit */ + switch (comport->databit) + { + case 0x07: + new_cfg.c_cflag |= CS7; + break; + case 0x06: + new_cfg.c_cflag |= CS6; + break; + case 0x05: + new_cfg.c_cflag |= CS5; + break; + default: + new_cfg.c_cflag |= CS8; + break; + } + + /* Set the parity */ + switch (comport->parity) + { + case 0x01: // Odd + new_cfg.c_cflag |= (PARENB | PARODD); + new_cfg.c_cflag |= (INPCK | ISTRIP); + break; + case 0x02: // Even + new_cfg.c_cflag |= PARENB; + new_cfg.c_cflag &= ~PARODD;; + new_cfg.c_cflag |= (INPCK | ISTRIP); + break; + case 0x03: + new_cfg.c_cflag &= ~PARENB; + new_cfg.c_cflag &= ~CSTOPB; + break; + default: + new_cfg.c_cflag &= ~PARENB; + } + + /* Set Stop bit */ + if (0x01 != comport->stopbit) + { + new_cfg.c_cflag |= CSTOPB; + } + else + { + new_cfg.c_cflag &= ~CSTOPB; + } + + /* Set flow control */ + switch (comport->flowctrl) + { + case 1: // Software control + case 3: + new_cfg.c_cflag &= ~(CRTSCTS); + new_cfg.c_iflag |= (IXON | IXOFF); + break; + case 2: // Hardware control + new_cfg.c_cflag |= CRTSCTS; // Also called CRTSCTS + new_cfg.c_iflag &= ~(IXON | IXOFF); + break; + default: // NONE + new_cfg.c_cflag &= ~(CRTSCTS); + new_cfg.c_iflag &= ~(IXON | IXOFF); + break; + } + + /* Set baudrate */ + switch (comport->baudrate) + { + case 115200: + tmp = B115200; + break; + case 57600: + tmp = B57600; + break; + case 38400: + tmp = B38400; + break; + case 19200: + tmp = B19200; + break; + case 9600: + tmp = B9600; + break; + case 4800: + tmp = B4800; + break; + case 2400: + tmp = B2400; + break; + case 1800: + tmp = B1800; + break; + case 1200: + tmp = B1200; + break; + case 600: + tmp = B600; + break; + case 300: + tmp = B300; + break; + case 200: + tmp = B200; + break; + case 150: + tmp = B150; + break; + case 134: + tmp = B134; + break; + case 110: + tmp = B110; + break; + case 75: + tmp = B75; + break; + case 50: + tmp = B50; + break; + default: + tmp = B115200; + } + cfsetispeed(&new_cfg, tmp); + cfsetispeed(&new_cfg, tmp); + + /* Set the Com port timeout settings */ + new_cfg.c_cc[VMIN] = 0; + new_cfg.c_cc[VTIME] = 0; + + tcflush(comport->fd, TCIFLUSH); + if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg)) + { + retval = -7; // Failed to set device com port settings + goto CleanUp; + } + + COM_PRINT("Connected device \"%s\".\n", comport->dev_name); + + retval = comport->fd; + +CleanUp: + COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure"); + return retval; +} + + +int comport_recv(comport_t * comport, char *buf, int buf_size, unsigned long timeout) +{ + int retval = 0; // Function return value + int iRet; + fd_set stReadFds, stExcpFds; + struct timeval stTime; + + if (NULL == buf || 0 >= buf_size) + { + COM_PRINT("%s() usage error.\n", __FUNCTION__); + retval = -1; + goto CleanUp; + } + + if ( comport->fd < 0 ) + { + COM_PRINT("%s() comport not connected.\n", __FUNCTION__); + retval = -2; + goto CleanUp; + } + + //printf("bufsize=%d timeout=%lu\n", buf_size, timeout); + + FD_ZERO(&stReadFds); + FD_ZERO(&stExcpFds); + FD_SET(comport->fd, &stReadFds); + FD_SET(comport->fd, &stExcpFds); + + if (0xFFFFFFFF != timeout) + { + stTime.tv_sec = (time_t) (timeout / 1000); + stTime.tv_usec = (long)(1000 * (timeout % 1000)); + + iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime); + if (0 == iRet) + { + retval = 0; // No data in Com port buffer + goto CleanUp; + } + else if (0 < iRet) + { + if (0 != FD_ISSET(comport->fd, &stExcpFds)) + { + retval = -6; // Error during checking recv status + COM_PRINT("Error checking recv status.\n"); + goto CleanUp; + } + + if (0 == FD_ISSET(comport->fd, &stReadFds)) + { + retval = 0; // No incoming data + COM_PRINT("No incoming data.\n"); + goto CleanUp; + } + } + else + { + if (EINTR == errno) + { + COM_PRINT("catch interrupt signal.\n"); + retval = 0; // Interrupted signal catched + } + else + { + COM_PRINT("Check recv status failure.\n"); + retval = -7; // Error during checking recv status + } + + goto CleanUp; + } + } + + usleep(10000); /* sleep for 10ms for data incoming */ + + // Get data from Com port + iRet = read(comport->fd, buf, buf_size); + if (0 > iRet) + { + if (EINTR == errno) + retval = 0; // Interrupted signal catched + else + retval = -3; // Failed to read Com port + + goto CleanUp; + } + +#if 0 + { + int i=0; + printf("Receive %d bytes data: \n", iRet); + for(i=0; i<iRet; i++) + { + printf("0x%02x ", buf[i]); + } + printf("\n"); + } +#endif + + retval = iRet; + + CleanUp: + return retval; + +} + +int comport_send(comport_t * comport, char *buf, int send_bytes) +{ + char *ptr, *end; + int retval = 0; + int send = 0; + + if (NULL == buf || 0 >= send_bytes) + { + COM_PRINT("%s() Usage error.\n", __FUNCTION__); + retval = -1; + goto CleanUp; + } + + if ( comport->fd < 0 ) // Comport not opened ? + { + retval = -3; + COM_PRINT("Serail not connected.\n"); + goto CleanUp; + } + + //printf("Send %s with %d bytes.\n", buf, send_bytes); + + // Large data, then slice them and send + if (comport->frag_size < send_bytes) + { + ptr = buf; + end = buf + send_bytes; + + do + { + // Large than frag_size + if (comport->frag_size < (end - ptr)) + { + send = write(comport->fd, ptr, comport->frag_size); + if (0 >= send || comport->frag_size != send) + { + retval = -4; + goto CleanUp; + } + ptr += comport->frag_size; + } + else // Less than frag_size, maybe last fragmention. + { + send = write(comport->fd, ptr, (end - ptr)); + if (0 >= send || (end - ptr) != send) + { + retval = -4; + goto CleanUp; + } + ptr += (end - ptr); + } + } + while (ptr < end); + } + else // The send data is not large than a fragmention. + { + send = write(comport->fd, buf, send_bytes); + if (0 >= send || send_bytes != send) + { + retval = -5; + goto CleanUp; + } + } + + CleanUp: + return retval; +} + diff --git a/apue/5.Comport/comport.h b/apue/5.Comport/comport.h new file mode 100644 index 0000000..9339836 --- /dev/null +++ b/apue/5.Comport/comport.h @@ -0,0 +1,106 @@ +/********************************************************************************* + * Copyright: (C) 2018 LingYun IoT System Studio + * All rights reserved. + * + * Filename: comport.h + * Description: This head file is for the common TTY/Serial port operator library + * + * Version: 1.0.0(10/17/2018~) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "10/17/2018 03:33:25 PM" + * + ********************************************************************************/ +#ifndef __COMPORT_H_ +#define __COMPORT_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <getopt.h> +#include <fcntl.h> +#include <errno.h> +#include <termios.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> + +#define BUF_64 64 + +#ifndef DEVNAME_LEN +#define DEVNAME_LEN 64 +#endif + +//#define COM_DEBUG +#ifdef COM_DEBUG +#define COM_PRINT(format,args...) printf(format, ##args) +#else +#define COM_PRINT(format,args...) do{} while(0); +#endif + +//#define msleep(m) {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);} + +typedef struct comport_s +{ + char dev_name[DEVNAME_LEN]; + unsigned char databit, parity, stopbit, flowctrl; + long baudrate; + + int fd; + int frag_size; +} comport_t; + +/* + * description: initialise the comport structure + * + * input args: $dev_name: The comport device name path, such as '/dev/ttyS3' + * $baudrate: The baudrate, such as 115200 + * $settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N' + * + * return value: The comport_t structure pointer, NULL means failure. + */ + +comport_t *comport_init(const char *dev_name, int baudrate, const char *settings); + + +/* + * description: Open the comport specified by $comport + * input args: $comport: corresponding comport point + * return value: The comport opened file description, <0 means failure + */ +extern int comport_open(comport_t * comport); + +/* + * description: read data from $comport in $timeout <ms> to $buf no more than $buf_size bytes + * return value: the actual read data bytes, <0: read failure + */ +extern int comport_recv(comport_t * comport, char *buf, int buf_size, unsigned long timeout); + +/* + * description: write $send_bytes bytes data from $buf to $comport + * return value: 0: write ok <0: write failure + */ +extern int comport_send(comport_t * comport, char *buf, int send_bytes); + +/* + * description: display current comport settings such as databit,parity,stopbit,flowctrl + * input args: $comport: corresponding comport point + */ +//extern void disp_settings(comport_t * comport); + +/* + * description: close comport + * input args: $comport: corresponding comport point + */ +extern void comport_close(comport_t * comport); + + +/* + * description: terminat comport, close and free it + * input args: $comport: corresponding comport point + */ +extern void comport_term(comport_t * comport); + +#endif diff --git a/apue/5.Comport/comport_main.c b/apue/5.Comport/comport_main.c new file mode 100644 index 0000000..cc127af --- /dev/null +++ b/apue/5.Comport/comport_main.c @@ -0,0 +1,269 @@ +/********************************************************************************* + * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> + * All rights reserved. + * + * Filename: comport.c + * Description: This file used to do ioctl() on common device or communicate + * with serial port/TTY device. + * + * Version: 1.0.0(10/18/2011~) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "10/18/2011 10:08:05 AM" + * + ********************************************************************************/ +#include <getopt.h> +#include <libgen.h> +#include <sys/ioctl.h> + +#include "comport.h" + +unsigned char g_ucProcToken = 0x01; +unsigned char g_ucCtrlZ; + +void print_version(char *name); +void usage(char *name); +int do_ioctl(char *dev_name, int cmd, int arg); +void signal_handler(int i_sig); +void nonblock(void); +int kbhit(void); + +int main(int argc, char **argv) +{ + int opt = 0; + int retval = 0; + int recv_size = 0; + int i; + char *dev_name = NULL; + int baudrate = 115200; + char *settings = "8N1N"; + char buf[512]; + unsigned char disp_mode = 0x00; + comport_t *comport = NULL; + + struct sigaction sigact; + + struct option long_options[] = { + {"device", required_argument, NULL, 'd'}, + {"baudrate", required_argument, NULL, 'b'}, + {"settings", required_argument, NULL, 's'}, + {"ioctl", required_argument, NULL, 'i'}, + {"hex", no_argument, NULL, 'x'}, + {"version", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + while ((opt = getopt_long(argc, argv, "d:b:s:ivh", long_options, NULL)) != -1) + { + switch (opt) + { + case 'd': + dev_name = optarg; + break; + case 'b': + baudrate = atoi(optarg); + break; + case 's': /* Default settings as 8N1N */ + settings = optarg; + break; + case 'i': + if (5 != argc) + { + usage(argv[0]); + } + else + { + do_ioctl(argv[2], atoi(argv[3]), atoi(argv[4])); + } + return 0; + case 'x': /* Display receive data as Hex mode */ + disp_mode = 0x01; + break; + case 'v': /* version */ + print_version(argv[0]); + return 0; + case 'h': /* help */ + usage(argv[0]); + return 0; + default: + break; + } /* end of "switch(opt)" */ + } + + if (argc < 2) + { + usage(argv[0]); + return 0; + } + + if (NULL == (comport = comport_init(dev_name, baudrate, settings))) + { + printf("Comport initialize failure.\n"); + return -1; + } + + if ( (retval=comport_open(comport)) < 0) + { + printf("Failed to open %s with baudrate %d, %s. RetCode [%d]\n", dev_name, baudrate, + settings, retval); + return -1; + } + + nonblock(); + + /* Process level signal handler */ + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_handler = signal_handler; + + sigaction(SIGTERM, &sigact, NULL); /* catch terminate signal */ + sigaction(SIGINT, &sigact, NULL); /* catch interrupt signal */ + sigaction(SIGSEGV, &sigact, NULL); /* catch segmentation faults */ + sigaction(SIGTSTP, &sigact, NULL); /* catch ctrl+Z */ + sigaction(SIGSTOP, &sigact, NULL); /* catch ctrl+Z */ + + while (0x01 == g_ucProcToken) + { + recv_size = comport_recv(comport, buf, sizeof(buf) - 1, 10); + if (recv_size > 0) + { + for (i = 0; i < recv_size; i++) + { + if (0 == disp_mode) + printf("%c", buf[i]); + else + printf("%02X ", buf[i]); + } + fflush(stdout); + } + if (0 != kbhit()) + { + retval = fgetc(stdin); + + if (0x0A == retval) + { + buf[0] = 0x0D; /* 13 == 0x0D */ + } + else + { + buf[0] = retval; + } + + comport_send(comport, buf, 1); + } + else if (0x00 != g_ucCtrlZ) + { + g_ucCtrlZ = 0x00; + buf[0] = 0x1A; + comport_send(comport, buf, 1); + } + } + + comport_term(comport); + return 0; +} /* ----- End of main() ----- */ + +void print_version(char *name) +{ + char *progname = NULL; + char *ptr = NULL; + + ptr = strdup(name); + progname = basename(ptr); + + printf("%s version: 1.0.0 on %s\n", progname, __DATE__); + printf("Copyright (C) 2010 guowenxue <guowenxue@gmail.com>\n"); + + free(ptr); + return; +} + +void usage(char *name) +{ + char *progname = NULL; + char *ptr = NULL; + + ptr = strdup(name); + progname = basename(ptr); + printf("Usage1: comport -d <device> [-b <baudrate>][-s <settings>] [-x]\n"); + printf("Usage2: comport [-i <driver port> <cmd> <arg>][--help][--version]\n"); + printf(" -d[device ] device name\n"); + printf(" -b[baudrate] device baudrate (115200, 57600, 19200, 9600), default is 115200\n"); + printf(" -s[settings] device settings as like 8N1N(default setting)\n"); + printf(" - data bits: 8, 7\n"); + printf(" - parity: N=None, O=Odd, E=Even, S=Space\n"); + printf(" - stop bits: 1, 0\n"); + printf(" - flow control: N=None, H=Hardware, S=Software, B=Both\n"); + printf(" -x[hex ] display received data in hex format\n"); + printf(" -i[ioctl ] ioctl system call (cmd & arg only support int)\n"); + printf(" -v[version ] Display the program version\n"); + printf(" -h[help ] Display this help information\n"); + + print_version(progname); + + free(ptr); + + return; +} + +int do_ioctl(char *dev_name, int cmd, int arg) +{ + int fd = -1; + int retval = -1; + if (((fd = open(dev_name, O_RDWR)) < 0)) + { + printf("Open device \"%s\" failure: %s\n", dev_name, strerror(errno)); + return -1; + } + + retval = ioctl(fd, cmd, arg); + printf("ioctl (%s, %d, %d) returned %d\n", dev_name, cmd, arg, retval); + + close(fd); + return retval; +} + +void signal_handler(int i_sig) +{ + if (SIGTERM == i_sig || SIGINT == i_sig) + { + g_ucProcToken = 0x00; + } + else if (20 == i_sig) + { + g_ucCtrlZ = 0x01; + } +} + +void nonblock(void) +{ + struct termios ttystate; + + //get the terminal state + tcgetattr(STDIN_FILENO, &ttystate); + + //turn off canonical mode + ttystate.c_lflag &= ~ICANON; + + //minimum of number input read. + ttystate.c_cc[VMIN] = 1; + + //set the terminal attributes. + tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); +} + + +int kbhit(void) +{ + struct timeval tv; + + fd_set fds; + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 + + select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); + + return FD_ISSET(STDIN_FILENO, &fds); +} diff --git a/apue/5.Comport/makefile b/apue/5.Comport/makefile new file mode 100644 index 0000000..0d3b690 --- /dev/null +++ b/apue/5.Comport/makefile @@ -0,0 +1,13 @@ +INST_PATH=/usr/bin + +BIN_FILES=comport + +all: clean + gcc *.c -o ${BIN_FILES} + + +clean: + rm -f ${BIN_FILES} + +install: + @cp ${BIN_FILES} ${INST_PATH} -- Gitblit v1.9.1